Robinhood Chain Token Holders API: Live and Historical Snapshots
Get the holders of any Robinhood Chain token, live or at any past block or market cap, with cohorts and holder-count history. Code in Node.js and Python.
Crius 8 min read
The Crius token holders API returns the current holders of any ERC-20 on Robinhood Chain, and the holders as they were at any past block, timestamp, market cap or lifecycle moment, valued at that moment’s price. On top of snapshots it answers the two questions raw transfer logs make hard: which wallets held continuously through a window, and how the holder count moved over time.
This guide covers the four holder endpoints, the point-in-time syntax they share, and two complete scripts you can run against api.crius.sh today. If you only need a quick concentration check, the token profile has a holder summary; everything below is for when you need the actual wallets.
Why holder data is hard to build yourself
A token’s holder list is the running sum of every Transfer event since the contract was deployed. Computing the current list from an RPC node means replaying the whole log history; computing it as of block 84,387,222 means doing it again with a cut-off, and doing it as of “the first time market cap crossed $100k” means you also need a price for every block. On Robinhood Chain, where blocks arrive roughly every 100 ms, a busy token accumulates millions of transfers within weeks.
Crius keeps balances for every token from block 0 and replays transfer history server-side, so each of these is one HTTP request. Every response carries "history": "complete" when the token’s full history is indexed, and meta.block tells you exactly which block the answer reflects.
The four endpoints
| Endpoint | What it answers | Plan | Credits |
|---|---|---|---|
/holders |
Who holds the token right now? | Free | 2 |
/holders/snapshot |
Who held it at block N, time T or market cap X, and what did they do since? | Free | 5 |
/holders/cohort |
Who held continuously through a window without selling? | Starter | 10 |
/holders/history |
How did the number of holders change over time? | Starter | 10 |
All four live under https://api.crius.sh/v1/robinhood/token/{address}/ and need an API key in the x-api-key header. A free key covers live holders and snapshots.
Live holders
curl "https://api.crius.sh/v1/robinhood/token/0xc9675fe679c7d4e1b94416f66d61c96127eb964a/holders?limit=5" \ -H "x-api-key: $CRIUS_API_KEY"The response ranks holders by balance and labels infrastructure, because on-chain, pools and lockers are holders too. For a large token the first row is often the Uniswap v4 PoolManager, which custodies the liquidity of every v4 pool:
{ "count": 57727, "distribution": { "top10_pct": 19.8791 }, "history": "complete", "holders": [ { "rank": 1, "address": "0x8366a39cc670b4001a1121b8f6a443a643e40951", "label": "uniswap_v4_pool_manager", "balance": 50934240.59, "pct": 5.13987 }, { "rank": 2, "address": "0x8f62…80a3", "label": null, "balance": 31288190.83, "pct": 3.15735 } ]}That is a real response for one of the most-held memecoins on the chain at time of writing (Oct 2026): 57,727 holders, top ten holding about 20% of supply. When you calculate concentration, decide whether infrastructure counts. Most analyses should exclude it, which is what exclude=infra does on the historical endpoints.
Point-in-time syntax
Snapshots and cohorts share one way to name a moment:
| Form | Meaning |
|---|---|
block:84387222 |
An exact L2 block |
ts:1791572442200 |
The last block at or before a unix-millisecond time |
mcap:100000 |
The block where market cap first crossed $100k (mcap_crossing=last for the most recent crossing) |
launch, trading_open, graduation, ath, now |
Lifecycle labels |
Market-cap points are the useful ones in practice. “Holders at $100k market cap” is comparable across tokens in a way that “holders at block 84 million” is not.
Snapshots: who held at a moment, and what they did since
compare_to=now adds a compare block to every holder, with their balance now and a status of unchanged, increased, reduced or exited. Each holder also gets a cost_basis_usd and unrealized_pnl_usd from their own buys.
curl "https://api.crius.sh/v1/robinhood/token/0xc9675fe679c7d4e1b94416f66d61c96127eb964a/holders/snapshot?at=mcap:100000&compare_to=now&exclude=infra&limit=2" \ -H "x-api-key: $CRIUS_API_KEY"{ "snapshot": { "at": "mcap:100000", "block": 84387222, "ts": 1791572442200 }, "price_at_snapshot": { "usd": 0.000101365, "eth_usd": 2481.01 }, "holders_count": 206, "distribution": { "top10_pct": 18.2298, "top10_ex_infra_pct": 6.70094 }, "holders": [ { "rank": 1, "address": "0x487c…930d", "balance": 7540817.38, "pct": 0.754, "value_usd": 764.38, "cost_basis_usd": 584.52, "unrealized_pnl_usd": 179.86, "compare": { "to": "now", "balance_now": 7495997.01, "change_pct": -0.594, "status": "reduced" } }, { "rank": 2, "address": "0x4987…56ea", "balance": 7236749.46, "pct": 0.724, "compare": { "to": "now", "balance_now": 7236749.46, "change_pct": 0, "status": "unchanged" } } ]}Note the two concentration figures: the top ten held 18.2% of supply, but only 6.7% once the pool and other infrastructure are excluded.
The script below pages through the whole snapshot (meta.next_cursor) and summarises what the early holders did. It’s the basis of “are early buyers still in?” checks:
// holders.mjs: who held at $100k market cap, and what did they do since? (Node 18+)const API = "https://api.crius.sh/v1/robinhood";const KEY = process.env.CRIUS_API_KEY;const TOKEN = process.argv[2] ?? "0xc9675fe679c7d4e1b94416f66d61c96127eb964a";
async function get(path) { const res = await fetch(`${API}${path}`, { headers: { "x-api-key": KEY } }); const body = await res.json(); if (!res.ok) throw new Error(`${res.status} ${body.error?.code}: ${body.error?.message}`); return body;}
async function snapshot(at) { const holders = []; let cursor = ""; do { const q = new URLSearchParams({ at, compare_to: "now", exclude: "infra", limit: "500" }); if (cursor) q.set("cursor", cursor); const { data, meta } = await get(`/token/${TOKEN}/holders/snapshot?${q}`); holders.push(...data.holders); cursor = meta.next_cursor ?? ""; } while (cursor); return holders;}
const early = await snapshot("mcap:100000");const byStatus = {};for (const h of early) byStatus[h.compare.status] = (byStatus[h.compare.status] ?? 0) + 1;const stillIn = early.filter((h) => h.compare.balance_now > 0);console.log(`holders at $100k market cap: ${early.length}`);console.log("what they did since:", byStatus);console.log(`still holding: ${stillIn.length} (${((stillIn.length / early.length) * 100).toFixed(1)}%)`);Run against the token above, it printed:
holders at $100k market cap: 205what they did since: { reduced: 40, unchanged: 150, exited: 14, increased: 1 }still holding: 191 (93.2%)A token where most early holders are exited tells a very different story from this one, where 150 of 205 never touched their position.
Snapshots also take tag (sniper, whale, dev…), min_usd and min_pct filters, so “snipers who held at graduation” is a single request: at=graduation&tag=sniper.
Cohorts: who held through a window
A snapshot is one moment; it can’t tell a wallet that held for two weeks from one that sold and bought back an hour ago. Cohorts can. You define what counts as a holder (min_usd, min_balance or min_pct), the window (from, to), and what breaks continuity with reset_on:
sell(default): any sell resets the streakany_decrease: transfers out count toobelow_threshold: only dropping below your size threshold countsnone: just check the start and end
"""cohort.py: wallets that held at least $50 continuously from $100k market cap until now."""import os, sys, requests
API = "https://api.crius.sh/v1/robinhood"TOKEN = sys.argv[1] if len(sys.argv) > 1 else "0xc9675fe679c7d4e1b94416f66d61c96127eb964a"s = requests.Session()s.headers["x-api-key"] = os.environ["CRIUS_API_KEY"]
r = s.get(f"{API}/token/{TOKEN}/holders/cohort", params={ "from": "mcap:100000", "to": "now", "min_usd": 50, "continuous": "true", "reset_on": "sell", "exclude": "infra", "sort": "hold_time", "limit": 100,}, timeout=60)r.raise_for_status()c = r.json()["data"]print(f"qualified at the start: {c['started_qualified']}, held throughout: {c['qualified']}")for h in c["holders"][:5]: days = h["hold_time_s"] / 86400 print(f"{h['address'][:10]}… held {days:.1f} d, entry mcap ${h['entry_mcap_usd']:,.0f}, " f"PnL ${h['pnl_usd']:,.0f}, tags {h['tags']}")
hist = s.get(f"{API}/token/{TOKEN}/holders/history", params={"interval": "1d", "min_usd": 10, "exclude": "infra"}, timeout=60).json()["data"]print(f"holders >= $10: min {hist['summary']['min']}, max {hist['summary']['max']}, now {hist['summary']['now']}")Output at time of writing:
qualified at the start: 205, held throughout: 1510xbf0ba9eb… held 14.7 d, entry mcap $101,365, PnL $5,596, tags []0x369600ed… held 14.7 d, entry mcap $101,365, PnL $5,059, tags []0xf07e29f8… held 14.7 d, entry mcap $101,365, PnL $6,204, tags []holders >= $10: min 1, max 643, now 614Each cohort row carries qualified_since_block, min_balance_in_window, sells_in_window and a reset_history, so you can explain why a wallet is in or out of the list. That matters for airdrop and reward lists, where the cohort is effectively the eligibility rule.
Holder-count history
/holders/history returns columnar arrays per interval (t, holders, min, max, new, exited) using your definition of a holder. Two details worth knowing:
min_usdis converted at the current price. “At least $10” means at least the number of tokens worth $10 today, applied to every interval, so the definition doesn’t drift with price.newandexitedcount crossings, not net change. On an actively traded token, wallets cross your threshold many times a day, so these can be far larger than the change inholders. Useholders(orminandmax) for the curve and the crossings to gauge churn.
Limits to plan around
- Very large tokens. Historical replays (snapshots at a past point, cohorts) are not available for tokens with more than about 2 million transfers. The API answers
window_too_largeand points you to live/holders. On Robinhood Chain that means a handful of the largest assets. - Heavy endpoints. Snapshots, cohorts and history are computed on demand. Keep concurrency modest (a few requests in flight per key), cache results for at least 30 seconds, and retry
503responses after theirRetry-After. - Infrastructure. Always decide on
exclude=infra; it changes concentration numbers dramatically, as the 18.2% vs 6.7% example shows.
Frequently asked questions
Can I get the holders of a token at a specific past block?
Yes. Call /holders/snapshot?at=block:<number>, or use ts:<unix ms> for a time. The response is valued at that block’s price and includes compare_to=now changes if you ask for them.
How do I get holders at a market cap level instead of a block?
Use at=mcap:<usd>. By default this is the first block where the token’s market cap crossed that level; mcap_crossing=last picks the most recent crossing.
Does the holder count include liquidity pools and burn addresses?
The live list includes them, labelled. Historical endpoints accept exclude=infra to leave out pools, LP lockers, launchpad contracts, routers and burn addresses. The snapshot response reports concentration both ways.
How far back does holder history go?
To block 0. Crius indexes Robinhood Chain from genesis, and responses mark "history": "complete" when a token’s full history is available.
Which plan do I need?
Live holders and snapshots work on the Free plan. Cohorts and holder-count history need Starter or higher. See plans and limits.
Related
- Product overview: token holders API and historical data
- Reference: holders & traders, conventions
- Guides: holder analysis and bubble maps, detecting bundles and snipers, smart money and top traders
Build with Crius
Robinhood Chain data in one API
Free plan with 1M credits a month. Your key in under a minute.
More from the blog
- OHLCVCandles
How to Fetch Historical OHLCV Candles on Robinhood Chain
Fetch historical OHLCV candles for any Robinhood Chain token: intervals from 1s to 1d, paging with to_ts, pool selection, gap filling and clean wicks.
- HoldersAnalytics
Holder analysis on Robinhood Chain: snapshots, diamond hands and bubble maps
How to analyse a token's holders on Robinhood Chain: live concentration, holders at any past block or market cap, wallets that held through a window, and bubble maps of connected wallets.
- TutorialHistorical data
How to Get All Robinhood Chain Transactions Without Running a Node
Export every trade, transfer and liquidity event for a Robinhood Chain token or wallet with an indexed API. Tested Python and Node.js, no archive node.