Forgotten ΞTH

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.

Base URL https://forgotteneth.com

Bulk Address Lookup

FILE data/index_shards/{prefix}.json

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.

How it works

  • data/index_shards/meta.json — protocol metadata (contract address, coverage, scan date)
  • data/index_shards/{prefix}.json — 256 shards (00.jsonff.json), keyed by the first two hex chars of the lowercased address
  • Each shard is a flat object: { "0x<full address>": { "<protocol_key>": "<balance_eth>" } }
  • Regenerated every scheduled refresh

Examples

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

Bulk scanning a wallet list

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).

Why no live /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.

Summary

GET /api/summary

Overview of all tracked contracts with ETH balances, address counts, and coverage percentages. Rate limit: 30 req/min per IP.

Response

{
  "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"
    },
    ...
  }
}

Response Fields

FieldTypeDescription
total_ethnumberSum of all mapped depositor balances across all protocols
contract_countnumberNumber of tracked contracts
contracts.*.total_ethnumberTotal ETH mapped to known depositors in this contract
contracts.*.contract_eth_balancenumberActual ETH balance of the contract onchain
contracts.*.addresses_with_balancenumberNumber of depositors with non-zero balances
contracts.*.coverage_pctnumberPercentage of contract ETH mapped to known depositors (total_eth / contract_eth_balance * 100)
contracts.*.scan_datestringWhen this contract was last scanned (UTC date)

Protocol Detail

GET /api/table?exchange=...

Detailed metadata for a single protocol: balances, coverage, balance distribution, and monthly TVL history. Rate limit: 60 req/min per IP.

ParameterTypeDescription
exchangestringProtocol key (e.g. etherdelta, ens_old, thedao). See full key list.

Response

{
  "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 }
    ]
  }
}

Response Fields

FieldTypeDescription
meta.distributionobjectBalance distribution across 6 tiers. Each tier has count (addresses) and total_eth
meta.tvlarrayMonthly historical ETH balance from deployment to present. Each entry has date (YYYY-MM) and eth
meta.activityobject?Transaction activity metadata (when available): total transactions, last activity date

Total

GET /api/total

Lightweight endpoint returning total tracked ETH and counts. Ideal for widgets and bots. Rate limit: 60 req/min per IP.

Response

{
  "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
}

Response Fields

FieldTypeDescription
total_ethnumberTotal ETH mapped to known depositors
total_contract_ethnumberTotal ETH actually held in contracts onchain (may differ from total_eth due to unmapped depositors)
contract_countnumberNumber of tracked contracts
address_countnumberTotal unique addresses with claimable balances across all contracts

Protocol List

STATIC /data/protocols.json

Static JSON listing all tracked protocols with keys, names, and categories. No rate limit.

Response

[
  { "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" },
  ...
]

Protocol Info

STATIC /data/protocol_info.json

Descriptions, categories, deploy dates, theme colors, and slugs for all tracked protocols. Static file, no rate limit.

Response

{
  "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"
  },
  ...
}

Claims

GET /api/claims

All verified ETH claims made through the site. Includes per-claim tx hashes, ENS deed names, and per-protocol aggregates. Rate limit: 30 req/min per IP.

Response

{
  "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"
    },
    ...
  ]
}

Response Fields

FieldTypeDescription
total_claimsnumberTotal number of claim transactions
unique_addressesnumberUnique wallets that have claimed
total_ethnumberTotal ETH claimed across all transactions
by_protocolobjectAggregate claims and ETH per protocol
claims[].timestampstringISO 8601 timestamp of the claim
claims[].addressstringWallet address that claimed
claims[].protocolstringProtocol key
claims[].ethnumberETH amount claimed
claims[].tx_hashstringEthereum transaction hash (verifiable on Etherscan)
claims[].deed_namestring?ENS only. The domain name of the released deed

Error Responses

All error responses follow a consistent JSON format with an error field.

StatusMeaningResponse
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"}

Response Headers

All API responses include these headers:

HeaderValueDescription
Cache-Controlprivate, max-age=300Address checks cached for 5 min. /api/summary and /api/table use s-maxage=3600 (1h CDN cache)
X-Content-Type-OptionsnosniffPrevents MIME type sniffing
Access-Control-Allow-Origin*CORS enabled for all origins — call from any domain
Content-Typeapplication/jsonAll responses are JSON

Notes

  • All 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.
  • Data refreshes on the scheduled refresh cycle. The scan_date field shows when each contract was last scanned.
  • Per-address lookups are served from the sharded JSON index on GitHub, not a live API. All endpoints below return aggregate data only.
  • For protocol keys, see /data/protocols.json or the /api/summary response.
  • Static files under /data/ are not rate-limited and can be cached freely.