Solana Token Holders API
Get real-time and historical token holder data for any SPL token on Solana. Bitquery provides two approaches to retrieve token holders; choose the one that fits your use case.
Can I get Solana token holder data using Bitquery?
Yes. Bitquery exposes Solana SPL holder analytics via GraphQL: use V1 transfer-based aggregates for full history and top holders, or V2 BalanceUpdates for fast snapshots on recently active tokens (roughly the last hours of balance updates). Pick V1 for long-lived tokens and trends; V2 for brand-new launches and near-real-time rankings.
How do I track whale wallets and their token holdings on Solana?
Use the V1 holder query to list the largest wallets by net balance, or V2 BalanceUpdates ranked by the sum of each wallet's balance changes for fresh launches. Set a minimum holding or post-process balances to focus on whales, then correlate with Solana transfers or DEX trades for accumulation or distribution.
Choosing the Right API
Bitquery provides two versions of Solana APIs, each with different strengths for retrieving token holder data:
| Feature | V1 API (Transfers) | V2 API (Balance Updates) |
|---|---|---|
| Data coverage | Complete historical data from token launch | Last ~8 hours of balance updates |
| Best for | Any token, any age | Newly launched tokens (< 8 hours old) |
| Data freshness | About 10 minutes behind real-time; the newest blocks can be incomplete | Real-time |
| Method | Tokens received minus tokens sent, per address, over the whole transfer history | Sum of each wallet's balance changes inside the window |
| Query complexity | Two sums (inflow by receiver, outflow by sender), joined in your code | One sum, ranked on the server: sum(of: BalanceUpdate_Amount) |
| Ideal use cases | Tokens older than 8 hours, historical holder analysis, whale tracking | Tokens launched within the last 8 hours, Pump.fun launches, fast holder snapshots |
- Token launched more than 8 hours ago → Use V1 API (complete history)
- Token launched within the last 8 hours → Use V2 API (faster, simpler)
- Need both speed and history → Combine both: V2 for the latest snapshot, V1 for historical trends
V1 API — Historical Token Holders via Transfers
The V1 API works out each address's balance from its full transfer history: tokens received minus tokens sent. It covers any token, whatever its launch date.
Strengths:
- Full historical coverage from token genesis
- Works for any SPL token, any age
- Balances computed from on-chain transfer history
Limitation:
- Data lags about 10 minutes behind real-time, and the newest blocks can be incomplete, so a token launched in the last hour can show partial or negative balances. Use V2 for tokens under ~8 hours old.
For more V1 Solana transfer examples, see the V1 Solana Transfers documentation.
Top Token Holders
Get the top holders for any SPL token by calculating net balances from transfer history.
Try it live: Solana Token Holders V1
query TopHoldersV1($token: String!, $since: ISO8601DateTime) {
solana(network: solana) {
inflow: transfers(
currency: { is: $token }
date: { since: $since }
success: { is: true }
options: { limit: 25000, asc: "receiver.address" }
) {
receiver {
address
}
amount(calculate: sum)
}
outflow: transfers(
currency: { is: $token }
date: { since: $since }
success: { is: true }
options: { limit: 25000, asc: "sender.address" }
) {
sender {
address
}
amount(calculate: sum)
}
}
}
{
"token": "943YczGfS95e1ZnUSMd5DPQrGXaKBS2zGR76htycpump",
"since": "2026-02-19"
}
How This Query Works
inflowgroups the token's transfers by receiver and sums what each address received.outflowgroups the same transfers by sender and sums what each address sent.- Balance is inflow minus outflow for each address. Join the two lists on the address in your code, then sort by balance.
- The empty address in
outflowis the mint. Drop empty addresses from both lists, and drop addresses whose balance is zero or below. - Amounts are raw units. Divide by
10^decimals(6 for Pump.fun tokens).
Set since to the launch date or earlier. A later date leaves out the first transfers, and every balance that depends on them comes out wrong.
Both sums must come from separate aliases. A single query that puts sum_in: amount(calculate: sum) and sum_out: amount(calculate: sum) on the same row reads the same transfers twice, so sum_in - sum_out is 0 for every address.
Customization Options
Balances at a past date: add till to the date filter of both aliases:
date: { since: "2026-02-19", till: "2026-03-01" }
More addresses: each alias returns up to its limit. For a token with more addresses than that, page through with offset, keeping the sort on the address so pages do not overlap (use sender.address in outflow):
options: { limit: 25000, offset: 25000, asc: "receiver.address" }
Current holders only: after the join, keep addresses whose inflow minus outflow is above zero.
V2 API — Real-Time Token Holders via Balance Updates
The V2 API reads Solana's balance update records in real time. It keeps only the last ~8 hours, so it gives a full holder list only for a token launched inside that window.
Strengths:
- Real-time data with minimal delay
- One query, ranked on the server; no join in your code
- Great for newly launched tokens and fast-moving markets
Limitation:
- Only covers the last ~8 hours of balance updates
- Best suited for tokens launched within that window
Top Token Holders
Get the top 50 holders of a token launched within the last ~8 hours.
Try it live: Solana Token Holders V2
query TopHolders($token: String!) {
Solana(dataset: realtime) {
BalanceUpdates(
limit: { count: 50 }
orderBy: { descendingByField: "Holding" }
where: {
BalanceUpdate: { Currency: { MintAddress: { is: $token, not: "" } } }
Transaction: { Result: { Success: true } }
}
) {
BalanceUpdate {
Account {
Owner
}
}
Holding: sum(of: BalanceUpdate_Amount)
}
}
}
{
"token": "token mint address"
}
How This Query Works
- Fetches every balance change of the token inside the real-time window, from successful transactions only.
- Groups by
Account.Owner, so each row is one wallet with all its token accounts together. sum(of: BalanceUpdate_Amount)adds up each wallet's changes. For a token launched inside the window, that sum is the wallet's current balance, and a wallet that sold everything sums to 0.- Sorted by holding, largest first. Amounts are already in token units.
Do not rank holders with PostBalance(maximum: Block_Slot). It takes the balance at the highest slot, and an account can change several times in one slot. At a Pump.fun graduation a SOL-paired bonding curve goes from 206,900,000 tokens to 0 in one slot, and a wallet can sell out in several transactions in one slot. In our tests on Pump.fun tokens that graduated on 8 October 2026, that query showed emptied bonding curves and sold-out wallets holding 57,680,000 to 383,635,727 tokens; the true balance of each was 0. Adding PostBalance: { gt: "0" } makes it worse: an account that sold out keeps its last nonzero balance.
To read one wallet's current balance, take its latest row ordered by slot and then transaction index, as in the developer holdings query.
Customization Options
Get more holders: raise the limit.
limit: { count: 200 }
Filter by minimum balance: keep only wallets above a threshold.
Holding: sum(of: BalanceUpdate_Amount, selectWhere: { gt: "1000000" })
Do not filter PostBalance in where. That drops balance changes, and the sums stop matching the balances.
Use Cases
Whale tracking (largest holders)
Monitor large holders and track their accumulation or distribution patterns. Use V1 for historical whale behavior or V2 for real-time whale alerts on new tokens. See How do I track whale wallets and their token holdings on Solana? above for the query approach.
Token Distribution Analysis
Analyze how evenly a token is distributed across holders. Calculate metrics like the Gini coefficient or top-10 holder concentration to assess decentralization.
New Token Launch Monitoring
Track holder growth for newly launched tokens (especially Pump.fun launches). Use V2 for instant holder snapshots within the first 8 hours.
Holder Count Over Time
Use V1 to track how the number of unique holders changes over different date ranges, revealing adoption trends.
Airdrop Verification
Verify that airdrop recipients actually hold the tokens by querying current balances.
Smart Money Tracking
Identify wallets that consistently hold tokens early in successful launches. Cross-reference with the Solana Trader API for deeper analysis.
Best Practices
- Choose the right API for your use case — V1 for historical/complete data, V2 for speed on new tokens
- Set appropriate date ranges in V1 — Narrower ranges reduce query complexity and points consumed
- Filter out zero balances — Exclude wallets that have sold all tokens for cleaner results
- Account for token decimals — Raw balances need to be divided by
10^decimalsfor human-readable amounts - Exclude known program accounts — Filter out system programs, DEX pools, and bridge contracts for accurate retail holder counts
- Cache results — Token holder data doesn't change every second; cache for 1–5 minutes to reduce API usage
- Combine V1 and V2 — Use V2 for the latest snapshot and V1 for historical trend analysis
Related APIs
- Solana Balance Updates API — Real-time balance change monitoring
- Solana Transfers API — Track token transfers
- Solana DEX Trades API — Trading activity for tokens
- Solana Trader API — Trader analytics and smart money tracking
- Solana Token Supply API — Token supply data
- Pump.fun API — Pump.fun token data
Support
For questions or issues:
Ready to run this in production?
Get an API key and run these queries in minutes, or talk to us about plans and enterprise delivery.