ENS Resolver — Name to Address, Reverse Lookup, Avatar
Pricing
from $1.40 / 1,000 result items
ENS Resolver — Name to Address, Reverse Lookup, Avatar
Resolve Ethereum Name Service names to addresses and addresses to primary ENS names, with avatar, text records (email, url, twitter, github, description) and content hash. Bulk. Built for agent identity checks. No API key.
Pricing
from $1.40 / 1,000 result items
Rating
0.0
(0)
Developer
Samat Makatov
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Resolve Ethereum Name Service names in bulk: name.eth → address, address → primary name, with avatar, social handles,
any text record, multi-chain addresses, contenthash, registration/expiry dates and on-chain events. Also lists every
name an address owns and looks names up in the ENS index by label. Built for identity checks, CRM enrichment and
domain monitoring. Uses public Ethereum RPC and the Blockscout ENS index (enstate.rs only as a fallback) — no API key,
no proxy, no browser.
Use cases
- Counterparty identity check — confirm that
acme.ethreally belongs to the wallet you are about to pay (isPrimaryName,reverse_record_mismatch). - CRM / lead enrichment — turn a list of wallet addresses into ENS names, Twitter, GitHub, website and email.
- Portfolio of names — list every ENS name owned by or pointing to your treasury address, with expiry dates.
- Renewal alerts — daily run over your brand names; flag
expires_within_30d,expired_in_grace_period. - Brand checks — is your brand registered as an ENS name, who owns it and when does it expire (
uniswap→uniswap.eth). - Cross-chain payouts — read BTC / Solana / Base / Arbitrum address records set on a name before sending funds.
Input
| Field | Type | Default | Allowed values / notes |
|---|---|---|---|
mode | string | resolve | resolve (one item per query), ownedBy (one item per name owned by / resolving to an address), search (one item per registered name: an exact lookup of the label, uniswap → uniswap.eth, not a keyword search). Apify refuses any other value before the run starts, with the list of allowed values. |
queries | string[] | — (required) | resolve: ENS names (incl. subnames, name.base.eth, name.cb.id) and/or 0x addresses. ownedBy: 0x addresses (anything else is listed in SUMMARY.errors). search: a label or a full name (uniswap, app.uniswap.eth). Duplicates are looked up (and billed) once, compared after ENS normalisation: Vitalik.ETH = vitalik.eth, an address in any letter case, uniswap = uniswap.eth in search. |
textRecords | string[] | avatar, url, email, com.twitter, com.github, description | Any text-record key, or shortcuts *standard, *services, *all (see Reference); an unknown *shortcut fails the run with a suggestion |
coinTypes | string[] | [] | Keys from the coin-type table below (any letter case) or a numeric SLIP-44 coin type. An unknown key fails the run with a suggestion and the list of valid keys. |
includeRegistration | boolean | true | Owner, registrant, wrapped owner, registration/expiry dates, days to expiry, grace period, resolver, NFT token id |
includeContenthash | boolean | true | IPFS / IPNS / Arweave / Swarm contenthash, read from the name's resolver and returned as a URI |
verifyReverse | boolean | true | For names: check the resolved address's primary name → isPrimaryName |
includeEvents | boolean | false | Recent ENS events (registration, renewals, transfers, record updates) with tx hashes |
eventsLimit | integer | 20 | 1–100 |
expiresWithinDays | integer | 30 | 0–3650; adds flag expires_within_<N>d |
lookupOwnedBy | boolean | true | ownedBy: include names owned (or wrapped-owned) by the address |
lookupResolvedTo | boolean | true | ownedBy: include names whose ETH record points to the address |
onlyActive | boolean | true | ownedBy / search: skip expired names |
maxNamesPerQuery | integer | 50 | 1–500; the index is read 100 names per page, page after page up to this cap |
fields | string[] | [] | Keep only these top-level fields, in your order. query, name, address, found, fetchedAt are always kept and come first unless you list them. Letter case is forgiven; an unknown name fails the run with a suggestion; a field that only the other mode's rows have is left out with a note. |
rpcUrls | JSON array | — | Your own Ethereum mainnet JSON-RPC URLs, tried before the public ones (optional, for large batches). A secret input: stored encrypted and never written to the log or SUMMARY, because such URLs usually carry a provider key. A malformed entry fails the run (its position is named, not its text). |
Reference
Text-record shortcuts
| Shortcut | Keys |
|---|---|
*standard | avatar, description, display, email, keywords, mail, notice, location, phone, url, header, name |
*services | com.twitter, com.github, com.discord, org.telegram, com.reddit, com.linkedin, com.youtube, io.keybase, eth.ens.delegate, com.farcaster, xyz.farcaster, com.instagram, com.warpcast, xyz.lens |
*all | both lists |
Any other key (e.g. org.discourse, snapshot) can be passed literally. Global keys are defined in ENSIP-5.
Coin types (coinTypes, ENSIP-9 / ENSIP-11)
| Key | Coin type | Chain |
|---|---|---|
btc | 0 | Bitcoin |
ltc | 2 | Litecoin |
doge | 3 | Dogecoin |
eth | 60 | Ethereum |
atom | 118 | Cosmos |
xrp | 144 | XRP |
trx | 195 | Tron |
dot | 354 | Polkadot |
sol | 501 | Solana |
bnb | 714 | BNB Beacon Chain |
optimism | 2147483658 | OP Mainnet (EVM 10) |
bsc | 2147483704 | BNB Smart Chain (EVM 56) |
gnosis | 2147483748 | Gnosis (EVM 100) |
polygon | 2147483785 | Polygon (EVM 137) |
zksync | 2147483972 | ZKsync Era (EVM 324) |
base | 2147492101 | Base (EVM 8453) |
arbitrum | 2147525809 | Arbitrum One (EVM 42161) |
avalanche | 2147526762 | Avalanche C-Chain (EVM 43114) |
linea | 2147542792 | Linea (EVM 59144) |
scroll | 2148018000 | Scroll (EVM 534352) |
EVM chains use 0x80000000 | chainId; any other SLIP-44 number can be passed as a numeric string.
Flags (flags[], mode=resolve)
| Flag | Meaning |
|---|---|
not_registered | .eth name unknown to RPC and to the ENS index — such a name has nothing to return, so it is not an item: it is listed in SUMMARY.notFound |
no_forward_resolution | Name exists but has no ETH address record |
no_primary_name | Address has no reverse (primary) name — with nothing else resolved it is listed in SUMMARY.notFound instead of being an item |
reverse_record_mismatch | Name points to an address whose primary name is a different name — treat as unverified identity |
no_reverse_record | Name points to an address that has no primary name |
expires_within_<N>d | Expires within expiresWithinDays |
expired_in_grace_period / expired | Expired less / more than 90 days ago |
owner_differs_from_resolved_address | Controller/owner is not the address the name points to |
wrapped_name, offchain_name, subname | NameWrapper name; offchain (CCIP-read) name; subdomain |
Examples
1. Verify a payee before sending funds
{ "queries": ["nick.eth", "vitalik.eth"], "verifyReverse": true, "includeRegistration": true, "textRecords": ["url", "com.twitter"] }
2. Enrich a list of wallet addresses for CRM
{ "queries": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "0xb8c2C29ee19D8307cb7255e1Cd9CbDE883A267d5"], "textRecords": ["*standard", "*services"], "includeContenthash": false, "fields": ["reverseName", "twitter", "github", "url", "email", "description", "completeness"] }
3. All names owned by our treasury, with expiry
{ "mode": "ownedBy", "queries": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"], "lookupResolvedTo": false, "onlyActive": false, "maxNamesPerQuery": 100 }
4. Renewal monitor with a 60-day window
{ "queries": ["uniswap.eth", "ens.eth"], "expiresWithinDays": 60, "textRecords": ["url"], "verifyReverse": false, "fields": ["registration", "flags"] }
5. Brand check: is the name registered, by whom, until when
{ "mode": "search", "queries": ["uniswap", "app.uniswap.eth"], "onlyActive": false }
6. Cross-chain payout addresses
{ "queries": ["vitalik.eth"], "coinTypes": ["btc", "sol", "base", "arbitrum"], "textRecords": ["avatar"] }
Output
mode: "resolve" — one item per query (trimmed real example):
{"query": "vitalik.eth", "kind": "name", "name": "vitalik.eth", "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045","found": true, "isPrimaryName": true, "reverseName": "vitalik.eth","avatar": "https://euc.li/vitalik.eth", "avatarUrl": "https://euc.li/vitalik.eth","header": "https://pbs.twimg.com/profile_banners/295218901/1638557376/1500x500", "display": null,"description": "mi pinxe lo crino tcati", "url": "https://vitalik.ca", "email": null,"twitter": "VitalikButerin", "github": "vbuterin", "discord": null, "telegram": null, "farcaster": null, "lens": null,"texts": { "avatar": "https://euc.li/vitalik.eth", "url": "https://vitalik.ca", "description": "mi pinxe lo crino tcati", "com.twitter": "VitalikButerin", "com.github": "vbuterin" },"addresses": {},"contenthash": "ipfs://bafybeigqyo555suvqi3scc2izft3mozskktbtkzs2xghoe2rpxetxbbdiq", "resolver": "0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63","registration": { "owner": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "registeredAt": "2017-06-18T08:39:14.000Z", "expiresAt": "2048-04-30T00:13:44.000Z", "daysToExpiry": 7880, "isExpired": false, "inGracePeriod": false, "isWrapped": false, "tokenId": "79233663829379634837589865448569342784712482819484549289560981379859480642508", "…": "…" },"events": [], "completeness": 85, "flags": [], "warnings": [], "sources": ["rpc", "bens"],"ensAppUrl": "https://app.ens.domains/vitalik.eth", "fetchedAt": "2026-10-02T19:09:22.058Z"}
| Field | Description |
|---|---|
kind | name, address or invalid |
name, address, found | Normalized ENS name, resolved/queried address; found = both known (false only for a registered name without an address record, which still carries registration / records) |
isPrimaryName, reverseName | Reverse-record verification (see flags) |
avatar, avatarUrl, header | Raw avatar record and a fetchable URL (ipfs:// and NFT avatars mapped to gateways / ENS metadata service); the header (banner) record |
display, description, url, email, twitter, github, discord, telegram, farcaster, lens | Common records, handles cleaned of URL prefixes and @ |
query, fetchedAt | The query as typed (trimmed); when the row was read (UTC) |
texts | All requested text records that are set |
addresses | Requested multi-chain address records (null when not set) |
contenthash, resolver | Decentralised website hash as a URI (ipfs:// CIDv1, ipns://, bzz://, ar://; an unknown namespace as raw hex); resolver contract |
registration | Registration & expiry object (null if disabled or not indexed) |
events | Recent ENS events: txHash, timestamp, from, fromName, action |
completeness | 0–100 profile score (address, avatar, description, url, email, socials, contenthash, extra addresses) |
ensAppUrl | Link to the name in the ENS app |
flags, warnings, sources | Triage flags; failed sub-lookups (the row is still delivered); which sources answered (rpc, bens, enstate) |
mode: "ownedBy" / "search" — one item per name: query, relation (owned, resolved_to, owned_and_resolved; null in search), name, address, owner, wrappedOwner, registeredAt, expiresAt, daysToExpiry, isExpired, inGracePeriod, isSubname, protocol, ensAppUrl, source, fetchedAt. A query with no matches is not an item (not charged): it is listed in SUMMARY.notFound.
Use it from code / agents
curl -X POST "https://api.apify.com/v2/acts/yadroo~ens-resolver/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"queries":["vitalik.eth","0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"]}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('yadroo/ens-resolver').call({ queries: ['vitalik.eth'], coinTypes: ['btc', 'sol'] });const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClientclient = ApifyClient(token)run = client.actor("yadroo/ens-resolver").call(run_input={"mode": "ownedBy", "queries": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"]})items = client.dataset(run["defaultDatasetId"]).list_items().items
MCP: add https://mcp.apify.com to your MCP client (Claude, Cursor, …) and call the yadroo/ens-resolver tool with the same JSON.
Pricing
Pay per event: $0.001 per run start + $0.002 per dataset item. Bronze −10 %, Silver −20 %, Gold and above −30 % on the item price; the start event is the same on every plan; platform usage is included. In resolve mode that is one item per query: resolving 100 names or addresses costs $0.201. In ownedBy / search every returned name is an item, so cap it with maxNamesPerQuery (e.g. an address with 50 names = $0.101). Queries with no result, invalid queries, duplicates and failed lookups are not dataset items and cost nothing — see SUMMARY.
The run never goes over your Maximum cost per run: it stops before the first item it could not pay for, ends with the status "Stopped at your spending limit: N rows delivered", and lists the queries it did not get to in SUMMARY.notProcessed.
Limits & FAQ
- Sources — forward/reverse resolution, text and address records and the contenthash come from public Ethereum RPC nodes (ENS Universal Resolver, with fallback across several providers); registration, events,
ownedByandsearchcome from the Blockscout ENS index (BENS). enstate.rs is asked only when an RPC record lookup failed, and is skipped for the rest of the run after two failures in a row. - Speed & capacity — about 1.3–1.8 s per name in
resolvemode with public RPCs and the default options (two runs of 334 names on Apify on 02.10.2026 took 7 and 10 minutes), so the default 15-minute run fits about 400–600 names; every extra coin type, text key orincludeEventsadds a little. The run stops starting new queries shortly before its timeout (90 s before the default 15 minutes), saves what it has, ends SUCCEEDED with "Stopped before the run timeout" and lists the queries it did not get to inSUMMARY.notProcessed: run those again, or raise the run timeout.ownedBy/searchread the index 100 names per page. Public RPCs rate-limit large batches; failed sub-lookups are listed inwarningsand the item is still delivered. For large lists pass your own node inrpcUrls. - Restarts — if Apify migrates or restarts the run, it continues after the last finished query; no item is stored or billed twice.
- Freshness — RPC data is live; the ENS index lags the chain by minutes.
- Offchain names (
*.cb.id,*.base.eth, other CCIP-read names) resolve via RPC; registration data may be missing for them. - Search is an exact lookup in the index: a bare label (
uniswap,uniswap.eth) is checked under every TLD the index knows for Ethereum, a longer name (app.uniswap.eth) as given. It does not find names that merely contain the word. - Errors — Apify refuses an off-list
modebefore the run starts. An unknown coin type, text-record shortcut or field name, a malformedrpcUrlsentry or an emptyquerieslist fails the run at once with a message that names it. Per-query problems never stop the run and are never charged: theSUMMARYrecord lists invalid names/addresses and failed lookups undererrors(with a reason that says what is wrong: wrong length, non-hex character, missing TLD, which lookup failed) and queries with nothing to return undernotFound(unregistered names, addresses without a primary name, no matches), witherrorCount/notFoundCount. A query is reported as not found only when the sources answered; when a lookup failed it is an error. The run fails only when it saved no item and at least one query failed; a run where every query was simply not found succeeds with 0 items. - SUMMARY record —
delivered(items saved, also asitems),errors/errorCount,notFound/notFoundCount,notProcessed/notProcessedCount(queries a stop left out),queriesDone,duplicatesRemoved,notes(input corrections),stoppedBy(limit,timeout,abortedor null) and the finalstatus. Lists hold the first 100 entries; the counts are exact. - Address checksum — mixed-case addresses must pass the EIP-55 checksum. A failed checksum almost always means a typo, so the query is rejected (
0x address fails the EIP-55 checksum) instead of silently resolving a different wallet. All-lowercase addresses skip the check. - Roadmap — L2 primary names (ENSIP-19), name history diffs for monitoring.
Made by Yadroo. Siblings: wallet-intel · base-token-intel · dexscreener-tokens · bitcoin-mempool · x402-endpoints