Skip to content

ENS Resolution

Most apps need ENS resolution in three modes:

  • Forward — given a name (vitalik.eth), resolve records like avatar, bio, links, and multichain addresses.
  • Reverse — given an address, find its primary name on a chain.
  • Identity — given an address, resolve the primary name and its records in one query.

Behind every mode sits the same protocol complexity: resolver contracts, coin-type encoding, inconsistent text-record keys, and avatar formats that may be URLs, IPFS paths, or NFT references. The Omnigraph handles that complexity for you and returns clean, structured results in one request.

Forward resolution — interpreted profile

Section titled “Forward resolution — interpreted profile”

When you have a name and need display-ready data, query domain.resolve.profile. This is where the Omnigraph does the heavy lifting: instead of decoding coin types, normalizing text-record keys, and chasing avatar formats yourself, you get a consumer-shaped view of the most common display fields — ready to drop into a UI or hand straight to an AI agent.

This query below loads a domain's high-level profile (avatar, socials, addresses, and more).

Run in ENSAdmin
GraphQL
query DomainProfile($name: InterpretedName!) {
domain(by: {name: $name}) {
resolve {
profile {
description
avatar {
httpUrl
}
addresses {
ethereum
base
solana
bitcoin
rootstock
}
socials {
github {
handle
httpUrl
}
twitter {
handle
httpUrl
}
}
website {
httpUrl
}
header {
httpUrl
}
}
}
}
}
Variables
{
"name": "gregskril.eth"
}
Output
{
"data": {
"domain": {
"resolve": {
"profile": {
"description": "I like baking and building apps on web3 protocols.",
"avatar": {
"httpUrl": "https://gregskril.com/img/profile.jpg"
},
"addresses": {
"ethereum": "0x179a862703a4adfb29896552df9e307980d19285",
"base": "0x179a862703a4adfb29896552df9e307980d19285",
"solana": "2JQANQn1kccapb7GT8XScf9qBy59uMo9vh9WwVQhwStJ",
"bitcoin": "3NnpwUMGdGKuYaPDQagNXAgVXz9HdnJDNS",
"rootstock": "0x179a862703A4AdFb29896552dF9e307980D19285"
},
"socials": {
"github": {
"handle": "gskril",
"httpUrl": "https://github.com/gskril"
},
"twitter": {
"handle": "gregskril",
"httpUrl": "https://x.com/gregskril"
}
},
"website": {
"httpUrl": "https://gregskril.com/"
},
"header": {
"httpUrl": "https://files.gregskril.com/cdn/QmfGaXqmqasCrKktBgD4AvvJb3DLndiKXdz457uBGLTFGK"
}
}
}
}
}
}

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.

What you get in resolve.profile:

  • Addresses — keyed by chain (ethereum, solana, base, …) in chain-native encodings.
  • Social accounts{ handle, httpUrl } pairs, ready to link.
  • Avatar and header imageshttpUrl values you can use directly in <img src="…" />, including derivation from NFT references per ENSIP-12.
  • Missing or invalid recordsnull, so you can render without extra guards.

The same predictable shape works well for AI agents — structured fields and null for anything missing or invalid, without decoding resolver data in the prompt.

resolve.records returns protocol-accurate resolver data: numeric coin types, arbitrary text keys, and unparsed bytes. This is the shape you would work with if you decoded resolver storage yourself — or if you need records that profile does not model.

This query below resolves raw records for a given name, such as addresses, texts, and contenthash.

Run in ENSAdmin
GraphQL
query DomainRecords($name: InterpretedName!) {
domain(by: {name: $name}) {
canonical {
name {
interpreted
}
}
resolve {
records {
addresses(coinTypes: [60, 2147483658, 501]) {
coinType
address
}
texts(keys: ["description", "avatar", "url", "com.github", "com.twitter"]) {
key
value
}
contenthash
}
}
}
}
Variables
{
"name": "gregskril.eth"
}
Output
{
"data": {
"domain": {
"canonical": {
"name": {
"interpreted": "gregskril.eth"
}
},
"resolve": {
"records": {
"addresses": [
{
"coinType": 60,
"address": "0x179a862703a4adfb29896552df9e307980d19285"
},
{
"coinType": 2147483658,
"address": "0x179a862703a4adfb29896552df9e307980d19285"
},
{
"coinType": 501,
"address": "0x1350bfe02357c8bc583d7514f44ba2c31821d8739160e7b79a0a94bc113a4f73"
}
],
"texts": [
{
"key": "description",
"value": "I like baking and building apps on web3 protocols."
},
{
"key": "avatar",
"value": "https://gregskril.com/img/profile.jpg"
},
{
"key": "url",
"value": "https://gregskril.com/"
},
{
"key": "com.github",
"value": "gskril"
},
{
"key": "com.twitter",
"value": "gregskril"
}
],
"contenthash": "0xe30101701220f0bd3d5d672c6197d341797bb34d4a5e31fbb40c437fead8756213522b976ed9"
}
}
}
}
}

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.

Reverse resolution answers a simple question: what name does this address want to be known by? On a given chain, that is its primary name (ENSIP-19). If the address has not set one, the result is null — safe to render like any other missing field.

Primary names are per-chain. Use friendly chain names like ETHEREUM or BASE rather than raw coin types. beautified is ready for UI rendering; interpreted is the stable form for lookups and links. See Beautified Name.

This query loads the primary names for an account on Ethereum and Base.

Run in ENSAdmin
GraphQL
query AccountPrimaryName($address: Address!) {
account(by: { address: $address }) {
address
resolve {
primaryNames(where: { chainNames: [ETHEREUM, BASE] }) {
chainName
name { interpreted beautified }
}
}
}
}
Variables
{
"address": "0x179a862703a4adfb29896552df9e307980d19285"
}
Output
{
"data": {
"account": {
"address": "0x179a862703a4adfb29896552df9e307980d19285",
"resolve": {
"primaryNames": [
{
"chainName": "ETHEREUM",
"name": {
"interpreted": "gregskril.eth",
"beautified": "gregskril.eth"
}
},
{
"chainName": "BASE",
"name": {
"interpreted": "greg.base.eth",
"beautified": "greg.base.eth"
}
}
]
}
}
}
}

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.

If you need the display data that goes with that name — not just the name itself — see Identity resolution below.

Identity resolution — full address resolve

Section titled “Identity resolution — full address resolve”

Identity resolution is the pattern most wallets and explorers actually use: start from an address, get the primary name, and load its full display data — all in one request. It is reverse resolution followed immediately by forward resolution, with no extra round trip.

This query loads the primary name for an account on Ethereum and forward-resolves its profile in the same request.

Run in ENSAdmin
GraphQL
query AccountPrimaryNameRecords($address: Address!) {
account(by: { address: $address }) {
address
resolve {
primaryName(by: { chainName: ETHEREUM }) {
name { interpreted beautified }
resolve {
profile {
description
socials {
twitter {
httpUrl
}
}
}
}
}
}
}
}
Variables
{
"address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
}
Output
{
"data": {
"account": {
"address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
"resolve": {
"primaryName": {
"name": {
"interpreted": "vitalik.eth",
"beautified": "vitalik.eth"
},
"resolve": {
"profile": {
"description": "mi pinxe lo crino tcati",
"socials": {
"twitter": {
"httpUrl": "https://x.com/VitalikButerin"
}
}
}
}
}
}
}
}
}

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.

Breaking down the example above:

  • Start from an address — pass any wallet address; the query looks up that account’s ENS identity.
  • Pick a chain — primary names are per-chain (e.g. Ethereum mainnet). Use friendly chain names like ETHEREUM or BASE instead of raw coin types.
  • Display the namebeautified is ready for UI rendering; interpreted is the stable form for lookups and links.
  • Load the display data in the same request — avatar, bio, and social links are forward-resolved from the primary name. The response shape is the same resolve.profile structure covered in the forward resolution section above.