Recover ETH stuck in old smart contracts
All endpoints are read-only GET requests. Responses are JSON with snake_case keys. No authentication required. Data refreshes on the scheduled refresh cycle from onchain Multicall3 scans. Rate limits vary per endpoint (see each section). CORS * enabled.
Per-address lookups go through the public sharded JSON index on GitHub, not a live API. Same data the site uses internally, delivered via GitHub raw — free, unauthenticated, and never rate-limited.
data/index_shards/meta.json — protocol metadata (contract address, coverage, scan date)data/index_shards/{prefix}.json — 256 shards (00.json…ff.json), keyed by the first two hex chars of the lowercased address{ "0x<full address>": { "<protocol_key>": "<balance_eth>" } }ADDR=0xab5801a7d398351b8be11c439e05c5b3259aec9b
PREFIX=${ADDR:2:2}
curl -s "https://raw.githubusercontent.com/q84c6tsm95-create/forgotten-eth/main/data/index_shards/${PREFIX}.json" \
| jq ".[\"${ADDR}\"]"
const addr = '0xab5801...'.toLowerCase(); const prefix = addr.slice(2, 4); const shard = await (await fetch( `https://raw.githubusercontent.com/q84c6tsm95-create/forgotten-eth/main/data/index_shards/${prefix}.json` )).json(); console.log(shard[addr]); // { protocol_key: "0.123" } or undefined
import json, urllib.request addr = '0xab5801...'.lower() prefix = addr[2:4] url = f'https://raw.githubusercontent.com/q84c6tsm95-create/forgotten-eth/main/data/index_shards/{prefix}.json' shard = json.loads(urllib.request.urlopen(url).read()) print(shard.get(addr)) # { 'protocol_key': '0.123' } or None
Group your addresses by their two-char prefix, fetch each shard once, then do constant-time lookups. 256 shards total ≈ 50 MB worst case; most use cases need fewer than 10. Cache locally and re-fetch only after a new refresh (check /api/summary's scan_date).
/api/check?Direct programmatic access to the per-address endpoint was removed to prevent abuse and keep the public API free. The shards above are the same source of truth, delivered faster and at zero infrastructure cost. The aggregate endpoints (summary, table, total, claims) remain available for live counters.
Overview of all tracked contracts with ETH balances, address counts, and coverage percentages. Rate limit: 30 req/min per IP.
{
"total_eth": 157640.24,
"contract_count": 193,
"contracts": {
"etherdelta": {
"contract": "0x8d12A197cB00D4747a1fe03395095ce2A5CC6819",
"total_eth": 1234.56,
"contract_eth_balance": 1500.00,
"addresses_with_balance": 245119,
"coverage_pct": 99.8,
"scan_date": "2026-03-30 UTC"
},
...
}
}
| Field | Type | Description |
|---|---|---|
| total_eth | number | Sum of all mapped depositor balances across all protocols |
| contract_count | number | Number of tracked contracts |
| contracts.*.total_eth | number | Total ETH mapped to known depositors in this contract |
| contracts.*.contract_eth_balance | number | Actual ETH balance of the contract onchain |
| contracts.*.addresses_with_balance | number | Number of depositors with non-zero balances |
| contracts.*.coverage_pct | number | Percentage of contract ETH mapped to known depositors (total_eth / contract_eth_balance * 100) |
| contracts.*.scan_date | string | When this contract was last scanned (UTC date) |
Detailed metadata for a single protocol: balances, coverage, balance distribution, and monthly TVL history. Rate limit: 60 req/min per IP.
| Parameter | Type | Description |
|---|---|---|
| exchange | string | Protocol key (e.g. etherdelta, ens_old, thedao). See full key list. |
{
"exchange": "etherdelta",
"meta": {
"contract": "0x8d12A197cB00D4747a1fe03395095ce2A5CC6819",
"total_eth": 1234.56,
"contract_eth_balance": 1500.00,
"addresses_with_balance": 245119,
"coverage_pct": 99.8,
"scan_date": "2026-03-30 UTC",
"distribution": {
">=100 ETH": { "count": 10, "total_eth": 2460.18 },
"10-100 ETH": { "count": 150, "total_eth": 3560.60 },
"1-10 ETH": { "count": 1882, "total_eth": 4567.89 },
"0.1-1 ETH": { "count": 8500, "total_eth": 3200.00 },
"0.01-0.1 ETH": { "count": 45000, "total_eth": 1200.00 },
"<0.01 ETH": { "count": 189577, "total_eth": 257.89 }
},
"tvl": [
{ "date": "2018-01", "eth": 150000 },
{ "date": "2026-03", "eth": 1500 }
]
}
}
| Field | Type | Description |
|---|---|---|
| meta.distribution | object | Balance distribution across 6 tiers. Each tier has count (addresses) and total_eth |
| meta.tvl | array | Monthly historical ETH balance from deployment to present. Each entry has date (YYYY-MM) and eth |
| meta.activity | object? | Transaction activity metadata (when available): total transactions, last activity date |
Lightweight endpoint returning total tracked ETH and counts. Ideal for widgets and bots. Rate limit: 60 req/min per IP.
{
"total_eth": 157640.24,
"total_contract_eth": 159064.22,
"contract_count": 193,
"address_count": 552886,
"eth_claimed": 11496.9,
"unique_claimers": 586,
"peak_eth": 169137.14
}
| Field | Type | Description |
|---|---|---|
| total_eth | number | Total ETH mapped to known depositors |
| total_contract_eth | number | Total ETH actually held in contracts onchain (may differ from total_eth due to unmapped depositors) |
| contract_count | number | Number of tracked contracts |
| address_count | number | Total unique addresses with claimable balances across all contracts |
Static JSON listing all tracked protocols with keys, names, and categories. No rate limit.
[
{ "key": "etherdelta", "name": "EtherDelta", "contract": "0x8d12...", "category": "dex" },
{ "key": "ens_old", "name": "ENS Old Registrar", "contract": "0x6090...", "category": "other" },
{ "key": "thedao", "name": "The DAO", "contract": "0xbb9b...", "category": "ico" },
...
]
Descriptions, categories, deploy dates, theme colors, and slugs for all tracked protocols. Static file, no rate limit.
{
"etherdelta": {
"name": "EtherDelta",
"desc": "The first popular decentralized exchange on Ethereum...",
"category": "dex",
"color": "#6441a5",
"contract": "0x8d12A197cB00D4747a1fe03395095ce2A5CC6819",
"deployed": "February 2016",
"slug": "etherdelta"
},
"ens_old": {
"name": "ENS Old Registrar",
"desc": "The original ENS name registration system...",
"category": "other",
"color": "#5284ff",
"contract": "0x6090A6e47849629b7245Dfa1Ca21D94cd15878Ef",
"deployed": "May 2017",
"slug": "ens"
},
...
}
Recent verified ETH claims, drawn from up to 1,000 recorded events. Includes transaction hashes, payout chains, ENS deed names, and aggregates for the returned claims. Held items are excluded. Rate limit: 30 req/min per IP.
{
"total_claims": 251,
"unique_addresses": 43,
"total_eth": 1042.66,
"by_protocol": {
"ens_old": { "claims": 208, "eth": 763.45 },
"idex": { "claims": 14, "eth": 273.88 },
...
},
"claims": [
{
"timestamp": "2026-04-01T22:09:17.553Z",
"address": "0x5807a8b404c71cf22eb0bac2e5f2a6c202ebe0a1",
"protocol": "ens_old",
"eth": 118.811,
"tx_hash": "0xc70e253ef2445e...",
"deed_name": "wellsfargo"
},
...
]
}
| Field | Type | Description |
|---|---|---|
| total_claims | number | Number of returned claims; one transaction may settle multiple items |
| unique_addresses | number | Unique wallets that have claimed |
| total_eth | number | ETH total for the returned claims |
| by_protocol | object | Aggregate claims and ETH per protocol |
| claims[].timestamp | string | ISO 8601 timestamp. Verified L2 settlements use block time; legacy claims use recorded time |
| claims[].address | string | Wallet address that claimed |
| claims[].protocol | string | Protocol key |
| claims[].eth | number | ETH amount claimed |
| claims[].tx_hash | string | Transaction hash on the payout chain |
| claims[].payout_chain_id | number | Payout network chain ID; 1 is Ethereum, 10 Optimism, 42161 Arbitrum One |
| claims[].item_id | string? | Individual claim identity, when recorded |
| claims[].token_amount | object? | Verified payout token, symbol, decimals and exact amount_raw string for supported L2 settlements |
| claims[].deed_name | string? | ENS only. The domain name of the released deed |
All error responses follow a consistent JSON format with an error field.
| Status | Meaning | Response |
|---|---|---|
| 400 | Invalid or missing parameters | {"error": "Invalid address format"} |
| 404 | Protocol not found | {"error": "Unknown exchange"} |
| 405 | Method not allowed | {"error": "Method not allowed"} |
| 429 | Rate limit exceeded (see per-endpoint limits) | {"error": "Rate limit exceeded. Try again in 1 minute."} |
| 500 | Server error (data unavailable) | {"error": "Summary data not available"} |
All API responses include these headers:
| Header | Value | Description |
|---|---|---|
| Cache-Control | private, max-age=300 | Address checks cached for 5 min. /api/summary and /api/table use s-maxage=3600 (1h CDN cache) |
| X-Content-Type-Options | nosniff | Prevents MIME type sniffing |
| Access-Control-Allow-Origin | * | CORS enabled for all origins — call from any domain |
| Content-Type | application/json | All responses are JSON |
ETH values are in ether (not wei) unless the field name ends in _wei.coverage_pct shows what fraction of depositors we've mapped. 100% means all known depositors are indexed.scan_date field shows when each contract was last scanned./data/protocols.json or the /api/summary response./data/ are not rate-limited and can be cached freely.