Hyperliquid Snapshots API
About every 12.5 minutes, Bitquery takes a snapshot of the full Hyperliquid exchange state and serves it through eleven Snapshot* cubes: every open position with its entry price, leverage, margin and unrealized PnL, every account, every resting order with its owner, every waiting stop and take-profit order, every spot balance, every leverage setting, every vault with its depositors, and Earn. All accounts at once, kept for 7 days.
Hyperliquid's own info API returns this state one address at a time (clearinghouseState, openOrders, spotClearinghouseState), so you have to know the address first. Snapshots answer the market-wide questions: who holds the biggest positions and at what entry, how the crowd is positioned against the whales, where the stops sit, who owns the walls in the book, who holds a token.
Snapshots are kept for about 7 days. A new snapshot appears about every 12.5 minutes. The cubes are query-only: there is no subscription, so poll at that pace and compare Block.Number to see whether a new snapshot has arrived.
To query or stream data outside the Bitquery IDE, you need an API access token.
Follow the steps here: How to generate Bitquery API token ➤
The snapshot cubes
| Cube | One row per | Use it for |
|---|---|---|
Snapshots | snapshot | the list of snapshots in the window: Block { Number Time } |
SnapshotMarkets | market | mark, oracle and external perp prices, best bid and ask, last trade, open interest, number of positions, margin tiers, halts, prediction market names |
SnapshotPositions | open perp position (trader × market) | side, size, entry price, leverage, margin, position value, unrealized PnL, cumulative funding |
SnapshotAccounts | account × perp dex | account value, margin used, maintenance margin, notional, number of positions |
SnapshotOrders | resting order or waiting trigger order | the order book with owners (L4), queue position, stop-loss and take-profit orders |
SnapshotBalances | non-zero spot balance (trader × token) | token holders, spot portfolios, entry notional |
SnapshotLeverageSettings | trader × perp market the trader touched | leverage and margin mode set, and what the next trade gets |
SnapshotVaults | vault | name, leader, equity, number of followers, commission, parent and child vaults |
SnapshotVaultFollowers | depositor × vault | share, equity, net deposit, all-time PnL, lockup |
SnapshotEarnReserves | Earn token | supplied, borrowed, utilization, rate model |
SnapshotEarnPositions | trader × Earn token | supply and borrow, basis and value |
A vault trades as its own account: its positions, margin and orders are the rows whose Trader.Address is the vault address, and IsVault: true marks them.
Which snapshot a query reads
The time filter on Block.Time decides which snapshots answer:
| Filter | Reads |
|---|---|
no Block.Time filter | the latest complete snapshot |
Block: {Time: {at: "..."}} with a time in the last 7 days | the latest complete snapshot at or before that time: the state at that moment |
Block: {Time: {since: "...", till: "..."}} (or any other range) | every complete snapshot in the range: a history |
A query only ever sees complete snapshots. All rows of one snapshot share Block.Number and Block.Time, so add Block { Number Time } to know which one answered. A Block.Number filter narrows what Block.Time selected: on its own it meets only the latest snapshot, so for an older height add Time too, or use at.
List the snapshots of the last few hours:
query {
Hyperliquid {
Snapshots(
where: {Block: {Time: {since_relative: {hours_ago: 3}}}}
orderBy: {descending: Block_Time}
) {
Block { Number Time }
}
}
}
Biggest positions with entry price and unrealized PnL
The largest positions on BTC by value, long and short, with entry price, leverage, margin mode, unrealized PnL and the funding paid since the position was opened. Position.Size is signed (negative = short), so rank by Valuation.PositionValue, the position's USD value at the snapshot's mark price.
query {
Hyperliquid {
SnapshotPositions(
where: {Market: {CoinRaw: {is: "BTC"}}}
orderBy: {descending: Valuation_PositionValue}
limit: {count: 20}
) {
Block { Number Time }
Trader { Address }
IsVault
Position { Side Size EntryPrice Leverage IsCross }
Valuation { EntryNotional PositionValue UnrealizedPnl MarkPx }
CumFunding { SinceOpen AllTime }
Margin { MarginUsed MaintenanceMargin }
}
}
}
CumFundingis positive when the account paid funding and negative when it received it: the opposite sign toFunding.AmountonPerpFundings.Position.Leverageis the leverage of the position, so grouping by it shows how leveraged a market is.SnapshotLeverageSettingsis the per-account setting, including markets with no open position.- Filter
Position: {Side: {is: "Short"}}for the shorts alone, orTrader: {Address: {is: "0x..."}}for one account.
Crowd vs whales: the long / short split of a market
Group the positions of one market by side: how many accounts are long and short, the total size and value of each side, and their unrealized PnL. A side with most of the accounts but a smaller share of the value is the crowd; the other is where the large positions are.
query {
Hyperliquid {
SnapshotPositions(where: {Market: {CoinRaw: {is: "BTC"}}}) {
Position { Side }
positions: count
size: sum(of: Position_Size)
value: sum(of: Valuation_PositionValue)
upnl: sum(of: Valuation_UnrealizedPnl)
}
}
}
The same split over time: with a since filter every snapshot answers, and grouping by Block.Time gives one row per snapshot.
query {
Hyperliquid {
SnapshotPositions(
where: {Market: {CoinRaw: {is: "BTC"}}, Block: {Time: {since_relative: {days_ago: 3}}}}
orderBy: {ascending: Block_Time}
limit: {count: 2000}
) {
Block { Time }
longs: count(if: {Position: {Side: {is: "Long"}}})
shorts: count(if: {Position: {Side: {is: "Short"}}})
longValue: sum(of: Valuation_PositionValue, if: {Position: {Side: {is: "Long"}}})
shortValue: sum(of: Valuation_PositionValue, if: {Position: {Side: {is: "Short"}}})
}
}
}
Open interest and prices of every market
SnapshotMarkets has one row per market: prices, the top of the book, open interest and the number of open positions.
query {
Hyperliquid {
SnapshotMarkets(
where: {Market: {IsPerp: true}}
orderBy: {descending: Positions}
limit: {count: 50}
) {
Block { Number Time }
Market { Symbol CoinRaw Kind Protocol MaxLeverage }
Prices { MarkPx OraclePx ExternalPerpPx }
Book { BestBid BestAsk LastTradePx Orders }
OpenInterest
Positions
IsHalted
}
}
}
OpenInterestcounts both sides: it is longs plus shorts, in coins (the sum of the absolute size of every position), so it is twice the open interest of one side. Divide by 2 for the figure most venues quote, and multiply byPrices.MarkPxfor USD.Margin,PricesandOpenInterestare perp-only (native and HIP-3) and empty on spot and prediction markets.Margin { Tiers { LowerBound MaxLeverage MaintenanceDeduction } }are the margin tiers: fromLowerBoundof position notional (USD) on,MaxLeverageapplies.
Stop-loss and take-profit map
Waiting trigger orders (IsTrigger: true) are not in the public book, so no L2 feed shows them. In a snapshot every one is listed with its owner: where the stops and take-profits of a market sit, and whose they are.
query {
Hyperliquid {
SnapshotOrders(
where: {Market: {CoinRaw: {is: "BTC"}}, IsTrigger: true, TriggerPx: {ge: "70000", le: "85000"}}
orderBy: {descending: Size}
limit: {count: 1000}
) {
Block { Time }
Trader { Address }
Side OrderType TriggerPx TriggerCondition LimitPx Size OrigSz IsPositionTpsl ReduceOnly
}
}
}
TriggerConditionis text (Price below 76000); filter and sort onTriggerPx, the number.- A position TP/SL (
IsPositionTpsl: true) closes the whole position, so itsSizeis0: take the size from the owner's position inSnapshotPositions. - Group by
TriggerPxandSidewithcountandsum(of: Size)for a histogram of stop levels; position TP/SLs add to the count but not to the size.
Order book walls and their owners
Resting orders (IsTrigger: false) are the book at the snapshot, order by order, with the owner of each. The largest orders on each side:
query {
Hyperliquid {
SnapshotOrders(
where: {Market: {CoinRaw: {is: "BTC"}}, IsTrigger: false}
orderBy: {descending: Size}
limit: {count: 50}
) {
Block { Time }
Trader { Address }
IsVault
Side LimitPx Size OrigSz OrderType Tif QueuePosition PlacedTime Oid
}
}
}
Side is Buy (bid) or Sell (ask); Size is what remains, OrigSz what was placed. QueuePosition is the order's place at its price level, 1 being filled first. PlacedTime is epoch milliseconds. Between snapshots, follow the same orders by Oid on the Orders and BookUpdates cubes.
Token holders
SnapshotBalances lists every non-zero spot balance. The largest HYPE holders:
query {
Hyperliquid {
SnapshotBalances(
where: {Token: {is: "HYPE"}}
orderBy: {descending: Total}
limit: {count: 100}
) {
Trader { Address }
Total
Hold
EntryNotional
}
}
}
Hold is the part of Total locked in open orders; EntryNotional is the USDC paid for Total, so EntryNotional / Total is the average entry. There is no USD value: Hyperliquid publishes none. System addresses (0x2222…2222, 0xfefe…fefe) can top the list. count with no other fields gives the number of holders.
Vaults: equity, followers and positions
query {
Hyperliquid {
SnapshotVaults(orderBy: {descending: Summary_Equity}, limit: {count: 25}) {
Vault
Name
Leader
Summary { Equity Followers LeaderFraction }
Terms { LeaderCommission LockupSeconds AllowDeposits IsClosed }
Relationship { Type ChildVaults }
}
}
}
The depositors of a vault are in SnapshotVaultFollowers (filter Vault: {is: "0x..."}: Trader { Address }, IsLeader, Share { Fraction Equity NetDeposit AllTimePnl }, Times { EntryTime LockupUntil }), and its open positions are SnapshotPositions with the vault address as Trader.Address. See the Vaults API for vault fills, deposits and liquidations.
One account: its portfolio at a moment and its history
Several cubes can go in one query: the account's margin per dex, its open positions, spot balances and orders at the latest snapshot. For the state at a past moment, add Block: {Time: {at: "..."}} with a time from the last 7 days to each cube, so all of them read the same snapshot.
query {
Hyperliquid {
SnapshotAccounts(
where: {Trader: {Address: {is: "0x5b5d51203a0f9079f8aeb098a6523a13f298c060"}}}
) {
Block { Number Time }
Protocol
Collateral
Total { AccountValue MarginUsed TotalNotional }
Positions
}
SnapshotPositions(
where: {Trader: {Address: {is: "0x5b5d51203a0f9079f8aeb098a6523a13f298c060"}}}
) {
Market { Symbol CoinRaw }
Position { Side Size EntryPrice Leverage IsCross }
Valuation { PositionValue UnrealizedPnl }
}
SnapshotBalances(
where: {Trader: {Address: {is: "0x5b5d51203a0f9079f8aeb098a6523a13f298c060"}}}
) {
Token
Total
EntryNotional
}
SnapshotOrders(
where: {Trader: {Address: {is: "0x5b5d51203a0f9079f8aeb098a6523a13f298c060"}}}
) {
Market { CoinRaw }
Side OrderType LimitPx TriggerPx Size IsTrigger
}
}
}
The native exchange (Protocol hypercore) and each HIP-3 dex keep separate margin, each in its own Collateral token, so an account has one SnapshotAccounts row per dex. Total is the account's margin summary, Cross the cross-margin part.
The account value over the last week, one point per snapshot:
query {
Hyperliquid {
SnapshotAccounts(
where: {Trader: {Address: {is: "0x5b5d51203a0f9079f8aeb098a6523a13f298c060"}}, Protocol: {is: "hypercore"}, Block: {Time: {since_relative: {days_ago: 7}}}}
orderBy: {ascending: Block_Time}
limit: {count: 1000}
) {
Block { Time }
Total { AccountValue MarginUsed TotalNotional }
Positions
}
}
}
The account's vault shares are in SnapshotVaultFollowers and its Earn supply and borrow in SnapshotEarnPositions, both filtered by Trader: {Address: {is: "0x..."}}.
Earn: supply, borrow and utilization
query {
Hyperliquid {
SnapshotEarnReserves {
Block { Time }
Token
TotalSupplied
TotalBorrowed
Utilization
Ltv
RateModel { BaseRate KinkUtilization MaxRate ProtocolShare }
}
}
}
Amounts are in the token. The borrow rate is BaseRate up to KinkUtilization, then rises linearly to MaxRate at full utilization; suppliers earn the borrow rate × Utilization × (1 − ProtocolShare).
Snapshots vs CurrentPositions
SnapshotPositions | CurrentPositions | |
|---|---|---|
| Freshness | the state at the latest snapshot, up to ~12.5 minutes old | updated with every fill and hourly funding |
| Content | entry price, margin, position value, unrealized PnL, cumulative funding over the position's life | size, leverage, margin mode; funding and realized PnL summed over the data window |
| History | every snapshot of the last 7 days, or the one at a moment | the latest state only |
| Sorting by size | numeric | Size sorts as text |
Use snapshots for the full state and its history, and the event cubes (Trades, Orders, PerpLiquidations) for what happened between two snapshots.
Pitfalls
- Open interest is doubled.
SnapshotMarkets.OpenInterestadds longs and shorts; one side is half of it. - Shorts are negative.
Position.Sizeis signed; sort byValuation.PositionValueto rank by size, and do not sumPosition.Sizeacross both sides expecting open interest. - Ranges multiply rows. A
sincefilter returns every snapshot in it, about 115 a day: aggregate (count,sum) perBlock.Time, or useatfor one moment. - Only the address. Snapshots carry the trader's address alone:
Trader { Signer Vault Broadcaster SignedAt }are not available, except onSnapshotOrders, where they come from Bitquery's order attribution and can be empty. - No liquidation price. Positions carry margin and maintenance margin, but not the liquidation price or the withdrawable amount.
- Numbers are strings at native precision, but filters, sorting and sums on them are numeric.
- Timestamps.
Block.Timeis a date-time; the other time fields are raw epoch integers:PlacedTimein milliseconds,CreateTime,Prices.UpdateTime,UpdateTimeandTimes.*in nanoseconds. - No subscription, 7 days. Poll about every 12.5 minutes; snapshots older than 7 days are not in the API.
Related
- Prediction Markets API — names, prices and holders of HIP-4 outcome markets, from the same snapshots
- Liquidations, Funding, Positions & Leverage
- Order Book API (L3)
- Vaults API
- Bitquery vs Hyperliquid's free data
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.