Skip to main content

GET /api/ens/batch-resolve

Resolve multiple Ethereum addresses to ENS names and social metadata in a single request.

Use Cases

  • Token deployer identity verification
  • Wallet screening for compliance
  • Bulk identity lookups for analytics
  • Agent-to-agent identity services

Endpoint

GET https://api.web3identity.com/api/ens/batch-resolve

Query Parameters

ParameterTypeRequiredDescription
addressesstringYesComma-separated Ethereum addresses (0x format). Max 100.
includestringNoFields to include: name,avatar,twitter,github,discord,email,url,telegram,linkedin. Default: name,avatar,twitter,github,discord

Performance

AddressesCold CacheWarm CacheCache Hit Rate
10~400ms<10ms100%
50~760ms<50ms96%
100~814ms<100ms90%

Cache TTL: 15 minutes

Pricing & Rate Limits

Free Tier

  • 100 addresses per day (anonymous users)
  • Resets daily at midnight UTC
  • No API key required
  • Perfect for testing and low-volume usage
  • $0.01 per batch (up to 100 addresses)
  • Payment via x402 protocol (USDC on Base)
  • No signup required - pay per request
  • Automatic payment settlement via Coinbase CDP

Usage Tracking

All responses include usage metadata:

{
"metadata": {
"usage": {
"tier": "free",
"addressesUsed": 10,
"totalToday": 25,
"limit": 100,
"remaining": 75,
"resetsAt": "2026-02-16T00:00:00.000Z"
}
}
}

When you exceed the free tier, you'll receive a 402 Payment Required response with payment instructions.

Example Request

Basic (2 addresses)

curl "https://api.web3identity.com/api/ens/batch-resolve?addresses=0x4D982788c01402C4E0f657E1192d7736084AE5a8,0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&include=name,twitter,github"

Large batch (50 addresses)

curl "https://api.web3identity.com/api/ens/batch-resolve?addresses=0x...,0x...&include=name"

Response Format

{
"addresses": [
{
"address": "0x4d982788c01402c4e0f657e1192d7736084ae5a8",
"ens": "garypalmerjr.eth",
"avatar": "eip155:1/erc721:0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d/3636",
"social": {
"twitter": "GaryPalmerJr",
"github": "GaryPalmerJr",
"discord": "garypalmerjr"
}
},
{
"address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
"ens": "vitalik.eth",
"avatar": "https://euc.li/vitalik.eth",
"social": {
"twitter": "VitalikButerin",
"github": "vbuterin"
}
},
{
"address": "0x0000000000000000000000000000000000000001",
"ens": null,
"social": {}
}
],
"metadata": {
"total": 3,
"resolved": 2,
"failed": 0,
"noEns": 1,
"cacheHits": 6,
"cacheMisses": 0,
"cacheHitRate": "100.0%",
"processingTimeMs": 5,
"phase": 2
}
}

Response Fields

addresses[] (array)

FieldTypeDescription
addressstringLowercase Ethereum address
ensstring|nullENS name (null if none)
avatarstringAvatar URL or NFT reference (CAIP-22)
socialobjectSocial profiles (fields depend on include param)
errorstringError message if resolution failed
reasonstringFailure reason

metadata (object)

FieldTypeDescription
totalintegerTotal addresses requested
resolvedintegerAddresses with ENS names
failedintegerAddresses with errors
noEnsintegerAddresses without ENS
cacheHitsintegerQueries served from cache
cacheMissesintegerQueries that hit blockchain
cacheHitRatestringCache hit percentage
processingTimeMsintegerTotal server processing time
phaseintegerAPI version (2)
warningstringPerformance warnings (if any)
recommendationstringUsage recommendations (if batch >50)

Error Codes

400 Bad Request

Missing addresses:

{
"error": true,
"code": "MISSING_ADDRESSES",
"message": "Query parameter \"addresses\" is required",
"timestamp": "2026-02-15T20:00:00.000Z"
}

Invalid address format:

{
"error": true,
"code": "INVALID_ADDRESSES",
"message": "Invalid Ethereum addresses: 0xinvalid, 0xbad",
"timestamp": "2026-02-15T20:00:00.000Z"
}

Too many addresses:

{
"error": true,
"code": "TOO_MANY_ADDRESSES",
"message": "Maximum 100 addresses allowed per request. Requested: 150",
"timestamp": "2026-02-15T20:00:00.000Z"
}

500 Internal Server Error

{
"error": true,
"code": "BATCH_RESOLVE_ERROR",
"message": "Internal resolution error",
"timestamp": "2026-02-15T20:00:00.000Z"
}

Best Practices

1. Batch Size

  • Recommended: 50 addresses or fewer
  • Absolute max: 100 addresses
  • Larger batches (>50) will show performance recommendations

2. Caching

  • Results cached for 15 minutes
  • Repeated queries are 50-100x faster
  • No need to implement client-side caching

3. Field Selection

Only request fields you need to reduce payload size:

# Minimal (just names)
?include=name

# Social only
?include=twitter,github,discord

# Full profile
?include=name,avatar,twitter,github,discord,email,url

4. Error Handling

Always check metadata.failed for partial failures:

const data = await fetch(url).then(r => r.json());

if (data.metadata.failed > 0) {
const failed = data.addresses.filter(a => a.error);
console.warn('Some addresses failed:', failed);
}

const resolved = data.addresses.filter(a => a.ens);
// Process successful results

Integration Examples

JavaScript (Node.js)

async function resolveDeployers(addresses) {
const url = new URL('https://api.web3identity.com/api/ens/batch-resolve');
url.searchParams.set('addresses', addresses.join(','));
url.searchParams.set('include', 'name,twitter,github');

const response = await fetch(url);
if (!response.ok) {
throw new Error(`ENS resolution failed: ${response.statusText}`);
}

const data = await response.json();

return {
identities: data.addresses.filter(a => a.ens),
stats: data.metadata
};
}

// Usage
const deployers = ['0x4D982788...', '0xd8dA6BF2...'];
const { identities, stats } = await resolveDeployers(deployers);
console.log(`Resolved ${stats.resolved}/${stats.total} identities`);
console.log(`Cache hit rate: ${stats.cacheHitRate}`);

Python

import requests
from typing import List, Dict

def resolve_deployers(addresses: List[str]) -> Dict:
"""Resolve ENS names and social profiles for addresses."""
url = "https://api.web3identity.com/api/ens/batch-resolve"
params = {
"addresses": ",".join(addresses),
"include": "name,twitter,github"
}

response = requests.get(url, params=params)
response.raise_for_status()

data = response.json()

return {
"identities": [a for a in data["addresses"] if a["ens"]],
"stats": data["metadata"]
}

# Usage
deployers = ["0x4D982788...", "0xd8dA6BF2..."]
result = resolve_deployers(deployers)
print(f"Resolved {result['stats']['resolved']}/{result['stats']['total']}")
print(f"Cache hit rate: {result['stats']['cacheHitRate']}")

Rate Limits

  • Free tier: 100 calls/day
  • Paid tier: Coming soon (Phase 3)

Updated February 15, 2026 - Phase 2 complete