Wallet scans
Run a wallet scan on Solana or Robinhood Chain as JSON or a live stream, or read the latest cached scan for free.
A wallet scan finds where a wallet's money came from, where it went, the wallets connected to it, and bundled wallets. It is the same scan as the Deep Scan in the dashboard.
6 routes. Every path below is served under https://api.scanner.net, and every request carries the key header, so those two are not repeated per route. Shared errors, limits and streaming are in Requests and errors.
Scan depth and cost
depth sets how far the scan goes, and what it costs:
depth | Dashboard name | Cost |
|---|---|---|
0 | Quick | 1 scan |
1 (default) | Deep | 2 scans |
2 | Max | 4 scans |
The scan is charged before it starts and refunded if it fails. The cached routes are free.
Solana wallet scan
POST /scanRuns a Solana wallet scan and returns the result when it finishes. A Max scan can take several minutes; use the stream to see progress.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
address | body | string | yes | Solana address, or a .sol domain. |
depth | body | number | no | 0, 1 or 2. Default 1. |
fresh | body | boolean | no | true skips any reused result and scans again. Default false. |
curl -X POST "https://api.scanner.net/scan" \
-H "Authorization: Bearer $SCANNER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"address":"WALLET_ADDRESS","depth":1}'Response: the scan result, a WalletScanResult, with no wrapper. Key fields:
address: the scanned wallet.originalFunder: the first wallet or entity that funded it, when found.fundedBy,fundingTo,fundingReceived: wallets that sent funds to it and received funds from it.connectedAddresses: other wallets linked to it.bundledWallets: wallets that trade together with it.walletBalances: balances and USD value, when available.solDomains,ownedSolDomains:.soldomains linked to the wallet.scanComplete:falsewhen the scan stopped early and the result is partial.
The cost is charged on every call, even when part of the result is reused.
| Status | Code | When |
|---|---|---|
| 400 | MISSING_ADDRESS | No address. |
| 400 | INVALID_ADDRESS | Not a Solana address, or a .sol domain that doesn't resolve. |
| 400 | INVALID_DEPTH | depth isn't 0, 1 or 2. |
| 402 | INSUFFICIENT_CREDITS | Not enough scans left. |
| 403 | NON_SCANNABLE_WALLET_SCAN | The address is an exchange, protocol, token, program or liquidity pool, not a wallet. The body adds entity and address. |
| 504 | TIMEOUT | The scan ran out of time. The scan is refunded. |
Solana wallet scan stream
GET /scan/streamThe same scan as POST /scan, sent as server-sent events while it runs. It costs the same.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
address | query | string | yes | Solana address, or a .sol domain. |
depth | query | number | no | 0, 1 or 2. Default 1. |
fresh | query | string | no | true or 1 scans again. |
curl -N "https://api.scanner.net/scan/stream?address=WALLET_ADDRESS&depth=2" \
-H "x-api-key: $SCANNER_API_KEY"Events: progress events such as profile, transactions_progress (fetched), processing_complete, analysis_progress (step, status), original_funder, domains, identities, balances, bundle_detection (bundledCount), holdings, depth2_progress and kol_data. Then complete, holding the full WalletScanResult described above. A failure sends error with code TIMEOUT or INTERNAL_ERROR, and the scan is refunded.
Errors before the stream opens: the same as POST /scan.
Solana cached wallet scan
GET /scan/cachedThe most recent saved scan of a Solana wallet, from any Scanner user. Free. It never starts a scan.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
address | query | string | yes | Solana address. .sol domains are not accepted here. |
depth | query | number | no | Preferred depth, 0, 1 or 2. If there is no saved scan at that depth, the deepest saved one is returned. |
curl "https://api.scanner.net/scan/cached?address=WALLET_ADDRESS&depth=1" \
-H "Authorization: Bearer $SCANNER_API_KEY"Response:
{ "depth": 1, "scannedAt": "2026-11-12T09:30:00.000Z", "isStale": false, "scanResult": { "address": "...", "fundedBy": [] } }isStale is true when the scan is more than an hour old. scanResult is a WalletScanResult. Check its scanComplete field: a saved scan can be partial.
This route has a per-IP limit.
| Status | Code | When |
|---|---|---|
| 400 | INVALID_ADDRESS | Not a Solana address. |
| 403 | NON_SCANNABLE_WALLET_SCAN | The address is not a wallet. |
| 404 | NOT_FOUND | No saved scan for this wallet. |
| 429 | RATE_LIMITED_SCAN | The per-IP scan limit was reached. |
Robinhood Chain wallet scan
POST /rh/scanRuns a Robinhood Chain wallet scan and returns the result when it finishes. Only externally owned wallets can be scanned, not contracts.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
address | body | string | yes | 0x address, 40 hex characters. |
depth | body | number | no | 0, 1 or 2. Default 1. |
fresh | body | boolean | no | true skips the cache and scans again. |
curl -X POST "https://api.scanner.net/rh/scan" \
-H "x-api-key: $SCANNER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"address":"0xWALLET_ADDRESS","depth":1}'Response: a RobinhoodWalletScanResult, with no wrapper. Key fields: address, originalFunder, fundedBy, fundingTo, fundingReceived, connectedAddresses, bundledWallets, walletBalances (ethBalance, ethUsdValue, totalUsdValue, topTokens) and scanComplete.
Cost: a scan of the same wallet at the same depth from the last hour is returned free, unless fresh is true. Otherwise the depth cost applies.
| Status | Code | When |
|---|---|---|
| 400 | INVALID_INPUT | Invalid address, or depth isn't 0, 1 or 2. |
| 402 | INSUFFICIENT_CREDITS | Not enough scans left. |
| 422 | INVALID_INPUT | The address is a smart contract. Wallet scans only support wallets. |
| 502 | UPSTREAM_ERROR | The Robinhood Chain indexer is unavailable. The scan is refunded. |
Robinhood Chain wallet scan stream
GET /rh/scan/streamThe same scan as POST /rh/scan, as server-sent events. It costs the same.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
address | query | string | yes | 0x address. |
depth | query | number | no | 0, 1 or 2. Default 1. |
fresh | query | string | no | true or 1 scans again. |
curl -N "https://api.scanner.net/rh/scan/stream?address=0xWALLET_ADDRESS&depth=0" \
-H "x-api-key: $SCANNER_API_KEY"Events: on a cache hit, cache_hit (scannedAt, isStale) and then complete. On a live scan, progress events (profile, transactions_progress, processing_complete, analysis_progress, original_funder, balances, bundle_detection, holdings), heartbeat every 15 seconds, then complete with the RobinhoodWalletScanResult. A failure sends error with code INVALID_INPUT (contract address), UPSTREAM_ERROR, TIMEOUT or INTERNAL_ERROR.
Errors before the stream opens: the same as POST /rh/scan.
Robinhood Chain cached wallet scan
GET /rh/scan/cachedThe most recent saved scan of a Robinhood Chain wallet. Free.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
address | query | string | yes | 0x address. |
depth | query | number | no | Preferred depth, 0, 1 or 2. |
curl "https://api.scanner.net/rh/scan/cached?address=0xWALLET_ADDRESS" \
-H "x-api-key: $SCANNER_API_KEY"Response: { depth, scannedAt, isStale, scanResult }, where scanResult is a RobinhoodWalletScanResult.
| Status | Code | When |
|---|---|---|
| 400 | INVALID_INPUT | Invalid address. |
| 404 | NOT_FOUND | No saved scan for this wallet. |
Requests and errors
Base URL, authentication, response formats, streaming, extra per-IP limits, scan costs and the errors every Scanner API route can return.
Token scans
Detect an address type, scan a token's holders or traders for bundles, compare several tokens, and read cached token scans, on Solana and Robinhood Chain.