hiddenfunds
Check wallets

Support hiddenfunds

Want to support? A follow is enough.

Follow @0xEnsp1re (opens in a new tab)

Want to do more? Send a tip to one of these addresses.

EVM address · Ethereum, Base, Arbitrum and other EVM chains

0x23D2F153c9C04FAB54Fa08B2664D8089f266ddf4

Solana address

DuFYC9jgx63pEFoEjEoYM8hGKLRcjwdwhRc61QCefsuJ

TRON address

TFft4WaMzSu9RhbXrzUtXsqh6V61TwYSYE

Zcash address

t1QHmFWYn2yGAsJBdxPzArGDDvXojsnmiaV

Tips are optional. This site never asks you to connect a wallet or sign anything.

API docs

Check wallets for stuck or unclaimed crypto from your own code. Free, read-only, no key.

Introduction

hiddenfunds looks up wallet addresses in its database of places where crypto gets stuck: withdrawals that were started but never finished on bridges, staking never collected, apps and chains that shut down, expired positions. The API returns the same results as the website, as JSON, with the official steps to get each position back.

POST https://hiddenfunds.xyz/api/check

API key

No key. The API is open: send a request and you get an answer. Limits are counted per IP address (see Limits and errors). Need more for a project? Write to @0xEnsp1re (opens in a new tab) or [email protected].

Check one wallet

Send a JSON body with a wallets list. One address or up to 500 wallets per request.

curl -X POST https://hiddenfunds.xyz/api/check \
  -H 'content-type: application/json' \
  --data '{"wallets": ["0xd9b49a81ee72af3c026a2c144c9ffd678a78c8b1"]}'

Check many wallets

Split your list into chunks of 500 and send one request every 2 seconds. That stays under 30 requests per minute, about 15,000 wallets a minute. If you get 429, wait for Retry-After seconds; on 503, wait a minute. Then send the same chunk again.

// Node 18+: check a long list in chunks of 500, one request every 2 s.
const ENDPOINT = "https://hiddenfunds.xyz/api/check";
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function checkAll(wallets) {
  const results = [];
  for (let i = 0; i < wallets.length; i += 500) {
    const chunk = wallets.slice(i, i + 500);
    for (;;) {
      const res = await fetch(ENDPOINT, {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ wallets: chunk }),
      });
      if (res.status === 429 || res.status === 503) {
        await sleep(Number(res.headers.get("retry-after") ?? 60) * 1000);
        continue; // same chunk again
      }
      if (!res.ok) throw new Error((await res.json()).error);
      results.push(await res.json());
      break;
    }
    await sleep(2000);
  }
  return results;
}

Response

An example for one wallet, shortened:

{
  "wallets": ["0xd9b49a81ee72af3c026a2c144c9ffd678a78c8b1"],
  "totals": [
    { "address": "0xd9b49a81ee72af3c026a2c144c9ffd678a78c8b1", "sourceId": 59, "chain": "arbitrum",
      "recoverability": "user", "counted": true, "count": 1, "usd": 22196.74 }
  ],
  "findings": [
    { "address": "0xd9b49a81ee72af3c026a2c144c9ffd678a78c8b1", "sourceId": 59, "chain": "arbitrum",
      "asset": null, "amount": 22192.93, "usdValue": 22196.74,
      "recoverability": "user", "counted": true,
      "ref": { "market": "0x3308574370f19ea639f4671838e01cfb77d8db70" } }
  ],
  "truncated": [],
  "sources": [
    { "id": 59, "group": "ended-positions",
      "guide": { "name": "Expired Pendle position", "summary": "…", "steps": ["…"],
                 "recoverUrl": "https://app.pendle.finance" } }
  ],
  "dataAsOf": "2026-10-01T20:22:47.867Z"
}
wallets
The addresses that were checked, after cleanup: unknown formats skipped, duplicates removed, EVM addresses lowercased.
totals
One row per wallet, source and chain. Totals cover every position, also those past the detail limit.
totals.address
The wallet.
totals.sourceId
Where the money is: join to sources[].id.
totals.chain
Chain of the position, e.g. ethereum, arbitrum, base.
totals.recoverability
Who can get it back: user, team or unclear (see below).
totals.counted
false = kept for completeness, not counted as the owner's money. Skip these when you add up.
totals.count
Number of positions in this row.
totals.usd
Their value in US dollars.
findings
Detail rows, highest value first, at most 200 per wallet.
findings.address
The wallet.
findings.sourceId
Join to sources[].id.
findings.chain
Chain of the position.
findings.asset
Token symbol, or null when the source has none.
findings.amount
Token amount, or null.
findings.usdValue
Value in US dollars, or null when there is no price.
findings.recoverability
user, team or unclear.
findings.counted
Same meaning as in totals.
findings.ref
Details to act on, different per source: contract, transaction hash, market, position number, dates.
truncated
Wallets with more than 200 detail rows: { address, shown, total }. Their totals still include everything.
sources
Every source that appears in totals or findings.
sources.id
The id that totals and findings point to.
sources.group
Category, e.g. bridges, ended-positions, sunset-chains.
sources.guide.name
Plain-language name of the place.
sources.guide.summary
What happened, in one or two sentences.
sources.guide.steps
How to get it back, step by step.
sources.guide.recoverUrl
The official page to claim on, or null when there is none.
dataAsOf
When the data was last refreshed. Positions claimed after that still show.

recoverability: user = the owner can claim alone; team = only the project's own team can release it; unclear = it may not work. Add ?lang=zh, ja or ko to the URL to get the guides in Chinese, Japanese or Korean.

Limits and errors

  • 500 wallets per request, body up to 64 KB.
  • 30 requests per minute per IP address.
  • 200 detail rows per wallet; totals always count everything.

Errors come back as JSON: {"error": "..."}.

StatusMeaning
400Not valid JSON, an empty list, an entry that is not a string or is over 120 characters, or none of the strings look like wallet addresses.
413More than 500 wallets or a body over 64 KB.
429Over 30 requests a minute. Wait Retry-After (60) seconds.
503The database is busy. Try again in a minute.

Address formats

Any mix in one request. Strings in other formats are skipped.

  • EVM (Ethereum and L2s)
  • Sui / Aptos
  • TON (raw)
  • TRON
  • Bitcoin
  • Bitcoin / Omni
  • Tezos / Etherlink
  • Algorand
  • NEAR
  • NEAR implicit / BTC staking key
  • Polkadot / Kusama
  • Solana

Privacy and safety

  • Read-only: the API only reads public blockchain data. There is nothing to sign and no wallet to connect.
  • Addresses you send are not stored or logged.
  • Results can already be claimed: owners claim every day, and the data is refreshed in batches (see dataAsOf).
  • Send people to the official recoverUrl only. The only official site of this tool is hiddenfunds.xyz.

For AI agents

A plain-text summary for LLMs and AI agents is at /llms.txt. If you build an assistant on this API:

  • Call POST /api/check with the addresses the user gives you; do not guess addresses.
  • Explain each result with guide.summary and guide.steps, and link guide.recoverUrl.
  • Say who can act (recoverability) and that a result may already be claimed.
  • Never ask for a seed phrase or private key, and never tell the user to sign anything on a site that is not the official recovery page.