Resolve an ENS name or Basename via API
Users type names like vitalik.eth or jesse.base.eth; contracts and transfers need addresses. This is a keyless lookup that returns the address and the resolver used.
The problem
Name resolution is more than a table lookup. You compute the name's namehash, ask the ENS registry for the resolver of that node, then ask the resolver for its address record. Basenames live on a different chain, Base, with their own registry, so the right chain depends on the suffix. Libraries do this for you, but they still need an RPC endpoint you must supply and keep reliable.
How /resolve answers it
GET /resolve?name=jesse.base.eth routes names ending in .base.eth to the Basenames registry on Base and every other name to the ENS registry on Ethereum mainnet. It returns the resolved address, the resolver contract, the registry that was asked and resolvedOn, the chain. If the name has no resolver or no address record, you get a 404 with an explanatory error, so a typo never turns into a valid-looking address. Pair it with /balance to go from a name to a balance in two calls.
Request and response
Example: a Basename.
$ curl -i "https://chainread.imac2014ville.workers.dev/resolve?name=jesse.base.eth"
HTTP/2 402
payment-required: eyJ4NDAyVmVyc2lvbiI6Mi4uLn0= # base64 JSON: scheme "exact", network eip155:8453,
# asset USDC, amount 2000 (= $0.002)
# An x402 client signs the payment, then retries with a PAYMENT-SIGNATURE header.
The paid response (as returned at the time of capture):
{
"ok": true,
"name": "jesse.base.eth",
"address": "0x2211d1d0020daea8039e46cf1367962070d77da9",
"resolver": "0xc6d566a56a1aff6508b41f6c90ff131615583bcd",
"resolvedOn": "base",
"registry": "0xB94704422c2a1E396835A571837Aa5AE53285a95",
"note": "Names are lowercased; full ENS normalization (emoji/Unicode) is not applied."
}
JavaScript with @x402/fetch
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
const signer = privateKeyToAccount(process.env.PRIVATE_KEY); // wallet holding USDC on Base
const pay = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(signer) }],
});
const res = await pay("https://chainread.imac2014ville.workers.dev/resolve?name=" + encodeURIComponent(name));
if (res.status === 404) throw new Error("name not registered or has no address");
const { address, resolvedOn } = await res.json();
console.log(name, "->", address, "on", resolvedOn);
Pricing
/resolve costs $0.002 per call. There is no API key and no account: each request is paid in USDC on Base over x402. Malformed input returns 400 and failed lookups return a non-2xx status, so those are not charged.
Limitations
- Forward resolution only (name to address). Reverse lookup from an address to a primary name is not offered.
- Names are lowercased but not fully ENS-normalised, so emoji and non-ASCII names may not resolve correctly. Names that use an offchain (CCIP-read) resolver are not supported.
- The address is whatever the owner set in the resolver at the latest block. Verify high-value transfers with a small test payment.
More guides
- Get an ERC-20 balance via HTTP API, no RPC key
- Base gas price API: what a transaction costs right now
ChainRead overview/openapi.jsonllms.txt
Sister services
- BaseLens: Base chain tools: tx explainer, wallet snapshot, x402 endpoint check, web-to-markdown
- DepVet: npm and PyPI package vetting before install
- TokenGuard: honeypot and rug pull checks for Base tokens, plus pre-screened new launches
- MacroLens: country macro statistics and company registries (Norway, France)
- SkyFeed: weather forecasts, US alerts, earthquakes and public holidays