Skip to content

ENS Resolver

Enter a .eth name. Get the resolver contract it points to and the ETH address it resolves to, in two chained onchain reads.

Ethereumno signup · no wallet connect · free

Result

Enter an ENS name above and click "Resolve name" to see results here.

Step 1 of 2: find the resolver

registry.resolver(sel.namehash(name))

One of two onchain reads this tool sends. sel.namehash computes the ENS node from the name. Run this in your own code →

Step 2 of 2: read the address record

resolver.addr(sel.namehash(name))

The other onchain read this tool sends, reusing the same namehash. Run this in your own code →

What this tool does

The ENS Resolver takes any .eth name and resolves it to an ETH address, the same lookup a wallet does when you type a name instead of a hex address. It is built for developers and integrators who want to see exactly what onchain resolution requires: two chained reads, not one, with the ENS namehash computed entirely server-side.

Key facts

  • Resolves a .eth name to its ETH address using two chained on-chain reads: registry.resolver(namehash) on the ENS Registry, then resolver.addr(namehash) on the returned resolver contract.
  • The ENS namehash is computed entirely server-side via sel.namehash(name); no client-side keccak256 or ENS library is required.
  • Ethereum mainnet only, forward resolution (name to address) only; reverse resolution is not implemented.
  • CCIP-Read (ERC-3668) off-chain resolvers are not supported, since only on-chain reads are performed.

How to use it

  1. Enter a .eth name into the form above, for example vitalik.eth.
  2. Run the query and read the resolver contract in the result panel.
  3. Read the resolved ETH address underneath it, with a copy button for pasting it elsewhere.

If the name has no resolver set, the tool stops after the first read and tells you so. If the resolver has no ETH address record, both reads complete and the tool still shows you the resolver address it found, alongside a note that there is no address record.

What is happening under the hood

ENS resolution cannot be a single expression because the second read’s target address is only known after the first read completes:

  1. registry.resolver(sel.namehash(name)) on the ENS Registry (0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e on mainnet) returns the resolver contract for a name.
  2. resolver.addr(sel.namehash(name)) on that resolver returns the resolved ETH address.

Both calls take the same argument, sel.namehash(name), the ENS namehash of the name. sel.namehash folds the dot-separated labels of the name into the namehash algorithm’s recursive keccak256(parent + keccak256(label)) construction internally, so both requests this tool sends are just the one-liners above, with a single name context variable. No keccak256, hashing, or ENS library runs in the browser: the entire namehash computation happens inside the expression the API evaluates. The two reads shown on this page still double as a demo of evmquery handling dependent, sequential queries: step 2 needs the resolver contract address that step 1 returns, so the requests cannot be combined into one call.

Build this yourself

Both requests below are the exact shapes this tool sends for vitalik.eth. Run the first, take its result.value, and use it as the resolver contract address in the second.

Step 1: find the resolver (curl)

curl -X POST https://api.evmquery.com/api/v1/query \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chain": "evm_ethereum",
"schema": {
"contracts": { "registry": { "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" } },
"context": { "name": "string" }
},
"context": { "name": "vitalik.eth" },
"expression": "registry.resolver(sel.namehash(name))"
}'

This returns {"result":{"value":"0x231b0ee14048e9dccd1d247744d114a4eb5e8e63","type":"sol_address"}}, vitalik.eth’s real resolver.

Step 2: read the address (curl)

Same request shape, with contracts.resolver.address set to the resolver from step 1, and resolver.addr(...) in place of registry.resolver(...):

curl -X POST https://api.evmquery.com/api/v1/query \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chain": "evm_ethereum",
"schema": {
"contracts": { "resolver": { "address": "0x231b0ee14048e9dccd1d247744d114a4eb5e8e63" } },
"context": { "name": "string" }
},
"context": { "name": "vitalik.eth" },
"expression": "resolver.addr(sel.namehash(name))"
}'

This returns {"result":{"value":"0xd8da6bf26964af9d7eed9e03e53415d37aa96045","type":"sol_address"}}, vitalik.eth’s real, publicly known address.

TypeScript

const registryResp = await fetch("https://api.evmquery.com/api/v1/query", {
method: "POST",
headers: {
"x-api-key": process.env.EVMQUERY_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
chain: "evm_ethereum",
schema: {
contracts: { registry: { address: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" } },
context: { name: "string" },
},
context: { name: "vitalik.eth" },
expression: "registry.resolver(sel.namehash(name))",
}),
});
const { result: resolverResult } = await registryResp.json();
const addrResp = await fetch("https://api.evmquery.com/api/v1/query", {
method: "POST",
headers: {
"x-api-key": process.env.EVMQUERY_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
chain: "evm_ethereum",
schema: {
contracts: { resolver: { address: resolverResult.value } },
context: { name: "string" },
},
context: { name: "vitalik.eth" },
expression: "resolver.addr(sel.namehash(name))",
}),
});
const { result: addrResult } = await addrResp.json();

No manual ABI is needed for either call. resolver(bytes32) and addr(bytes32) are common enough selectors that evmquery’s ABI-less discovery resolves them automatically. The free tier has no monthly cap. Get a free API key to drop these snippets into your project.

When you would use this

  • Resolving user input. Let people type a name instead of a 42-character hex address anywhere your app accepts a recipient, a lookup target, or a profile link.
  • Verifying a name before sending funds. Confirm what an ENS name actually resolves to right now, since resolver records can change.
  • Learning how ENS resolution really works. See both onchain reads and the exact namehash expression that produces the node argument, instead of a black-box .eth to address conversion.
  • Prototyping ENS support without adding viem or ethers. No client-side keccak256 or namehash library is needed to compute the ENS node; an app that already talks to evmquery can send the name as-is and let sel.namehash compute it server-side.

FAQ

Why does this tool make two onchain reads instead of one?

ENS resolution is inherently two steps. The ENS Registry only stores which resolver contract is responsible for a name, not the address itself. The resolved address lives on that resolver contract, whose address is only known after the first read, so a second read is required. This tool shows both reads and their results rather than hiding the chain behind a single call.

Which chains and names does this support?

Ethereum mainnet only, resolving .eth names to their ETH address record. The ENS Registry is canonical on mainnet, so this tool does not attempt cross-chain ENS lookups.

Can I look up which name an address owns?

No. This tool only does forward resolution, name to address. Reverse resolution, address to name, uses a separate ENS mechanism and is not implemented here.

What about off-chain or CCIP-Read resolvers?

Not supported. Some resolvers use CCIP-Read (ERC-3668) to fetch records from an off-chain gateway. SEL only performs onchain reads, so names that depend on an off-chain resolver will not resolve through this tool.

Limits and accuracy

  • Built and tested against mainnet .eth names. Other ENS-compatible TLDs use the same namehash algorithm and will run through this tool, but they aren’t the focus and aren’t verified here. No L2 ENS deployments.
  • Forward resolution only. No reverse resolution (address to name).
  • ENSIP-10 wildcard resolution, where a parent name’s resolver handles subnames that have no resolver of their own, is not distinguished from a genuinely unset resolver. Both currently surface as “no resolver set.”
  • The result reflects the latest block at the time of the read. There is no historical replay.
  • The demo is rate limited per browser. If you hit the limit, grab a free API key and the limit goes away.

No CCIP-Read or off-chain resolver support. SEL cannot perform off-chain lookups, so names that rely on a gateway will fail here even though a wallet with CCIP-Read support would resolve them.

Run this query in your own code

No monthly cap on the free tier. No credit card needed.