Hyperliquid whale tracker: whale positions, wallets and PnL
Track any Hyperliquid wallet: its open positions every 5 minutes, its PnL, closed trades, fills and ledger; see who holds each coin's largest positions as they change; find the wallet behind a PnL card; and get a whale alert by e-mail or webhook.
“What is this wallet holding on Hyperliquid right now, and what is its PnL? (paste an address)”
hl_wallet“Whose position is this: a BTC short at 5x, entered at 76,327.4?”
hl_position_matchWhale positions: the largest open positions, every 5 minutes
Every open position on Hyperliquid, captured every 5 minutes: the biggest of any coin now, or what was open at any snapshot back to the history floor.
Position snapshots
Open Hyperliquid positions captured every 5 minutes — the latest snapshot, or history by window.
- Route
/v1/hyperliquid/positions- Cadence
- Snapshot every 5 minutes; archive one file per UTC day
- Coverage
- API: latest open positions (freshness-gated to the newest 15 minutes of snapshots) or historical 5-minute snapshots: pass start (and optionally end), and bound the read by symbol or wallet. Every row says which pnl-cohort label it carries (pnl_cohort_basis). Keyset pagination: nextCursor back as cursor, limit up to 5,000. Archive: positions.parquet per UTC day from 2026-05-08 (CC BY 4.0), every open position at every snapshot of the day, plus one file of the current open positions replaced every 5 minutes (date=latest). Each file comes as a temporary link from /archive/url; /archive/datasets lists the days and the file's own columns.
- Rows
Real rows: The 10 largest BTC positions now
The 10 largest BTC positions now · /positions
/v1/hyperliquid/positions?symbol=BTC&sort=size&limit=10Pass start (and optionally end) for history from 2026-05-01, bounded by symbol or wallet: resolution=5m every snapshot, resolution=1h the last of each hour. Every row says which PnL label it carries: pnl_cohort_basis (point_in_time or current) and pnl_cohort_as_of.
Fields
| Field | Type | Description |
|---|---|---|
wallet | string | Account address, 0x-prefixed |
symbol | string | Symbol; HIP-3 DEX symbols carry their DEX prefix, e.g. xyz:SILVER |
direction | string | long | short |
size_token | number | Position size in coin units |
size_usd | number | Notional at mark, USD |
entry_price | number | Average entry price |
mark_price | number | Mark price at the snapshot |
liquidation_price | number | Liquidation price as reported; 0.0 when none is reported |
unrealized_pnl | number | Mark-to-market PnL, USD |
leverage | number | Position leverage as reported |
leverage_type | string | cross | isolated |
margin_used | number | Margin backing the position, USD |
size_cohort | string | Account-value rung, e.g. whale (size ladder) |
pnl_cohort | string | Realized-PnL percentile rung, or unknown under 10 closed trades |
pnl_abs_cohort | string | Realized-PnL dollar band, e.g. -$10k-$0 |
liq_progress | number | How far price has moved toward liquidation (0 = none); > 0.5 counts as at risk |
dex_name | string | HL, or the HIP-3 DEX the position is on |
snapshot_ts | string | Snapshot instant, ISO-8601 UTC |
pnl_cohort_basis | string | point_in_time | current — which label the row carries |
pnl_cohort_as_of | string|null | Hour the point-in-time label was computed at; null for current |
opened_at | string|null | When the position was first seen open, ISO-8601 UTC; null when unknown |
Load it
/v1/hyperliquid/positions?symbol={symbol}&sort={sort}&cohort={cohort}&limit={limit}GET /v1/hyperliquid/positions · The largest open positions of a coin, now
- CLI
vike-data hl market- MCP
hl_market· 1 credit- Cost
- 1 request of the hourly limit
Position rows, current or historical.
open_only=true reads the latest-state table. Passing start/end switches to the historical snapshot table, which is 8.7 billion rows — bound it by symbol or wallet, or expect it to be slow.
Rows come in key order, not by size. The cursor pages on the table's primary key, so current positions are ordered by wallet, symbol, direction and historical ones by symbol, snapshot_ts, wallet (resolution=1h with wallet: by snapshot_ts, then symbol): limit=10 is the first ten wallets in address order, never the ten biggest positions. For the biggest, pass sort=size (below), or read /v1/hl-cohorts/symbols/{symbol}/size-breakdown (positioning by position-size bucket), /positions/symbols (open interest per symbol) or /v1/hl-cohorts/symbols/{symbol}/cohort-metrics (by cohort).
sort=size returns the limit biggest current positions of one symbol, ordered by size_usd descending, then wallet, then direction, from the same latest-state read as the default. It is a top-N, not a page: symbol is required, limit is at most 500, there is no cursor (nextCursor is always null), and start/end are refused; each violation is a 400 with a one-line reason. Every row additionally carries account_value: the wallet's NATIVE perp account value in USD at the newest snapshot (the same figure as equity.account_value on /wallets/{address}, so it leaves out a builder DEX's separate account), or null when it is unknown (a repaired value, or no row in the newest snapshot). It is never 0 for unknown. No per-position cumulative funding is served, because no per-position source exists that avoids scanning the funding table.
Every row declares its pnl-label provenance: pnl_cohort_basis (point_in_time | current, the same vocabulary labelBasis uses elsewhere) and pnl_cohort_as_of (the ISO hour the label was computed at, or null). Historical rows carry the point-in-time label from the hourly label table — not today's dictionary standing — with the current unlabelled tail (the newest hour or two) falling back to the dictionary and saying so per row; the envelope's label_computed block states the mode's source once. A historical pnl/pnl_abs cohort filter is answered from the same label table and therefore requires symbol or wallet alongside it.
A historical row's own label counts fills up to the end of its hour (label_computed.lookahead is true). For a backtest read label_causal instead: an object with the same keys (pnl_cohort, pnl_abs_cohort, pnl_cohort_as_of, pnl_cohort_basis) computed at the PREVIOUS hour, so it holds no later fill. It is null where that hour has no label for the wallet and is absent on current rows. The row's own label values are unchanged.
Parameters
| Parameter | In | Description |
|---|---|---|
symbol | query | HL ticker, e.g. BTC |
wallet | query | One wallet |
cohort | query | One label on axis |
axis | query | size | pnl | pnl_abs. Default size |
open_only | query | Boolean, default true. Latest open positions only |
start | query | ISO-8601 UTC. Setting either switches to history. Not before 2026-05-01 |
end | query | ISO-8601 UTC. Setting either switches to history |
limit | query | Default 100, max 5000 (500 with sort=size) |
cursor | query | Keyset cursor. Refused with sort=size |
sort | query | size = the biggest positions of one symbol first. Default: key order. Current mode only; needs symbol; limit at most 500; no cursor |
resolution | query | History only (needs start). 5m = every snapshot, ~5 minutes apart. 1h = the last snapshot of each hour, ~12x fewer rows. Default: 1h when wallet is given (served from a wallet-sorted copy), 5m otherwise. A 5m read of one wallet is limited to 48 hours per request. |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&limit=10&sort=size"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&limit=10&sort=size",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl market --view positions --symbol BTC --sort size --limit 10
# any MCP client; or from the terminal:
vike-data call hl_market --args '{"view": "positions", "symbol": "BTC", "sort": "size", "limit": 10}'
Match a PnL card: coin, side, leverage, entry price
- Route
GET /v1/hyperliquid/positions/match- CLI
vike-data perp find-position- MCP
hl_position_match· 2 credits- Cost
- 1 request of the hourly limit
Find open positions matching a symbol/side/leverage/entry profile — the 'who else is in this trade' query.
Parameters
| Parameter | In | Description |
|---|---|---|
symbolrequired | query | HL ticker as listed, e.g. BTC, kPEPE, xyz:TSLA; case-insensitive for those spellings |
siderequired | query | long | short |
leveragerequired | query | Numeric, 0 or more. Matched within ±0.5 absolute. 0 finds cross-margin positions with no leverage recorded |
entry_pricerequired | query | Numeric, positive |
mark_price | query | Tie-break among equally close entries (matches are ranked by entry-price distance first). Defaults to entry_price when omitted |
limit | query | Number of matches, 1–500 |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/positions/match?symbol=BTC&side=short&leverage=5&entry_price=76327.4&limit=3"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions/match?symbol=BTC&side=short&leverage=5&entry_price=76327.4&limit=3",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data perp find-position --coin BTC --side short --leverage 5 --entry 76327.4 --limit 3
# any MCP client; or from the terminal:
vike-data call hl_position_match --args '{"symbol": "BTC", "side": "short", "leverage": 5, "entry_price": 76327.4, "limit": 3}'
Track any Hyperliquid wallet: positions, PnL, trades, fills, funding, ledger, orders
Paste an address: open it live on vike.io, follow it with an alert, or call it from code.
Open the wallet live
Its equity, open positions, PnL, closed trades and fills on one page.
Get an e-mail when it trades
Its opens, closes, flips and adds, by e-mail or webhook.
Equity, open positions, PnL and lifetime flow
- Route
GET /v1/hyperliquid/wallets/{address}- CLI
vike-data hl wallet- MCP
hl_wallet· 1 credit- Cost
- 1 request of the hourly limit
One wallet: equity, cohorts, risk metrics, lifetime external flow.
openedWithin bounds the open-positions block only — the equity, lifetime and metrics blocks are wallet-level totals with nothing per-position to filter, and bounding them would return a number that looks bounded and is not. Positions with no known open time are excluded from every bounded bucket, matching what /v1/hl-cohorts/segments and /v1/hl-cohorts/heatmap do, so cohort comparisons stay like-for-like.
open_positions.perp_bias = (long - short) / equity.account_value and open_positions.equity_exposure = (long + short) / equity.account_value, native perp account only: positions on the main dex over the native perp account value; builder-DEX positions are not included. Unbounded ratios, null with no main-dex position or no positive equity.
A wallet we hold nothing for (no equity snapshot, open position, trade, fill or ledger event) is a 400 naming it, not a block of zeros.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | The wallet |
window | query | 1d | 7d | 30d | all. Default all |
openedWithin | query | 24h | 7d | 30d | all. Default all |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl wallet 0x7fdafde5cfb5465924316eced2d3715494c517d1
# any MCP client; or from the terminal:
vike-data call hl_wallet --args '{"address": "0x7fdafde5cfb5465924316eced2d3715494c517d1"}'
Win rate, average win and loss, overall and per coin
- Route
GET /v1/hyperliquid/wallets/{address}/trades/summary- CLI
vike-data hl wallet- MCP
hl_wallet· 1 credit- Cost
- 1 request of the hourly limit
Trade statistics for one wallet, overall and per coin.
Medians as well as means: one $4M outlier drags the mean trade size far from anything the wallet typically does, and the mean is where most leaderboards stop.
A wallet with no trade at all is a 400 naming it, not zeros. A wallet that has traded and was quiet in the requested window gets the zeros, which are true.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | The wallet |
window | query | 1d | 7d | 30d | all. Default all |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/trades/summary?window=30d"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/trades/summary?window=30d",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl wallet 0x7fdafde5cfb5465924316eced2d3715494c517d1 --view trades_summary --window 30d
# any MCP client; or from the terminal:
vike-data call hl_wallet --args '{"view": "trades_summary", "address": "0x7fdafde5cfb5465924316eced2d3715494c517d1", "window": "30d"}'
Closed trades: entry, exit, size and PnL
- Route
GET /v1/hyperliquid/wallets/{address}/trades- CLI
vike-data hl wallet-trades- MCP
hl_wallet_trades· 1 credit- Cost
- 1 request of the hourly limit
Closed round-trip trades for one wallet.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | The wallet |
symbol | query | HL ticker, e.g. BTC. Omit for all |
start | query | ISO-8601 UTC bounds |
end | query | ISO-8601 UTC bounds |
limit | query | Default 100, max 5000 |
cursor | query | nextCursor from the previous page, verbatim |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/trades?limit=20"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/trades?limit=20",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl wallet-trades 0x7fdafde5cfb5465924316eced2d3715494c517d1 --limit 20
# any MCP client; or from the terminal:
vike-data call hl_wallet_trades --args '{"address": "0x7fdafde5cfb5465924316eced2d3715494c517d1", "limit": 20}'
Every fill, newest first
- Route
GET /v1/hyperliquid/wallets/{address}/fills- CLI
vike-data hl wallet-activity- MCP
hl_wallet_activity· 1 credit- Cost
- 1 request of the hourly limit
Raw fills for one wallet.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | The wallet |
symbol | query | HL ticker |
start | query | ISO-8601 UTC bounds |
end | query | ISO-8601 UTC bounds |
side | query | buy | sell |
limit | query | Default 100, max 5000 |
cursor | query | Keyset cursor |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/fills?limit=50"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/fills?limit=50",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl wallet-activity 0x7fdafde5cfb5465924316eced2d3715494c517d1 --view fills --limit 50
# any MCP client; or from the terminal:
vike-data call hl_wallet_activity --args '{"view": "fills", "address": "0x7fdafde5cfb5465924316eced2d3715494c517d1", "limit": 50}'
Funding paid and received
- Route
GET /v1/hyperliquid/wallets/{address}/funding- CLI
vike-data hl wallet-activity- MCP
hl_wallet_activity· 1 credit- Cost
- 1 request of the hourly limit
Funding paid and received by one wallet.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | The wallet |
symbol | query | HL ticker |
start | query | ISO-8601 UTC bounds |
end | query | ISO-8601 UTC bounds |
limit | query | Default 100, max 5000 |
cursor | query | Keyset cursor |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/funding?limit=100"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/funding?limit=100",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl wallet-activity 0x7fdafde5cfb5465924316eced2d3715494c517d1 --view funding --limit 100
# any MCP client; or from the terminal:
vike-data call hl_wallet_activity --args '{"view": "funding", "address": "0x7fdafde5cfb5465924316eced2d3715494c517d1", "limit": 100}'
Deposits, withdrawals and transfers
- Route
GET /v1/hyperliquid/wallets/{address}/ledger- CLI
vike-data hl wallet-activity- MCP
hl_wallet_activity· 1 credit- Cost
- 1 request of the hourly limit
Deposits, withdrawals, transfers and vault events for one wallet.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | The wallet |
event_type | query | One of accountClassTransfer, borrowLend, deposit, internalTransfer, rewardsClaim, send, spotTransfer, subAccountTransfer, vaultCreate, vaultDeposit, vaultDistribution, vaultLeaderCommission, vaultWithdraw, withdraw. Validated against this fixed set |
start | query | ISO-8601 UTC bounds |
end | query | ISO-8601 UTC bounds |
limit | query | Default 100, max 5000 |
cursor | query | Keyset cursor |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/ledger?event_type=deposit&limit=20"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/ledger?event_type=deposit&limit=20",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl wallet-activity 0x7fdafde5cfb5465924316eced2d3715494c517d1 --view ledger --event-type deposit --limit 20
# any MCP client; or from the terminal:
vike-data call hl_wallet_activity --args '{"view": "ledger", "address": "0x7fdafde5cfb5465924316eced2d3715494c517d1", "event_type": "deposit", "limit": 20}'
What became of its orders: open, filled, canceled
- Route
GET /v1/hyperliquid/wallets/{address}/orders- CLI
vike-data hl orders- MCP
hl_orders· 1 credit- Cost
- 1 request of the hourly limit
What became of one wallet's orders in a window: each order seen resting in it or filled in it, with its fills in the window and a status. Newest placement first; notes says what a snapshot cannot tell.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | The wallet |
from | query | ISO-8601 UTC. Default: 7 days before to |
to | query | ISO-8601 UTC. Default: the newest order snapshot. At most 30 days after from |
symbol | query | HL perp ticker |
status | query | open | filled | partially_filled | canceled_or_expired |
limit | query | Default 100, max 1000 |
cursor | query | nextCursor from the previous page, verbatim |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/orders?limit=20"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/orders?limit=20",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl orders --view wallet --address 0x7fdafde5cfb5465924316eced2d3715494c517d1 --limit 20
# any MCP client; or from the terminal:
vike-data call hl_orders --args '{"view": "wallet", "address": "0x7fdafde5cfb5465924316eced2d3715494c517d1", "limit": 20}'
Big orders being worked: Hyperliquid TWAPs
A TWAP order is executed in slices over minutes or hours: which wallets are working one, on which coin, and how much of it is done.
TWAPs being worked now, across every wallet
- Route
GET /v1/hyperliquid/twaps- CLI
vike-data hl twaps- MCP
hl_twaps· 1 credit- Cost
- 1 request of the hourly limit
TWAP orders across wallets, one row per status line, newest first.
A line is a status CHANGE (activated, waitingForTrigger, then finished, terminated or stopped), not a slice fill: executed_size and executed_notional_usd are the cumulative totals when the line was written. Rejected placements (error) are hidden unless status=error. Rows sharing a ts keep a stable order, so a cursor never skips or repeats one.
Parameters
| Parameter | In | Description |
|---|---|---|
wallet | query | One wallet, 0x plus 40 hex, any case |
twap_id | query | One TWAP id: every status line of that TWAP |
symbol | query | HL ticker, e.g. BTC or xyz:AAPL |
status | query | One of activated, waitingForTrigger, finished, terminated, stopped, error. Default: every status except error, a rejected placement rather than an order; status=error shows those rows |
start | query | ISO-8601 UTC. Default: the 24 hours before end (before now when end is empty), unless wallet or twap_id is given. Resuming an order=asc cursor starts from the cursor instead; a desc cursor keeps the 24-hour floor |
end | query | ISO-8601 UTC. Default: now. A window wider than 31 days is a 400 unless wallet or twap_id is given |
order | query | asc | desc. Default desc, newest first. order=asc returns the oldest events first and is the mode for following a feed: pass each nextCursor back verbatim. It orders by key, so a row the writer inserts late with an older key is not seen by a poller already past it: re-read a small overlap. An asc page with rows always carries a cursor; an empty one returns the cursor you sent, or on a first call with no start or wallet or twap_id, a cursor at the lower bound of the default window (null when one of them already pins the place). So stop on an empty page, not on a null cursor. A desc page that comes back short carries no cursor. Anything else is a 400 |
limit | query | Default 100, max 5000 |
cursor | query | nextCursor from the previous page, verbatim. It pins the call that returned it: the feed, order, every filter and the start and end you sent. Changing or dropping any of them, start included, is a 400. Without wallet or twap_id, an asc cursor more than 31 days before end (before now when end is empty) is a 400 too: restart with start. /twaps?wallet= and the per-wallet TWAP route are one feed: with the same parameters their cursors are interchangeable |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/twaps?status=activated&limit=20"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/twaps?status=activated&limit=20",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl twaps --status activated --limit 20
# any MCP client; or from the terminal:
vike-data call hl_twaps --args '{"status": "activated", "limit": 20}'
Its TWAP orders
- Route
GET /v1/hyperliquid/wallets/{address}/twaps- CLI
vike-data hl twaps- MCP
hl_twaps· 1 credit- Cost
- 1 request of the hourly limit
One wallet's TWAP orders: /twaps with the wallet pinned, wrapped as wallet, items, nextCursor.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | The wallet |
twap_id | query | One TWAP id: every status line of that TWAP |
symbol | query | HL ticker, e.g. BTC or xyz:AAPL |
status | query | One of activated, waitingForTrigger, finished, terminated, stopped, error. Default: every status except error, a rejected placement rather than an order; status=error shows those rows |
start | query | ISO-8601 UTC. Default: no lower bound |
end | query | ISO-8601 UTC. Default: now. The window has no 31-day cap |
order | query | asc | desc. Default desc, newest first. order=asc returns the oldest events first and is the mode for following a feed: pass each nextCursor back verbatim. It orders by key, so a row the writer inserts late with an older key is not seen by a poller already past it: re-read a small overlap. An asc page with rows always carries a cursor; an empty one returns the cursor you sent, or on a first call null (the wallet already pins the place). So stop on an empty page, not on a null cursor. A desc page that comes back short carries no cursor. Anything else is a 400 |
limit | query | Default 100, max 5000 |
cursor | query | nextCursor from the previous page, verbatim. It pins the call that returned it: the feed, order, every filter and the start and end you sent. Changing or dropping any of them, start included, is a 400. It is also valid on /twaps?wallet= with the same parameters |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/twaps?limit=20"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/twaps?limit=20",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl twaps --wallet 0x7fdafde5cfb5465924316eced2d3715494c517d1 --limit 20
# any MCP client; or from the terminal:
vike-data call hl_twaps --args '{"wallet": "0x7fdafde5cfb5465924316eced2d3715494c517d1", "limit": 20}'
Live on vike.io: the TWAP tracker →
Large deposits, withdrawals and transfers
Money moving in and out of every Hyperliquid wallet; one wallet's own ledger is in the wallet section above.
Large deposits, withdrawals and transfers, across every wallet
- Route
GET /v1/hyperliquid/ledger- CLI
vike-data hl ledger- MCP
hl_ledger· 1 credit- Cost
- 1 request of the hourly limit
Deposits, withdrawals, transfers and vault events across wallets, newest first.
The cross-wallet twin of /wallets/{address}/ledger, with wallet on every row. A transfer between two wallets is one row per affected wallet with the same hash.
Parameters
| Parameter | In | Description |
|---|---|---|
wallet | query | One wallet, 0x plus 40 hex, any case |
event_type | query | One of accountClassTransfer, borrowLend, deposit, internalTransfer, rewardsClaim, send, spotTransfer, subAccountTransfer, vaultCreate, vaultDeposit, vaultDistribution, vaultLeaderCommission, vaultWithdraw, withdraw. Validated against this fixed set |
min_usd | query | Minimum absolute amount_usd, 0 or more. Default 0: no floor |
start | query | ISO-8601 UTC. Default: the 24 hours before end (before now when end is empty), unless wallet is given. Resuming an order=asc cursor starts from the cursor instead; a desc cursor keeps the 24-hour floor |
end | query | ISO-8601 UTC. Default: now. A window wider than 31 days is a 400 unless wallet is given |
order | query | asc | desc. Default desc, newest first. order=asc returns the oldest events first and is the mode for following a feed: pass each nextCursor back verbatim. It orders by key, so a row the writer inserts late with an older key is not seen by a poller already past it: re-read a small overlap. An asc page with rows always carries a cursor; an empty one returns the cursor you sent, or on a first call with no start or wallet, a cursor at the lower bound of the default window (null when one of them already pins the place). So stop on an empty page, not on a null cursor. A desc page the read finds short carries no cursor, but duplicate rows are dropped from a page after it is read, so a page with fewer than limit rows can still carry one: stop on an empty page. Anything else is a 400 |
limit | query | Default 100, max 5000 |
cursor | query | nextCursor from the previous page, verbatim. It pins the call that returned it: the feed, order, every filter and the start and end you sent. Changing or dropping any of them, start included, is a 400. Without wallet, an asc cursor more than 31 days before end (before now when end is empty) is a 400 too: restart with start |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/ledger?min_usd=1000000&limit=20"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/ledger?min_usd=1000000&limit=20",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl ledger --min-usd 1000000 --limit 20
# any MCP client; or from the terminal:
vike-data call hl_ledger --args '{"min_usd": 1000000, "limit": 20}'
Vault deposits and withdrawals, vault by vault: Vaults →
Who holds HYPE: the largest holders, staked and spot
Each wallet's spot HYPE plus staked HYPE at one current price, with its perp account value and PnL cohort.
The largest HYPE holders, staked and spot
- Route
GET /v1/hyperliquid/hype/holders- CLI
vike-data hl hype-holders- MCP
hl_hype_holders· 1 credit- Cost
- 1 request of the hourly limit
Real rows
The largest HYPE holders · /hype/holders
/v1/hyperliquid/hype/holders?limit=10Load it
/v1/hyperliquid/hype/holders?limit={limit}HYPE holder leaderboard — spot balance plus staked, per wallet.
pnl_cohort is resolved at query time and the envelope declares it (label_basis='current' + label_computed). Correct here, not a fallback: the leaderboard has no time axis — every row is last-known state, so a current label has no earlier row to contaminate. The caveat runs the other way: balances are last-known, so a stale balance can sit beside a fresh label. account_value is the wallet's perp account value and is null for a holder with no perp account on record (it used to read 0.0, the same as an account that really holds nothing).
Parameters
| Parameter | In | Description |
|---|---|---|
order | query | asc | desc. Default desc |
limit | query | Default 100, max 500 |
cursor | query | Keyset cursor |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/hyperliquid/hype/holders?limit=10"
import os, requests
r = requests.get(
"https://data.vike.io/v1/hyperliquid/hype/holders?limit=10",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data hl hype-holders --limit 10
# any MCP client; or from the terminal:
vike-data call hl_hype_holders --args '{"limit": 10}'
Follow the whales live
5 WebSocket channels at wss://stream.vike.io/v1/stream/hl, on the same free key.
| Channel | What it sends | Filters |
|---|---|---|
hl.top_positions | Who holds each coin's 10 largest positions, for the 50 coins whose top 10 is worth the most: a position that entered the top, left it or moved rank, at every 5-minute capture. | coin, direction, event, min_usd, pnl_cohort, size_cohort, wallet |
hl.positions | A whale's fill that opens, adds to, reduces, closes or flips a position, with its leverage and liquidation price: a wallet with an account of $250,000 or more, or a position worth $250,000 or more before or after the fill. | action, coin, min_leverage, min_usd, pnl_cohort, side, size_cohort, tag, wallet |
hl.order_walls | Resting orders of $1,000,000 or more that appeared on the book or disappeared from it, from the 5-minute order snapshots. | coin, event, min_usd, pnl_cohort, side, size_cohort, wallet |
hl.twaps | TWAP orders of every wallet, one event per status line (activated, finished, terminated, ...). | coin, min_usd, pnl_cohort, side, size_cohort, status, wallet |
hl.ledger | Deposits, withdrawals, transfers and vault events of every wallet, as they are recorded. | event_type, min_usd, pnl_cohort, size_cohort, wallet |
import json, os
from websockets.sync.client import connect # websockets >= 14
with connect("wss://stream.vike.io/v1/stream/hl",
additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
ws.send(json.dumps({"action": "subscribe", "id": "top", "channel": "hl.top_positions",
"filter": {"coin": ["BTC", "ETH"], "event": "entered"}}))
for message in ws:
frame = json.loads(message)
if frame["type"] == "ping":
ws.send(json.dumps({"action": "pong"}))
elif frame["type"] == "event":
e = frame["event"]
print(e["ts"], e["subject"], e["data"], e["labels"])
vike-data stream hl --channel hl.top_positions --filter coin=BTC,ETH --filter event=entered # prints NDJSON, reconnects by itself
{
"action": "subscribe",
"id": "top",
"channel": "hl.top_positions",
"filter": {
"coin": [
"BTC",
"ETH"
],
"event": "entered"
}
}
- Who enters the top 10 of BTC or ETH:
vike-data stream hl --channel hl.top_positions --filter coin=BTC,ETH --filter event=entered - Every position change of one wallet:
vike-data stream hl --channel hl.positions --filter wallet=0x7fdafde5cfb5465924316eced2d3715494c517d1 - Whale position changes of $1,000,000 or more:
vike-data stream hl --channel hl.positions --filter min_usd=1000000 - Order walls appearing on BTC:
vike-data stream hl --channel hl.order_walls --filter coin=BTC --filter event=appeared - TWAPs activated by whales:
vike-data stream hl --channel hl.twaps --filter status=activated --filter 'size_cohort=4x whale,3x whale,2x whale,whale' - Deposits and withdrawals of $1,000,000 or more:
vike-data stream hl --channel hl.ledger --filter event_type=deposit,withdraw --filter min_usd=1000000 - A
walletfilter takes up to 1,000 wallets on one subscription.
Every channel's fields, a real event and every filter value: AI & API →
Whale alerts by e-mail or webhook
No code: create one on your account page, or ask your AI to.
hl_walletFollow one wallet
An e-mail or a webhook when the wallet's fills open, close, flip, increase a position (and, if you like, reduce), for every coin or one, from a dollar size up. Up to 200 wallets per account.
E-mail me when Hyperliquid wallet 0x7fdafde5cfb5465924316eced2d3715494c517d1 opens, closes, flips or adds to a position.
# any MCP client (the tool alerts_create); or from the terminal:
vike-data call alerts_create --args '{"label": "Wallet moves", "alert_type": "hl_wallet", "wallet": "0x7fdafde5cfb5465924316eced2d3715494c517d1", "channels": ["email"]}'
vike-data alerts create --label "Wallet moves" --type hl_wallet --wallet 0x7fdafde5cfb5465924316eced2d3715494c517d1 --channel email
hl_cohort_fillThe whale alert
Every fill of $10,000 or more by any wallet in the size or PnL cohorts you pick (here whale and up: 4x whale, 3x whale, 2x whale, whale), on every coin or one, by e-mail or webhook.
E-mail me every Hyperliquid fill of $10,000 or more by a whale-sized account (4x whale, 3x whale, 2x whale, whale).
# any MCP client (the tool alerts_create); or from the terminal:
vike-data call alerts_create --args '{"label": "Whale fills", "alert_type": "hl_cohort_fill", "min_value_usd": 10000, "size_cohorts": ["4x whale", "3x whale", "2x whale", "whale"], "channels": ["email"]}'
vike-data alerts create --label "Whale fills" --type hl_cohort_fill --min-usd 10000 --size-cohorts '4x whale' '3x whale' '2x whale' whale --channel email
The same data on vike.io, no key
Leaderboard and whale tracker
Every ranked wallet on vike.io: sort, filter, open one.
Open → vike.ioOne wallet
Its equity, positions, trades and fills on one page: here the 30-day leader.
Open → vike.ioTWAP tracker
The TWAP orders being worked right now, and by whom.
Open → vike.ioWhales long vs short
Long and short by cohort; the data behind it is HL Cohorts.
Open →Long vs short by cohort, as data: HL Cohorts →
Every route on this page
Each with its parameters above, and in the full API reference.
Whale and wallet questions, answered with code
Each with the sentence to ask your AI instead. Every block was run against the live API on 2026-11-03.
Every open position on a Hyperliquid coin: who holds the biggest longs and shorts, and how much equity do they have?
The biggest open positions of one coin, largest first, each with the wallet's account value, from /v1/hyperliquid/positions?symbol=BTC&sort=size.
- Uses
/positions- Verified
- live API, 2026-11-03: 5 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the 20 biggest open BTC positions, longs and shorts together, largest first
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&sort=size&limit=20",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the 500 biggest BTC positions
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&sort=size&limit=500",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the biggest BTC longs and how many times their account value each one holds on BTC
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&sort=size&limit=500",
headers={"X-API-Key": API_KEY},
)
# then: jq '[.positions[] | select(.direction == "long") | {wallet, size_usd, account_value, x_equity: (if (.account_value // 0) > 0 then .size_usd / .account_value else null end)}] | .[:20]'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# every open BTC position: the first page of 5,000, ordered by wallet address, not by size
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&limit=5000",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the biggest open xyz:TSLA positions
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?symbol=xyz:TSLA&sort=size&limit=20",
headers={"X-API-Key": API_KEY},
)
Positions of 50 Hyperliquid watchlist wallets in one call
Track the open positions of a watchlist of Hyperliquid wallets from the 5-minute positions file.
- Uses
/archive/datasets,/archive/url,/positions- Verified
- live API, 2026-11-03: 3 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# ask for the link and download the current open positions of every wallet in one step
r = requests.get(
"https://data.vike.io/v1/hyperliquid/archive/url?dataset=positions&date=latest&redirect=1",
headers={"X-API-Key": API_KEY},
)
with open("positions-latest.parquet", "wb") as f:
f.write(r.content)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# everything one wallet holds right now
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?wallet=0x25773676902085225ae5751075e4161369334897&limit=200",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# snapshot time, write time, rows and bytes of the latest positions file
r = requests.get(
"https://data.vike.io/v1/hyperliquid/archive/datasets",
headers={"X-API-Key": API_KEY},
)
# then: jq '.latest.positions | {snapshot_ts, generated_at, rows, bytes, assets}'
Show one Hyperliquid wallet's hourly position history for 30 days
A wallet's positions at the last snapshot of every hour over 30 days, from /v1/hyperliquid/positions with wallet, start and end; resolution=5m gives every snapshot, 48 hours per request.
- Uses
/archive/url,/positions- Verified
- live API, 2026-11-03: 6 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# one wallet's positions at the end of every hour for 30 days
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?wallet=0x25773676902085225ae5751075e4161369334897&start=2026-09-24T00:00:00Z&end=2026-10-24T00:00:00Z&limit=5000",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# every snapshot of the wallet over 48 hours
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?wallet=0x25773676902085225ae5751075e4161369334897&start=2026-10-22T00:00:00Z&end=2026-10-24T00:00:00Z&resolution=5m&limit=5000",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the wallet's BTC position, hour by hour
r = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?wallet=0x25773676902085225ae5751075e4161369334897&symbol=BTC&start=2026-09-24T00:00:00Z&end=2026-10-24T00:00:00Z&limit=5000",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the next page of the month: NEXT is the first page's nextCursor; keep the same start, end and resolution
first = requests.get(
"https://data.vike.io/v1/hyperliquid/positions?wallet=0x25773676902085225ae5751075e4161369334897&start=2026-09-24T00:00:00Z&end=2026-10-24T00:00:00Z&limit=5000",
headers={"X-API-Key": API_KEY},
).json()
NEXT = first["nextCursor"] # the first page's cursor, passed back verbatim
r = requests.get(
f"https://data.vike.io/v1/hyperliquid/positions?wallet=0x25773676902085225ae5751075e4161369334897&start=2026-09-24T00:00:00Z&end=2026-10-24T00:00:00Z&limit=5000&cursor={NEXT}",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# a temporary link to every 5-minute position snapshot of one UTC day, as Parquet
r = requests.get(
"https://data.vike.io/v1/hyperliquid/archive/url?dataset=positions&date=2026-10-23",
headers={"X-API-Key": API_KEY},
)
Closed trades of a wallet: win rate, hold time, best and worst coin
A wallet's closed round trips with hold time and realized PnL, from /wallets/{address}/trades, and /trades/summary totals them overall and per coin, which gives the win rate, the median hold and the best and worst coin.
- Uses
/wallets/{…}/trades,/wallets/{…}/trades/summary- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the newest closed round trips of one wallet
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xfc667adba8d4837586078f4fdcdc29804337ca06/trades?limit=5",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# win rate, median and average hold, and net PnL over 30 days
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xfc667adba8d4837586078f4fdcdc29804337ca06/trades/summary?window=30d",
headers={"X-API-Key": API_KEY},
)
# then: jq '.overall | {trade_count, closed_trade_count, win_rate, median_duration, avg_duration, net_pnl}'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the worst and the best coin of the last 30 days by net PnL
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xfc667adba8d4837586078f4fdcdc29804337ca06/trades/summary?window=30d",
headers={"X-API-Key": API_KEY},
)
# then: jq '.by_symbol | sort_by(.net_pnl) | [first, last] | map({symbol, net_pnl, trade_count, win_rate, median_duration})'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# every closed BTC round trip of the wallet in October
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xfc667adba8d4837586078f4fdcdc29804337ca06/trades?symbol=BTC&start=2026-10-01T00:00:00Z&limit=1000",
headers={"X-API-Key": API_KEY},
)
Hyperliquid wallet ledger: deposits, withdrawals, transfers
A wallet's deposits, withdrawals, transfers and vault events, newest first, with a USD amount, the token and the counterparty, from /wallets/{address}/ledger; event_type filters to one kind.
- Uses
/wallets/{…},/wallets/{…}/ledger- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the wallet's newest ledger events
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/ledger?limit=5",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# bridge deposits into the wallet
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/ledger?event_type=deposit&limit=100",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# withdrawals out of the wallet
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1/ledger?event_type=withdraw&limit=100",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# lifetime deposits, withdrawals and per-type totals
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x7fdafde5cfb5465924316eced2d3715494c517d1",
headers={"X-API-Key": API_KEY},
)
# then: jq '{lifetime, ledger_by_type}'
Export a Hyperliquid wallet's fills, funding and ledger for taxes
Export a Hyperliquid wallet's fills, funding payments and ledger entries to CSV for taxes; funding and ledger are kept one year, fills have no expiry.
- Uses
/wallets/{…},/wallets/{…}/fills,/wallets/{…}/funding,/wallets/{…}/ledger- Verified
- live API, 2026-11-03: 7 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the newest fills of one wallet; repeat with /funding and /ledger
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff/fills?limit=3",
headers={"X-API-Key": API_KEY},
)
import csv
import os
import requests
H = {"X-API-Key": os.environ["VIKE_API_KEY"]}
WALLET = "0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff"
BASE = f"https://data.vike.io/v1/hyperliquid/wallets/{WALLET}"
WINDOW = {"start": "2026-01-01T00:00:00Z", "end": "2026-12-31T23:59:59Z"}
def rows(kind):
params = {**WINDOW, "limit": 5000}
while True:
r = requests.get(f"{BASE}/{kind}", params=params, headers=H, timeout=60)
r.raise_for_status()
body = r.json()
yield from body["items"]
if not body["nextCursor"]:
return
params["cursor"] = body["nextCursor"]
for kind in ("fills", "funding", "ledger"):
items = list(rows(kind))
if not items:
continue
with open(f"{WALLET}-{kind}.csv", "w", newline="") as f:
w = csv.DictWriter(f, fieldnames=list(items[0]), extrasaction="ignore")
w.writeheader()
w.writerows(items)
print(kind, len(items))
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# BTC fills of the wallet in the tax year, the largest page
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff/fills?symbol=BTC&start=2026-01-01T00:00:00Z&end=2026-12-31T23:59:59Z&limit=5000",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# one kind of ledger event, here the wallet's sends in the tax year (deposit and withdraw work the same way)
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff/ledger?event_type=send&start=2026-01-01T00:00:00Z&end=2026-12-31T23:59:59Z&limit=5000",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# net funding per coin over one page of payments
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff/funding?start=2026-01-01T00:00:00Z&limit=5000",
headers={"X-API-Key": API_KEY},
)
# then: jq '.items | group_by(.symbol) | map({symbol: .[0].symbol, payment_usd: (map(.payment_usd) | add)})'
HyperCore ↔ HyperEVM transfers of a user
Read the user's spotTransfer and send ledger events and keep the ones whose counterparty is a Hyperliquid system address, such as 0x2222…2222 for HYPE; the sign of amount_usd gives the direction.
- Uses
/wallets/{…}/ledger- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the user's spot transfers, where the Core and EVM moves sit
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xbf49ffdc3008791900bb96ebccb61118f70c1bc9/ledger?event_type=spotTransfer&limit=5",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# spot transfers to or from a system address, newest 1000
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xbf49ffdc3008791900bb96ebccb61118f70c1bc9/ledger?event_type=spotTransfer&limit=1000",
headers={"X-API-Key": API_KEY},
)
# then: jq '[.items[] | select((.counterparty // "") | test("^0x(2{40}|20{35}[0-9a-f]{4})$"))] | map({ts, token, amount_usd, counterparty, direction: (if .amount_usd > 0 then "evm_to_core" else "core_to_evm" end)})'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the user's send events, to filter the same way
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xbf49ffdc3008791900bb96ebccb61118f70c1bc9/ledger?event_type=send&limit=1000",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# HyperEVM transfers of the same address over 90 days
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0xbf49ffdc3008791900bb96ebccb61118f70c1bc9/transactions?chain=hyperevm&days=90&limit=100",
headers={"X-API-Key": API_KEY},
)
Wash trading between two Hyperliquid addresses: did they trade with each other?
Fetch both wallets' fills for the same coin and window from /v1/hyperliquid/wallets/{address}/fills and join them on trade_id, which both sides of one trade share.
- Uses
/archive/url,/wallets/{…}/fills- Verified
- live API, 2026-11-03: 5 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# wallet A's BTC fills in a three-second window
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x53136b4a7c432585f28903b77c7816a723e0271f/fills?symbol=BTC&start=2026-10-24T17:13:32Z&end=2026-10-24T17:13:35Z&limit=5000",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# wallet B's BTC fills in the same window
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0xb371766bcdcd556ce6b6cf164be6019d01441042/fills?symbol=BTC&start=2026-10-24T17:13:32Z&end=2026-10-24T17:13:35Z&limit=5000",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# next page of a one-month read: NEXT is the first page's nextCursor, passed back verbatim
first = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x53136b4a7c432585f28903b77c7816a723e0271f/fills?symbol=BTC&start=2026-10-01T00:00:00Z&end=2026-10-24T00:00:00Z&limit=5000",
headers={"X-API-Key": API_KEY},
).json()
NEXT = first["nextCursor"] # the first page's cursor, passed back verbatim
r = requests.get(
f"https://data.vike.io/v1/hyperliquid/wallets/0x53136b4a7c432585f28903b77c7816a723e0271f/fills?symbol=BTC&start=2026-10-01T00:00:00Z&end=2026-10-24T00:00:00Z&limit=5000&cursor={NEXT}",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# a temporary link to every fill of one UTC day, as Parquet
r = requests.get(
"https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-23",
headers={"X-API-Key": API_KEY},
)
Who bought and sold the most of a coin on Hyperliquid over a month?
Download a month of daily fills files from the archive, filter one asset, and sum size_token per wallet by side; net = bought - sold ranks the top buyers and sellers.
- Uses
/archive/datasets,/archive/url,/wallets/{…}- Verified
- live API, 2026-11-03: 3 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# size of the month's fills files, before you ask for any link
r = requests.get(
"https://data.vike.io/v1/hyperliquid/archive/datasets",
headers={"X-API-Key": API_KEY},
)
# then: jq '[.dates[] | select(.date | startswith("2026-09")) | .streams.fills.bytes] | {days: length, gb: (add / 1e9)}'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# one day of every fill; repeat per date of the month
r = requests.get(
"https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-09-01&redirect=1",
headers={"X-API-Key": API_KEY},
)
with open("fills-2026-09-01.parquet", "wb") as f:
f.write(r.content)
import polars as pl
by_wallet = (
pl.scan_parquet("fills-2026-09-*.parquet") # the month's 30 files, read as one table
.filter(pl.col("asset") == "BTC")
.group_by("wallet")
.agg(
bought=pl.col("size_token").filter(pl.col("side") == "buy").sum(),
sold=pl.col("size_token").filter(pl.col("side") == "sell").sum(),
bought_usd=pl.col("size_usd").filter(pl.col("side") == "buy").sum(),
sold_usd=pl.col("size_usd").filter(pl.col("side") == "sell").sum(),
)
.with_columns(net=pl.col("bought") - pl.col("sold"))
.collect()
)
print(by_wallet.sort("net", descending=True).head(10)) # top net buyers
print(by_wallet.sort("net").head(10)) # top net sellers
# by USD instead of coins: sort on bought_usd - sold_usd to compare across coins
print(by_wallet.with_columns(net_usd=pl.col("bought_usd") - pl.col("sold_usd")).sort("net_usd", descending=True).head(10))
# takers only: who crossed the spread to buy, as opposed to whose resting orders were hit
takers = pl.scan_parquet("fills-2026-09-*.parquet").filter((pl.col("asset") == "BTC") & ~pl.col("is_maker"))
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the sample hour's top buyer
r = requests.get(
"https://data.vike.io/v1/hyperliquid/wallets/0x5986347c1d0133d02d307f08bb1efd44c2eb89d9",
headers={"X-API-Key": API_KEY},
)
What are the latest large trades on a Hyperliquid coin, including HIP-3 and spot?
A coin's newest fills of $50,000 or more, with wallet, side, price, market or limit, and cohort labels, from /v1/hl-cohorts/symbols/{symbol}/large-fills; smaller trades are only in the daily fills file of the archive.
- Uses
/archive/url,/ohlcv,/v1/hl-cohorts/symbols/{…}/large-fills- Verified
- live API, 2026-11-03: 5 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the newest BTC fills of $50,000 or more
r = requests.get(
"https://data.vike.io/v1/hl-cohorts/symbols/BTC/large-fills?limit=3",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the newest HYPE spot fills of $50,000 or more
r = requests.get(
"https://data.vike.io/v1/hl-cohorts/symbols/@107/large-fills?limit=3",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# XYZ gold fills of $100,000 or more in the last 6 hours
r = requests.get(
"https://data.vike.io/v1/hl-cohorts/symbols/xyz:GOLD/large-fills?min_usd=100000&hours=6",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# every BTC trade in a pinned three-second window
r = requests.get(
"https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=1t&start=2026-10-21T00:00:00Z&end=2026-10-21T00:00:03Z&limit=10",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# a temporary download link for one day of every fill
r = requests.get(
"https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-23",
headers={"X-API-Key": API_KEY},
)
Who holds HYPE? Top holders
Wallets ranked by HYPE held on Hyperliquid spot plus HYPE staked, with USD at one current price and each wallet's cohort labels, from /v1/hyperliquid/hype/holders.
- Uses
/hype/holders- Verified
- live API, 2026-11-03: 5 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the three biggest HYPE holders, spot plus staked
r = requests.get(
"https://data.vike.io/v1/hyperliquid/hype/holders?limit=3",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# holders 501 to 1,000: NEXT is the first page's nextCursor, passed back verbatim
first = requests.get(
"https://data.vike.io/v1/hyperliquid/hype/holders?limit=500",
headers={"X-API-Key": API_KEY},
).json()
NEXT = first["nextCursor"] # the first page's cursor, passed back verbatim
r = requests.get(
f"https://data.vike.io/v1/hyperliquid/hype/holders?limit=500&cursor={NEXT}",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the share of the top 100's HYPE held by its ten largest holders
r = requests.get(
"https://data.vike.io/v1/hyperliquid/hype/holders?limit=100",
headers={"X-API-Key": API_KEY},
)
# then: jq '.holders | (map(.total_amount) | add) as $all | ((.[:10] | map(.total_amount) | add) / $all)'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# top-100 holders whose realized-PnL label contains "smart"
r = requests.get(
"https://data.vike.io/v1/hyperliquid/hype/holders?limit=100",
headers={"X-API-Key": API_KEY},
)
# then: jq '.holders[] | select((.pnl_cohort // "") | test("smart")) | {wallet, rank, total_amount, pnl_cohort}'
Hyperliquid whale tracker FAQ
How often are Hyperliquid positions captured?
Is there a free Hyperliquid whale tracker?
Can I look up a single wallet?
/v1/hyperliquid/wallets/{address} and its sub-routes cover its positions, closed trades, fills, funding, ledger, orders and TWAPs. Or paste the address into the box above.How do I find the wallet behind a Hyperliquid PnL card?
/v1/hyperliquid/positions/match: it returns the open positions that match, closest entry price first. In Claude or ChatGPT, just describe the card.