Skip to content

ENS Omnigraph API

The ENS Omnigraph API is the world’s first and only API providing unified access to the full state of ENSv1 and ENSv2. It’s a single, polymorphic GraphQL API over both ENSv1 and ENSv2 — write your query once and get correct, typed results regardless of which protocol version a given Domain lives in.

ENS Omnigraph diagram

The Omnigraph is delivered by ENSApi on top of the indexed data in ENSDb. It follows the Relay specification, abstracts away the most common ENS-protocol footguns, and exposes enough of the underlying protocol for builders who need to go deep.

When ENSv2 launches in Summer 2026, the two protocol versions coexist — and the Omnigraph keeps your app working against both, at the same time, with no code changes. Both ENSv1 and ENSv2 Domains are indexed concurrently and exposed through a unified schema.

Ask for a Domain by name (domain(by: { name: "vitalik.eth" })) and you get a typed result whether that name lives in ENSv1 or ENSv2 — your code doesn’t have to know which at query time.

  • Multichain in one query — mainnet .eth, Basenames (.base.eth), Lineanames (.linea.eth), and 3DNS names (.box) all in a single unified schema.
  • Typed, no footguns — names and labels are normalized for you, so rendering them in a UI is trivial.
  • The full ENS picture — resolve records, search Domains, list what an address owns, read a complete history of onchain Events, inspect Permissions, and more.
  • Built-in pagination — Relay-spec connections mean infinite scroll and stable pagination work out of the box.

From a wallet address: Ethereum primary name and interpreted profile, plus ENSv1 and ENSv2 ownership counts.

Run in ENSAdmin
GraphQL
query HelloWorld($address: Address!) {
# Lookup an Account by address.
account(by: { address: $address }) {
resolve {
# Reverse resolve the ENS primary name of the account
# using a convenient ETHEREUM alias for mainnet.
primaryName(by: { chainName: ETHEREUM }) {
# Get the regular interpreted variant of the primary name
# and also the special beautified variant that optimizes names
# containing special characters such as emojis for proper display in interfaces.
name { interpreted beautified }
resolve {
# If the account has a primary name on Ethereum (mainnet),
# forward resolve the interpreted ENS profile of that name in the same query!.
profile {
description
avatar { httpUrl }
addresses { ethereum bitcoin }
socials {
twitter { handle httpUrl }
github { handle httpUrl }
}
}
}
}
}
# Also load the count of ENSv1 and ENSv2 domains owned by the account
# to see if they have domains they should upgrade to ENSv2
v1DomainsCount: domains(where: { version: ENSv1 }) { totalCount }
v2DomainsCount: domains(where: { version: ENSv2 }) { totalCount }
}
}
Variables
{
"address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
}
Output
{
"data": {
"account": {
"v2DomainsCount": {
"totalCount": 0
},
"v1DomainsCount": {
"totalCount": 514
},
"resolve": {
"primaryName": {
"name": {
"interpreted": "vitalik.eth",
"beautified": "vitalik.eth"
},
"resolve": {
"profile": {
"description": "mi pinxe lo crino tcati",
"avatar": {
"httpUrl": "https://euc.li/vitalik.eth"
},
"addresses": {
"ethereum": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
"bitcoin": null
},
"socials": {
"twitter": {
"handle": "VitalikButerin",
"httpUrl": "https://x.com/VitalikButerin"
},
"github": {
"handle": "vbuterin",
"httpUrl": "https://github.com/vbuterin"
}
}
}
}
}
}
}
}
}

Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.

Browse more patterns in Examples. When you’re ready to understand the data model underneath, see Core Concepts.