ENS Indexer API

API Documentation

ENSWhois Docs Status API

Public API for querying ENS domain data. All endpoints return JSON.

https://api.enswhois.com

Authentication

API Key

Pass your key via the X-API-Key header. Sign up to get a key with 1,000 free credits.

Micropayments (MPP)

Pay per request using the MPP protocol. No account needed — pay directly from your wallet.

No authentication is needed to try the API - unauthenticated requests are limited to 5 per minute. Sign up for unlimited access.

CORS is enabled for all /api endpoints. You can call these from any origin.

Lookup

GET /whois/:name

Look up a domain.

Returns domain data with ownership, expiry, resolver, wrapped status, and availability information.

Parameters

NameTypeDescription
namestringFull ENS name (e.g. vitalik.eth)

Example Response

{
  "name": "vitalik.eth",
  "label": "vitalik",
  "labelhash": "0xaf2caa1c...",
  "token_id": "7960091...",
  "namehash": "0xee6c4522...",
  "parent_node": "0x93cdeb7...",
  "parent_name": "eth",
  "expiry_timestamp": "1754000000",
  "ownership": {
    "is_wrapped": false,
    "owner": "0xd8dA6BF2...",
    "registry": "0xd8dA6BF2...",
    "registrar": "0xd8dA6BF2..."
  },
  "resolver": {
    "status": "indexed",
    "chain": "mainnet",
    "address": "0x231b0ee1..."
  },
  "availability_status": "registered",
  "query": "vitalik.eth",
  "source": "indexed"
}
POST /whois/bulk
  • Bulk lookup for multiple domains by name or namehash
  • Maximum 500 items per request (names + namehashes combined)
  • Each result uses the same fields as the single whois endpoint

Request Body

NameTypeDescription
namesstring[]Array of full ENS names (e.g. ["vitalik.eth", "nick.eth"]). Optional if namehashes is provided.
namehashesstring[]Array of namehash hex strings (0x + 64 hex chars). Optional if names is provided.

At least one of names or namehashes must be provided. Both can be used together in a single request.

{
  "names": ["vitalik.eth", "nick.eth"],
  "namehashes": ["0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835"]
}

Example Response

{
  "results": [
    {
      "query": "vitalik.eth",
      "name": "vitalik.eth",
      "label": "vitalik",
      "expiry_timestamp": "1754000000",
      "ownership": { "..." },
      "resolver": { "..." },
      "availability_status": "registered",
      "source": "indexed"
    },
    {
      "query": "nonexistent.eth",
      "availability_status": "available",
      "source": "indexed"
    }
  ],
  "summary": {
    "total": 2,
    "registered": 1,
    "grace": 0,
    "premium": 0,
    "available": 1,
    "unknown": 0,
    "expiring_30d": 0
  }
}
GET /search-domains Paginated

Search domains with filters.

Query Parameters

NameTypeDescription
qstringSearch query (matches label by default)
search_full_namestringSet to true to search full_name instead of label
availability_statusstringFilter: registered, grace, premium, available
min_lengthintegerMinimum label length
max_lengthintegerMaximum label length
registrar_ownerstringFilter by registrar owner address (exact, case-insensitive)
wrapper_ownerstringFilter by wrapper owner address (exact, case-insensitive)
registry_ownerstringFilter by registry owner address (exact, case-insensitive)
resolverstringFilter by resolver address (exact, case-insensitive)
expiry_fromintegerMinimum expiry (unix timestamp)
expiry_tointegerMaximum expiry (unix timestamp)
is_wrappedstringtrue or false
sort_bystringfull_name (default), label, expiry_timestamp, effective_owner_address

Example Response

{
  "results": [
    {
      "name": "vitalik.eth",
      "label": "vitalik",
      "expiry_timestamp": "1754000000",
      "ownership": {
        "owner": "0xd8dA6BF2...",
        "is_wrapped": false
      }
    }
  ],
  "stats": {
    "expired": 12,
    "expiring_30d": 3,
    "expiring_90d": 8,
    "wrapped": 210,
    "wrapped_pct": 39.5
  },
  "total": 532,
  "page": 1,
  "page_size": 25
}

Events & Sub-Resources

GET /domain/:name/events

Get all on-chain events for a domain. Only non-null fields are included in each event object.

Parameters

NameTypeDescription
namestringFull ENS name (e.g. vitalik.eth)

Example Response

{
  "events": [
    {
      "contract": "CONTROLLER_9380470",
      "event_type": "NameRegistered",
      "block_number": 9380471,
      "transaction_hash": "0xabc...",
      "owner_address": "0xd8dA6BF2...",
      "cost_wei": "3200000000000000",
      "expiry_timestamp": "1754000000"
    },
    {
      "contract": "REGISTRY",
      "event_type": "NewOwner",
      "block_number": 9380471,
      "transaction_hash": "0xabc...",
      "owner_address": "0xd8dA6BF2..."
    }
  ]
}
GET /domain/:name/subdomains Paginated

List direct subdomains of a domain.

Only returns subnames created via on-chain events. Off-chain subnames (e.g. ENSIP-10 wildcard or CCIP-Read) are not discoverable by the indexer.

Parameters

NameTypeDescription
namestringParent domain name (e.g. vitalik.eth)

Query Parameters

NameTypeDescription
sort_bystringfull_name (default)

Example Response

{
  "domain": "vitalik.eth",
  "results": [
    {
      "name": "sub.vitalik.eth",
      "label": "sub",
      "expiry_timestamp": null,
      "ownership": {
        "owner": "0xd8dA6BF2...",
        "is_wrapped": false
      },
      "resolver": {
        "address": "0x231b0Ee1..."
      }
    }
  ],
  "total": 3,
  "page": 1,
  "page_size": 25
}
GET /domain/:name/registration-history

Registration and renewal history for a domain.

Parameters

NameTypeDescription
namestringFull ENS name (e.g. vitalik.eth)
mergedstringtrue (default) merges events from the same transaction; false returns individual events with a contract field

Example Response

{
  "domain": "vitalik.eth",
  "registrations": [
    {
      "event_type": "NameRegistered",
      "block_number": 9380471,
      "transaction_hash": "0xabc...",
      "cost_wei": "3200000000000000",
      "cost_eth": "0.003200",
      "expiry_timestamp": "1754000000",
      "owner_address": "0xd8dA..."
    }
  ],
  "renewals": []
}
GET /domain/:name/records

Returns current resolver records for a domain: text records, multi-chain addresses, and contenthash.

Parameters

NameTypeDescription
namestringFull ENS name (e.g. vitalik.eth)

Query Parameters

NameTypeDescription
typesstringComma-separated: text, addr, contenthash (default: all)

Example Response

{
  "domain": "vitalik.eth",
  "resolver": {
    "status": "indexed",
    "chain": "mainnet",
    "address": "0x231b0ee1..."
  },
  "records": {
    "texts": {
      "com.twitter": "VitalikButerin",
      "avatar": "eip155:1/..."
    },
    "addresses": {
      "60": "0xd8dA6BF2..."
    },
    "contenthash": null
  },
  "source": "indexed"
}
GET /domain/:name/records/text/:key

Look up a single text record for a domain.

Parameters

NameTypeDescription
namestringFull ENS name (e.g. vitalik.eth)
keystringText record key (e.g. com.x, avatar)

Example Response

{
  "domain": "vitalik.eth",
  "resolver": {
    "status": "indexed",
    "chain": "mainnet",
    "address": "0x231b0ee1..."
  },
  "key": "com.x",
  "value": "VitalikButerin",
  "block_number": 18500000,
  "transaction_hash": "0xabc...",
  "source": "indexed"
}

Derived History

GET /domain/:name/ownership-history

Effective ownership history for a domain, derived from on-chain events.

Returns ownership periods with the resolved effective owner at each point in time.

Parameters

NameTypeDescription
namestringFull ENS name (e.g. vitalik.eth)
auditstringtrue to include per-contract breakdown (registry, registrar, wrapper arrays). Default false

Example Response

{
  "history": [
    {
      "address": "0xd8dA6BF2...",
      "reason": "registrar",
      "from_block": 9500000,
      "from_tx": "0xdef456...",
      "to_block": null,
      "to_tx": null
    }
  ]
}
GET /domain/:name/resolver-history

Resolver change history derived from stored on-chain events. Each entry represents a period where a specific resolver contract was active for the domain.

Parameters

NameTypeDescription
namestringFull ENS name (e.g. vitalik.eth)

Example Response

{
  "history": [
    {
      "address": "0x4976fb03...",
      "from_block": 9412610,
      "from_tx": "0xdef456...",
      "to_block": 16773775,
      "to_tx": "0x789abc..."
    },
    {
      "address": "0x231b0Ee1...",
      "from_block": 16773775,
      "from_tx": "0x789abc...",
      "to_block": null,
      "to_tx": null
    }
  ]
}
GET /domain/:name/records/text/:key/history

Change history for a specific text record. Only includes changes from the domain's active resolver at the time - records set on non-active resolvers are excluded. Resolver changes are included as null-value boundaries.

Parameters

NameTypeDescription
namestringFull ENS name (e.g. vitalik.eth)
keystringText record key (e.g. avatar, com.twitter)

Example Response

{
  "domain": "vitalik.eth",
  "key": "avatar",
  "history": [
    {
      "value": "eip155:1/...",
      "block_number": 18500000,
      "resolver": "0x231b0ee1...",
      "source": "indexed",
      "transaction_hash": "0xabc..."
    },
    {
      "value": null,
      "block_number": 16773775,
      "source": "resolver_change"
    },
    {
      "value": "old-avatar",
      "block_number": 15000000,
      "resolver": "0x4976fb03...",
      "source": "indexed",
      "transaction_hash": "0xdef..."
    }
  ]
}

Each entry's source indicates provenance:

  • indexed - from an on-chain TextChanged event
  • resolver_change - the resolver changed, invalidating the previous value
  • live - current value from live on-chain resolution

Hash Lookups

GET /lookup-hash/:hash

Look up a domain by any hash. Tries namehash first (unique match), then falls back to labelhash (may match multiple domains).

Parameters

NameTypeDescription
hashstringA 66-character hex string (0x + 64 hex chars)

Example Response (namehash match)

{
  "type": "namehash",
  "name": "vitalik.eth",
  "label": "vitalik",
  "token_id": "7960091...",
  "namehash": "0xee6c4522...",
  "labelhash": "0xaf2caa1c...",
  "parent_name": "eth",
  "parent_node": "0x93cdeb7...",
  "expiry_timestamp": "1754000000",
  "ownership": {
    "owner": "0xd8dA6BF2...",
    "is_wrapped": false
  },
  "resolver": {
    "status": "indexed",
    "chain": "mainnet",
    "address": "0x231b0ee1..."
  }
}

Example Response (labelhash match)

{
  "type": "labelhash",
  "domains": [
    {
      "name": "vitalik.eth",
      "label": "vitalik",
      "token_id": "7960091...",
      "namehash": "0xee6c4522...",
      "labelhash": "0xaf2caa1c...",
      "parent_name": "eth",
      "parent_node": "0x93cdeb7...",
      "expiry_timestamp": "1754000000",
      "ownership": {
        "owner": "0xd8dA6BF2...",
        "is_wrapped": false
      },
      "resolver": {
        "status": "indexed",
        "chain": "mainnet",
        "address": "0x231b0ee1..."
      }
    }
  ]
}

Example Response (not indexed)

{
  "hash": "0xee6c4522...",
  "indexed": false
}
GET /lookup-namehash/:hash

Look up a single domain by its namehash. Returns full domain details including ownership, resolver, and wrapped status.

Parameters

NameTypeDescription
hashstringNamehash - a 66-character hex string (0x + 64 hex chars)

Example Response

{
  "name": "vitalik.eth",
  "label": "vitalik",
  "token_id": "7960091...",
  "namehash": "0xee6c4522...",
  "labelhash": "0xaf2caa1c...",
  "parent_name": "eth",
  "parent_node": "0x93cdeb7...",
  "expiry_timestamp": "1754000000",
  "ownership": {
    "owner": "0xd8dA6BF2...",
    "registry": "0xd8dA6BF2...",
    "registrar": "0xd8dA6BF2...",
    "is_wrapped": false
  },
  "resolver": {
    "status": "indexed",
    "chain": "mainnet",
    "address": "0x231b0ee1..."
  }
}
GET /lookup-labelhash/:hash Paginated

Look up domains by labelhash. A labelhash can match multiple domains across different parent names (e.g. vitalik.eth and vitalik.xyz share the same labelhash).

Parameters

NameTypeDescription
hashstringLabelhash - a 66-character hex string (0x + 64 hex chars)

Example Response

{
  "domains": [
    {
      "name": "vitalik.eth",
      "label": "vitalik",
      "token_id": "7960091...",
      "namehash": "0xee6c4522...",
      "labelhash": "0xaf2caa1c...",
      "parent_name": "eth",
      "parent_node": "0x93cdeb7...",
      "expiry_timestamp": "1754000000",
      "ownership": {
        "owner": "0xd8dA6BF2...",
        "is_wrapped": false
      },
      "resolver": {
        "status": "indexed",
        "chain": "mainnet",
        "address": "0x231b0ee1..."
      }
    }
  ],
  "total": 1,
  "page": 1,
  "page_size": 25
}