ENSWhois.com: An API-First Data Layer for ENS

ENS data is distributed across 20+ smart contracts, with state and history spanning back to 2017. Accessing and reconstructing this data reliably requires significant domain knowledge and non-trivial indexing.

I’ve built a distributed indexing solution that continuously syncs ENS data, processes it into a structured form, and exposes it via a RESTful API.

The API enables querying across:

  • Ownership (current and historical)
  • Resolver and text records
  • Reverse records
  • Full domain history
  • Names by address, TLD, namehash or labelhash

The blog post linked below goes into more depth about what the product does, and how it works:


ENSWhois

ENSWhois.com is a frontend built on top of this API.

It acts as both:

  • a user-facing product for exploring ENS data
  • a reference implementation demonstrating what becomes possible with a complete ENS data layer

Supplementary Links

The following supplementary links hopefully answer some of the more obvious questions:


API First

I believe that an API-first approach is crucial for the continued success of the Ethereum Name Service.

Today, integrating ENS often requires:

  • direct interaction with multiple contracts
  • reconstructing historical state from events
  • deep protocol-specific knowledge

This creates a barrier to growth - if it is hard to use ENS, people simply won’t do so.

An indexed, queryable data layer removes that complexity and enables:

  • faster integrations
  • new product surfaces
  • broader adoption beyond crypto-native developers

This direction has been shaped through conversations with companies in the DNS space that, in principle, want to use ENS, but are currently blocked by complexity.

Feedback

I would be very interested to hear people’s opinions on this and how it can be iterated and improved upon. :folded_hands:

If you are considering an integration, I would be happy to support - I am interested to learn how consumers utilize this.


Screenshots

:link: https://enswhois.com/name/vitalik.eth/events
:link: (API) https://api.enswhois.com/domain/vitalik.eth/events


:link: https://enswhois.com/name/com/subdomains
:link: (API) https://api.enswhois.com/domain/com/subdomains?page=1


:link: https://enswhois.com/labelhash/0x6fd43e7cffc31bb581d7421c8698e29aa2bd8e7186a394b85299908b4eb9b175
:link: (API) https://api.enswhois.com/lookup-labelhash/0x6fd43e7cffc31bb581d7421c8698e29aa2bd8e7186a394b85299908b4eb9b175


:link: https://enswhois.com/name/test.eth
:link: (API) https://api.enswhois.com/domain/test.eth/ownership-history


:link: https://status.enswhois.com/indexers


13 Likes

I have been thinking further about how ENS names become agents, and concluded that the pattern utilized by ENS8004.xyz (see Turning ENS Names into Discoverable AI Agents) should be the canonical methodology.

All the relevant information for surfacing that an ENS name is an agent is available on-chain. That said, in the interest of making integration of an ENS names’ status as an agent as simple as possible I have added support for it to the ENSWhois.com API.

Integration guidance is outlined here: Integrating ENS Agents | ENSWhois Docs

A single API call to the /domain/:name/agent endpoint will indicate its registration status.

This API is consumed by the ENSWhois product itself to produce new tooling such as the ENS Agents Directory: ENS Agents Directory | ENSWhois.com

A complete agent setup would include the registration of the ENS name in the Adapter8004 adapter contract AND specification of appropriate ENSIP-26 records AND specification of the ENSIP-25 agent-registration text record.

The directory allows you to filter agents based on the specification of these values.

Additionally ENS names that are agents will display a notification indicating this on the individual domain page.

Feedback welcomed.

2 Likes

Thanks @clowes.eth — really like the /domain/:name/agent endpoint. I tried it against my agent and wanted to sanity-check whether what I’m seeing is index lag, a key-format thing, or an expected missing step on my end.

emilemarcelagustin.eth (namehash 0xc0b72aaf8988b13cd7c462503ef0370708e231fcd48a86b057abf85c863b5712)

GET api.enswhois.com/domain/emilemarcelagustin.eth/agent returns my ENSIP-26 profile fine (context + endpoint), but registrations: [].

On-chain it is registered though — ERC-8004 #24994 in the Base registry 0x8004A169…a432 (chain 8453), and ownerOf(24994) matches the name’s owner. The ENS text records are:

agent-ids                                          = ["24994"]
agent-registration[0x0001…2105…8004a169…][24994]   = "1"      ← per-registry, ERC-7930 encoded
agent-registration                                 = (null)   ← bare key not set
agent-context                                       = "Trust Resolution Layer agent…"

So my registration lives under the per-registry ERC-7930 bracketed key rather than a bare agent-registration, and I registered directly into the 8004 registry rather than going through the Adapter8004 contract.

Question: does your indexer’s registrations reader (a) parse the bracketed agent-registration[<erc7930>][<id>] keys, or (b) key specifically off the Adapter8004 binding / a bare agent-registration key?

If it’s (a), this might just be a re-crawl; if it’s (b), I’ll bind through ENS8004.xyz / Adapter8004 to show up. Happy to share the resolver if useful — we read it via an agent-ids index since ENS has no text-record enumeration, so curious how you’re discovering the bracketed keys on your side.

Thanks for playing with this Marcus, and feeding back.

So, at the moment the API considers only names bound through Adapter8004 ‘agents’, the main reason being the fact that it binds the name to the agent.

For the API to surface the registration, it would need to be registered through the adapter contract either through ENS8004.xyz or manually.

Additionally, for now we only index the adapter contract on Ethereum Mainnet.

We have a full backend indexer that tracks TextChanged events.

Off-chain records are not easily discoverable. I would like to see:

function supportedTextKeys(bytes32 node) external view returns (string[] memory);

standardized to match supportedDataKeys which we defined in ENSIP-24.

So as not to bloat the thread, happy to continue this discussion directly or through the ENS x AI channel.

1 Like

I was asked recently by @netto.eth to help him debug an issue with primary names not being displayed correctly on Etherscan. Ultimately I ended up building a new tool for ENSWhois - Primary Name Debugger | ENSWhois.com

The tool allows you to enter an address and discern if the appropriate forward and reverse records have been set for spec compliant primary name resolution.

The tool gives consideration to both ENSIP-3 and ENSIP-19.

This is a first pass - there is a lot of nuance to backwards compatibility of reverse resolution specifications especially considering ENSIP-19 and cases where forward resolution uses custom resolvers (often also going off-chain). Any feedback is welcomed.

Etherscan Issue

The specific example I was debugging is the primary name resolution of the address 0xd2f7497bfe2daff1a69f306036a036abc8154aeb which is correctly setup (backward tx, forward tx) as ens.relayer.blockful.eth.

Etherscan does not display the primary name on the associated address page. My best guess is that they run their own indexer for primary name resolution and do not respect the default cointype - 0x80000000 (2147483648).

Assuming my hunch is correct, for the time being, the simplest solution to have your primary name display correctly would be to explicitly set the chain-specific forward resolution for your name (rather than taking advantage of the EVM chain default). Ethereum Mainnet is cointype 60.

Source

Pinging @mely.eth @gregskril - it may be worth reaching out to Etherscan regarding this. I am going to iterate on this further when I have time and could offer a stable API endpoint to support future integrations.

4 Likes

Thanks for the ping.

Yes this is correct.

Etherscan uses internal indexing for everything instead of external APIs/doing resolution on the fly, so unfortunately this won’t work for them. But Labs is in touch with Etherscan about v2 and various other things, so we’ll try to improve primary name implementation as part of that.

1 Like