Get a free key
Hyperliquid · Historical data

Hyperliquid historical data: trade history, candles and the order book

Hyperliquid historical data for backtests and research: every fill as one Parquet file a day, any wallet's trade history, candles and tick bars built from executed fills, the standing orders of the order book, and positions as they were at any past snapshot. The samples need no key.

Ask your AI · Claude, ChatGPT, CursorConnect in a minute →

“Give me BTC 1-minute candles on Hyperliquid for last Monday.”

hl_ohlcv

“Get me a download link for yesterday's Hyperliquid fills file.”

hl_archive
Coverage

How far back each Hyperliquid dataset goes

Every date below is read off the code that serves it.

DataDeliveryFromKeptWhere
Fills of one walletREST · MCPthe end of 2025-12-31no expiryOpen →
Fills of every wallet, one file a dayParquet2026-05-01every day sinceOpen →
Candles, time barsREST · MCP · WebSocketthe end of 2025-12-31no expiryOpen →
Candles, tick barsREST · MCPthe end of 2025-12-31built from the fillsOpen →
Position snapshotsREST · MCP2026-05-011 yearOpen →
Position snapshots, one file a dayParquet2026-05-08every day sinceOpen →
Standing ordersREST · MCP2026-07-295-minute snapshots from 2026-10-23 21:45 UTCOpen →
LiquidationsREST · MCP · WebSocketexact from 2026-08-03estimated beforeOpen →
Trade history

Every fill of any wallet

Side, price, size, fee, maker or taker and the PnL each fill closed, newest first.

Hyperliquid · API dataset · per wallet

Fills

Per-wallet fills with side, price, notional, fee, maker flag and closed PnL.

Route
/v1/hyperliquid/wallets/{address}/fills
Cadence
Continuous; archive one file per UTC day
Coverage
API: a wallet's fills, newest first, keyset-paged on (fill_ts, trade_id) — pass nextCursor back as cursor, limit up to 5,000; filter by symbol, side, start and end. Builder-routed fills have their own route, /builders/{builder}/fills. Archive: fills.parquet per UTC day from 2026-05-01 (CC BY 4.0), every fill of every wallet. Each file comes as a temporary link from /archive/url; /archive/datasets lists the days and the file's own columns.
Rows
MCP
hl_wallet_activity
Stream
hl.fills (from $1,000 unless you set min_usd)
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
tsstringFill time, ISO-8601 UTC with milliseconds
symbolstringSymbol; HIP-3 DEX symbols carry their DEX prefix, spot pairs are HL's @index
sidestringbuy | sell
directionstringbuy | sell (mirrors side)
size_tokennumberSize in coin units
pricenumberFill price
size_usdnumberNotional, USD
feenumberFee paid in fee_token; negative is a rebate
fee_tokenstringCurrency the fee is paid in
is_makerbooleanMaker (true) or taker (false)
crossedbooleanThe order crossed the book
closed_pnlnumberRealized PnL closed by this fill, USD
order_idintegerVenue order id
trade_idintegerVenue trade id
dex_namestringHL, or the HIP-3 DEX

Live: one wallet's fills

Fills tape · /wallets/{address}/fills

GET
Open this side to see the captured response.

    
address
symbol
limit
GET/v1/hyperliquid/wallets/{address}/fills?symbol={symbol}&limit={limit}

    
Press Send ▶ — the captured response appears here

    

The tape replays the fills captured for the most active wallet in the captured /traders reply. The builder's address chip is that same wallet.

GET /v1/hyperliquid/wallets/{address}/fills · Any wallet's trade history, fill by fill

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

ParameterInDescription
addressrequiredpathThe wallet
symbolqueryHL ticker
startqueryISO-8601 UTC bounds
endqueryISO-8601 UTC bounds
sidequerybuy | sell
limitqueryDefault 100, max 5000
cursorqueryKeyset cursor

Call it

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/hyperliquid/wallets/0xbf342cf5d1e4a4bb91b171c15e3cdbe82da3fcff/fills?symbol=BTC&limit=100"

Every fill of every wallet, one file a day: the Parquet archive.

Candles

Hyperliquid historical candles (OHLCV) from executed fills

Time bars and tick bars, perp and spot, the core venue and the HIP-3 DEXs: over REST, as an NDJSON export, and live.

Hyperliquid · API dataset · 1m–1d + ticks

Candles

Hyperliquid OHLCV built from executed fills — time bars and N-trade tick bars.

Route
/v1/hyperliquid/ohlcv
Cadence
Bars close every interval; closed bars also stream
Coverage
Time bars 1m 5m 15m 30m 1h 4h 1d from fill rollups (no TTL); tick bars (Nt, e.g. 15t = 15 trades) walked from raw fills, kept without expiry back to 2025-12-31. market=perp | spot; HL core plus the HIP-3 DEXs (dex=XYZ, CASH, HYNA, KM, FLX, VNTL, PARA, MKTS, IO). Closed bars stream on the hl.candles channel of wss://stream.vike.io/v1/stream/hl; /ohlcv/export streams a window as NDJSON.
Rows
MCP
hl_ohlcv
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
tsintegerBar open time, epoch milliseconds UTC
opennumberFirst fill price in the bar
highnumberHighest fill price
lownumberLowest fill price
closenumberLast fill price in the bar
volumenumberVolume in coin units
volume_usdnumberVolume, USD
n_tradesintegerFills in the bar
sourcestringEnvelope: the data that answered — 1m fills rollup, 1h fills rollup, or fills for tick bars

Live: BTC, hour by hour

Candles · /ohlcv

GET/v1/hyperliquid/ohlcv?symbol=BTC&interval=1h&market=perp&limit=48
Open this side to see the captured response.

    

Captured for BTC, ETH, SOL, HYPE at 1m, 15m, 1h, 4h, 1d, plus 15t tick bars for BTC: 48 bars each.

Intervals

Time bars 1m, 5m, 15m, 30m, 1h, 4h, 1d come from minute and hourly rollups kept from the end of 2025-12-31. Tick bars (15t: one bar per N trades) are built from the raw fills, kept without expiry; the answer's source says which answered.

Markets and DEXs

market=perp | market=spot. dex=HL is the core venue (perp and spot); the HIP-3 builder-deployed perp DEXs, XYZ, CASH, HYNA, KM, FLX, VNTL, PARA, MKTS, IO among them, are read live from the fills, so a newly deployed DEX works without a release.

Three ways out

REST /ohlcv, up to 5,000 bars a call, start and end as ISO-8601 UTC or epoch ms. Bulk /ohlcv/export as NDJSON. Live closed bars on hl.candles (time intervals only).

Build an /ohlcv request

symbol
market
limit
GET/v1/hyperliquid/ohlcv?symbol={symbol}&interval={interval}&market={market}&limit={limit}

    
Press Send ▶ — the captured response appears here

    

… or many coins per hour with /symbols/hourly

Many coins at once, hour by hour: close, open interest, funding rate and premium, up to 400 days in one call, from /symbols/hourly. Funding history and its route card: Funding rates.

symbols
days
GET/v1/hyperliquid/symbols/hourly?symbols={symbols}&days={days}

    
Press Send ▶ — the captured response appears here

    

NDJSON export

The first line names what answered: symbol, market, dex, interval, tz, source; every following line is one bar. The file comes as an attachment named hl_<symbol>_<interval>.ndjson.

bash
curl -H "X-API-KEY: $VIKE_API_KEY" -o hl_BTC_1h.ndjson \
  "https://data.vike.io/v1/hyperliquid/ohlcv/export?symbol=BTC&interval=1h&start=2026-01-01T00:00:00Z"

GET /v1/hyperliquid/ohlcv · Candles and tick bars from executed fills

CLI
vike-data candles hl
MCP
hl_ohlcv · 1 credit
Cost
1 request of the hourly limit

Hyperliquid candles, derived from executed fills.

Parameters

ParameterInDescription
symbolrequiredqueryPerp ticker (BTC), spot token (HYPE) or raw index (@107)
intervalquery1m | 5m | 15m | 30m | 1h | 4h | 1d, or Nt for N-trade bars. Default 1h
marketqueryperp | spot. Default perp
dexqueryHL core or a HIP-3 perp DEX, e.g. XYZ. Default HL. Builder DEXs are added over time, so do not hard-code a list
startqueryISO-8601 UTC or epoch ms, inclusive
endqueryISO-8601 UTC or epoch ms, exclusive
limitqueryDefault 500, clamped to 5000

Call it

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=1h&limit=48"

GET /v1/hyperliquid/ohlcv/export · The same bars as NDJSON, 5,000 a call

CLI
vike-data candles hl
MCP
hl_ohlcv · 1 credit
Cost
2 requests of the hourly limit

Stream a window as NDJSON. Billed 2 credits up front, because the response is a stream and its row count is unknown when the usage is recorded.

Parameters

ParameterInDescription
symbolrequiredqueryAs on /ohlcv
intervalqueryAs on /ohlcv. Default 1h
marketqueryAs on /ohlcv. Default perp
dexqueryAs on /ohlcv. Default HL
startqueryAs on /ohlcv
endqueryAs on /ohlcv
limitqueryDefaults to the maximum, 5000

Call it

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/hyperliquid/ohlcv/export?symbol=BTC&interval=1h&start=2026-01-01T00%3A00%3A00Z"
Archive

Hyperliquid Parquet archive: fills and positions, one file per UTC day

Fills from 2026-05-01, positions from 2026-05-08. A file has no URL of its own: you ask the API for a link, valid 7 days.

For

Backtest on full-day fills

If you are testing a signal against what actually traded, the fills file is every fill of the day with price, size, fee, whether the wallet was maker or taker and the realized PnL the node booked, sorted by asset so one asset is a slice of the file.

For

Positioning research without lookahead

If your question is how the crowd was positioned at a moment in the past, the positions files carry every snapshot with the size tier the wallet had when the row was written, so a historical row is not graded with today's label.

For

Whole-book snapshots without paging the API

If you need every open position at once, the latest positions file is one download of the current book, replaced every 5 minutes, instead of paging the positions route for minutes.

  1. Find the day

    /archive/datasets lists every published day with each file's rows and bytes, and the snapshot count of a positions day.

  2. Ask for a link

    /archive/url names one file and answers with a link that needs no key, valid 7 days.

  3. Download it whole

    Then read it locally with polars, pandas or DuckDB. The download is not counted against your hourly limit.

Download a day

bash
# 1. Which days exist, with rows, bytes and each positions day's snapshot count
curl -H "X-API-KEY: $VIKE_API_KEY" "https://data.vike.io/v1/hyperliquid/archive/datasets"

# 2. A link to one file: it needs no key, names that file only and works for 7 days
URL=$(curl -s -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-23" | jq -r .url)

# 3. Download the whole file, then read it locally
curl -f -o fills-2026-10-23.parquet "$URL"
  • Asking for a link is one ordinary request on your hourly budget; the download itself spends none, and there is no download quota.
  • A link works for any number of requests until it expires, so DuckDB or pyarrow can read byte ranges straight from it; for repeated queries, download the file once.
  • date=latest with dataset=positions is one file of the current open positions of every asset. The current open positions of every asset, one row per (wallet, asset, direction), refreshed about every 5 minutes. The columns are those of the daily positions file (meanings under schema.positions). snapshot_ts is per row: the ingestion cycle that last wrote the position. A position that closed within the last 15 minutes can still be present with an older snapshot_ts, the same rule as /v1/hyperliquid/positions; keep the rows at the file's snapshot_ts for the newest cycle only. There is no opened_at: /v1/hyperliquid/positions fills it per page, and joining it here costs 3x the rest of the run. Sorted by (asset, wallet, direction) in row groups of about 65,000 rows with min/max statistics (one asset is 1-2 of them). The file is REPLACED every ~5 minutes: download it whole (about 30 MB); a ranged read can straddle a replacement and fail, so retry it.
  • Licence CC BY 4.0: use it for anything, credit Vike.
Hyperliquid · REST · CLI · MCP

Which days exist, and what is in each file

Route
GET /v1/hyperliquid/archive/datasets
CLI
vike-data hl archive
MCP
hl_archive · 1 credit
Cost
1 request of the hourly limit
Free APIArchiveStreamMCP

Index of the Hyperliquid Parquet file archive: which UTC days exist and what is in each file.

One Parquet file per UTC day for fills (every fill) and positions (every 5-minute snapshot of every open position), from 2026-05-01. dates is newest first, each {"date": "YYYY-MM-DD", "streams": {"fills": {"rows", "bytes"}, "positions": {"rows", "bytes", "snapshots"}}}; snapshots is how many distinct 5-minute snapshots that day holds. schema lists every column of both datasets with its type and meaning. A day appears once it is complete (yesterday's files are published in the early UTC morning).

latest.positions is ONE file with the current open positions of every asset, replaced every 5 minutes (snapshot_ts, generated_at, rows, bytes, assets, note).

No daily or latest file has a direct URL and the folder cannot be listed: url_endpoint (/v1/hyperliquid/archive/url) answers with a 7-day link for exactly one file. The one exception is the free samples: samples_base is their public folder, and its files (manifest.json names them) are read with a plain GET or HEAD and no API key.

Parameters

None.

Call it

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/hyperliquid/archive/datasets"
Hyperliquid · REST · CLI · MCP

A 7-day download link for one file

Route
GET /v1/hyperliquid/archive/url
CLI
vike-data hl archive
MCP
hl_archive · 1 credit
Cost
1 request of the hourly limit
Free APIArchiveStreamMCP

A download link to ONE archive file, valid 7 days.

{"url", "expires_at", "expires_in", "dataset", "date", "bytes", "rows"}. The url is a presigned Cloudflare R2 link (host <account>.r2.cloudflarestorage.com): it needs no API key (the link is the credential), names exactly this file, and works for expires_in seconds (604800, 7 days) for any number of requests, so a reader that fetches byte ranges over HTTP (DuckDB, pyarrow) can use it directly. Once it expires, R2 answers 403: ask again. The call costs one credit and one request of the hourly budget like any route; the download itself spends none, and there is no download quota.

Parameters

ParameterInDescription
datasetrequiredqueryfills or positions. Anything else returns 400 naming both.
daterequiredqueryYYYY-MM-DD of a published UTC day, or latest (positions only: the file of the current open positions, replaced every 5 minutes). A day that is not published returns 400 naming the range that is.
redirectquery1 or true answers 302 with the link in Location; the JSON body is still sent, so a client that does not follow redirects keeps the answer.

Call it

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-23"
Schema

What is in a file

Every column of both files, as the exporter writes it.

fills.parquet · 16 columns

Every fill of every wallet on the day, one row per (wallet, fill). Sorted by asset, fill_ts, trade_id, wallet. A fill is identified by (wallet, fill_ts, trade_id). The two counterparties of a trade share trade_id, so a trade appears twice, once per wallet.

FieldTypeDescription
fill_tsDateTime64(3, 'UTC')Execution time of the fill, UTC, millisecond precision.
walletStringTrader address, lowercase 0x-hex.
assetStringInstrument as Hyperliquid names it: BTC on the main dex, dex:NAME (e.g. xyz:SP500) for a builder-deployed perp.
sideStringbuy or sell: the direction of THIS wallet's order.
size_tokenFloat64Fill size in base-asset units, unsigned (the direction is side).
priceFloat64Execution price, USD.
size_usdFloat64Notional of the fill, size_token * price, USD.
feeFloat64Fee charged in fee_token; negative is a maker rebate.
fee_tokenStringToken the fee is denominated in, e.g. USDC.
is_makerBoolTrue when this wallet's order was resting on the book.
order_idUInt64Hyperliquid order id (oid) of this wallet's order.
trade_idUInt64Hyperliquid trade id (tid). Both counterparties of one trade carry the same value; a fill is identified by (wallet, fill_ts, trade_id).
crossedBoolTrue when this fill crossed the book (the taker side).
closed_pnlFloat64Realized PnL in USD the node booked on this fill; 0 for a fill that opens or adds to a position.
dex_nameStringPerp dex the asset trades on: HL for the main dex, else the builder dex (e.g. XYZ).
start_positionFloat64 (nullable)Signed position in the asset immediately BEFORE this fill (negative is short). NULL for fills before 2026-09-29, when the column was added; 0.0 is a real value (flat before the fill).

positions.parquet · 19 columns

Every open position at every snapshot of the day (about every 5-7 minutes), one row per (wallet, asset, snapshot). Sorted by asset, wallet, snapshot_ts. Snapshots are not evenly spaced, and a source outage that could not be rebuilt leaves a gap that is published as it is: snapshots on the day's entry counts them. A position held across snapshots appears in each. account_value and pnl_cohort are as of the START of the row's clock hour (equity and fills strictly before it; pnl_cohort is one hour earlier than the API's point-in-time label; meanings under schema.positions). Hours the source rebuilt by replaying fills instead of reading a node state file are listed in reconstructed_hours on the day's entry (reconstructed, not measured: margin_used and liquidation_price are 0, state_ts is 1970-01-01). Sizes matched the next real snapshot at 97 % or better, except the hours also listed in reconstructed_lower_match_hours, which matched at 83-97 %.

FieldTypeDescription
snapshot_tsDateTime('UTC')Snapshot instant, UTC, whole minutes: the START of the ingestion cycle that wrote the row, not the instant of the node state it reads (typically 5-10 minutes earlier). Cycles are usually 5-7 minutes apart and irregular; a source outage leaves a longer gap. The day's snapshots count in the manifest says how many there are.
walletStringTrader address, lowercase 0x-hex.
assetStringInstrument as Hyperliquid names it: BTC on the main dex, dex:NAME (e.g. xyz:SP500) for a builder-deployed perp. Called symbol in /v1/hyperliquid/positions. The prefix is authoritative: judge the dex by it, not by dex_name.
directionInt81 long, -1 short. The only place the side is stored: size_token and size_usd are never negative.
size_tokenFloat64Position size in base-asset units, unsigned (the side is direction).
size_usdFloat64Notional of the position at mark_price, size_token * mark_price, USD, unsigned.
entry_priceFloat64Average entry price of the position, USD.
mark_priceFloat64Mark price when the row was written, USD.
liquidation_priceFloat64Liquidation price, USD; 0 when the position has none (e.g. a well-collateralised cross-margin position).
unrealized_pnlFloat64Unrealized PnL in USD, direction * (mark_price - entry_price) * size_token.
leverageFloat32Leverage of the position as a multiple (10 = 10x). 0 when none was recorded, which happens on cross-margin rows.
margin_usedFloat64Margin the position ties up, USD: size_usd / leverage, or size_usd itself where leverage is 0.
size_cohortStringAccount-value size tier of the wallet WHEN THE ROW WAS WRITTEN (shrimp, 2x shrimp, fish, ... up to 4x whale: 12 absolute-dollar thresholds assigned at ingestion), as stored: a point-in-time label, not today's grading. The same field and vocabulary as size_cohort in /v1/hyperliquid/positions.
leverage_typeStringcross or isolated.
dex_nameStringPerp dex the asset trades on: HL for the main dex, else the builder dex (e.g. XYZ). Rows written while a clearinghouse was not yet registered hold the literal clsN (e.g. cls10) and keep it; the asset prefix is authoritative.
state_tsDateTime('UTC')The instant the state-derived columns (size, entry, mark, unrealized_pnl, leverage, margin_used, direction) describe, read from the node's state file; snapshot_ts is the WRITE time of the ingestion cycle, typically 5-10 minutes later (liquidation_price is re-read from the node at write time and belongs to snapshot_ts). 1970-01-01 00:00:00 means the row came from no state file (the per-wallet API fallback) or was written before 2026-08-22, when the column was added. Do not anchor a projection of the row on it: use snapshot_ts.
liq_progressFloat64How far the mark has moved from entry toward liquidation, clamped to 0..1: 0 at or in profit versus entry (or no liquidation price), 1 at or through the liquidation price. When a cross-margin liquidation price has drifted past entry it falls back to liquidation_price / mark_price (long) or mark_price / liquidation_price (short). The same SQL as liq_progress in /v1/hyperliquid/positions.
account_valueFloat64 (nullable)Native Hyperliquid perp account value of the wallet, USD (the quantity /v1/hyperliquid/wallets/{address} serves as equity.account_value), AS OF THE START OF THE ROW'S CLOCK HOUR: the wallet's last snapshot of the previous hour (a row at 10:37 carries the 09:5x value). Builder-DEX account equity is NOT included, so a wallet trading only dex:NAME assets usually reads 0. In latest, as of the start of the hour of the file's newest snapshot (an older hour while the hourly rollup lags), so on the rows of positions that closed in the last 15 minutes it can be up to 15 minutes later than the row. NULL when unknown: the wallet had no snapshot in that previous hour (e.g. its first position opened in the row's hour); the stored value is a reconstruction, not a measurement (hours rebuilt from fills, and the values the 2026-08-10 repair rewrote); or the row is a builder-DEX position (dex_name other than HL) whose value comes from an hour up to 2026-08-10 00:48 UTC (the repair seam): until then a builder-DEX-only wallet's empty native account was stored as a non-equity figure the repair did not catch every time, and a genuine balance cannot be told apart from a fabricated one, so genuine values are withheld on those rows too. The same wallet's HL rows in the same snapshot keep the value; only its builder-DEX rows read NULL.
pnl_cohortStringRealized-PnL percentile cohort of the wallet AS OF THE START OF THE ROW'S CLOCK HOUR: graded on fills strictly before the row's hour (the hourly label of the previous hour). This is ONE HOUR EARLIER than the label /v1/hyperliquid/positions returns for the same row in historical mode (start given), where a row graded from the hourly label table carries pnl_cohort_basis = point_in_time: that label is the row's own hour and so counts the fills of up to 59 minutes after the row. In latest, as of the start of the hour of the file's newest snapshot (an older hour while the label rollup lags), so on the rows of positions that closed in the last 15 minutes it can count up to 15 minutes of fills after the row. unknown for a wallet with fewer than 10 closed trades then, or with no realized record that hour; never empty.
Samples

Try it with no key

One BTC hour of fills and one BTC position snapshot, the same columns as the archive.

Order book

Standing orders: what was resting, at any instant

Limit orders on the book and the stops and take-profits waiting to trigger, for a coin or a wallet.

What was resting on a market at a 5-minute snapshot: every order, with its price, size, side and type. The snapshots begin 2026-10-23 21:45 UTC; earlier instants, back to 2026-07-29, are rebuilt from checkpoints about 12 minutes apart, and a rebuild can miss short-lived orders. Each answer's source says which feed answered: l4_5m or state_12m.

/wallets/{address}/orders is one wallet's order history (what was resting, filled or canceled) on the Whale tracker; /symbols/{symbol}/order-clusters is where a coin's stops and limits cluster, on the Liquidations page.

Hyperliquid · REST · CLI · MCP

Every order resting at one instant

Route
GET /v1/hyperliquid/orders
CLI
vike-data hl orders
MCP
hl_orders · 1 credit
Cost
1 request of the hourly limit
Free APIArchiveStreamMCP

The orders resting at one instant: every order in a 5-minute snapshot, or a rebuild from the sightings around it when no complete 5-minute snapshot exists.

Returns snapshotTs, source (l4_5m | state_12m), orders, nextCursor. The 5-minute snapshots start at 2026-10-23 21:45 UTC; before that, and after a stalled feed's last snapshot, the answer is rebuilt from the 12-minute checkpoints. A rebuilt answer for a past at lists only the orders seen before the instant and again after it, so short-lived orders can be missing, and its snapshotTs is the at floored to 5 minutes; an at inside an outage of either feed is answered the same way. Rows in key order (dex, symbol, side, oid); the cursor pins the snapshot.

Parameters

ParameterInDescription
symbolqueryHL perp ticker, e.g. BTC or xyz:TSLA. symbol and/or wallet is required
walletqueryOne wallet. symbol and/or wallet is required
atqueryISO-8601 UTC, floored to 5 minutes. Default: the newest snapshot. Not before 2026-07-29, not in the future
oidqueryOne order id
order_typequeryLimit | Stop Market | Stop Limit | Take Profit Market | Take Profit Limit | Trailing Stop Market
created_fromqueryISO-8601 UTC. Placed at or after
created_toqueryISO-8601 UTC. Placed at or before
limitqueryDefault 100, max 1000
cursorquerynextCursor from the previous page, verbatim

Call it

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/hyperliquid/orders?symbol=BTC&limit=100"
Live

Closed candles on a WebSocket

The bars of /ohlcv, pushed the moment they close.

  • One URL, wss://stream.vike.io/v1/stream/hl: send your key in the X-API-KEY header, then one subscribe frame per channel.
  • The server pings every 15 s: answer with pong. 1 connection per key on this path, 100 subscriptions on one connection.
  • Delivery is at least once: dedupe on event.event_id. Dropped? Subscribe again with your last cursor: you get what you missed, up to 3 days back; without a socket, /v1/hyperliquid/stream-events reads the same events.
  • A channel runs while someone subscribes to it; on a quiet channel the first events come with the next pass.
Hyperliquid · WebSocket

hl.candles

Every closed bar of every coin that traded, at the time intervals of /ohlcv, read from the same rollups: the bars of /ohlcv, pushed.

Path
wss://stream.vike.io/v1/stream/hl
Filters
coin, dex, interval, market
Free APIArchiveStreamMCP

Filters

FieldTypeDescription
coinlist ≤ 200The symbol, e.g. BTC or xyz:TSLA; on hl.candles a spot token or its @index too.
dexlist ≤ 50HL, the core venue, or a HIP-3 builder DEX.
intervallist ≤ 50The bar's interval. One of: 15m, 1d, 1h, 1m, 30m, 4h, 5m.
marketlist ≤ 50perp or spot. One of: perp, spot.

Subscribe

python
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": "bars", "channel": "hl.candles",
                        "filter": {"coin": ["BTC"], "interval": ["1m"]}}))
    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(json.dumps(e))   # keep frame["cursor"] to resume after a drop
API

The historical data routes

Each one is a card above; every parameter of every route is also in the API reference.

RouteWhat it answersReference
GET /v1/hyperliquid/wallets/{address}/fillsAny wallet's trade history, fill by fillAPI reference →
GET /v1/hyperliquid/ohlcvCandles and tick bars from executed fillsAPI reference →
GET /v1/hyperliquid/ohlcv/exportThe same bars as NDJSON, 5,000 a callAPI reference →
GET /v1/hyperliquid/archive/datasetsWhich days exist, and what is in each fileAPI reference →
GET /v1/hyperliquid/archive/urlA 7-day download link for one fileAPI reference →
GET /v1/hyperliquid/ordersEvery order resting at one instantAPI reference →
11 studies

Historical data 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.

Hyperliquid · API

Download every Hyperliquid fill for a day as Parquet and load it in DuckDB

Ask /v1/hyperliquid/archive/url?dataset=fills&date=YYYY-MM-DD for a 7-day link to the day's Parquet file, download it whole, and query it in DuckDB. The 2026-10-23 fills file is 0.36 GB (11.9 million rows).

Uses
/archive/datasets, /archive/url
Verified
live API, 2026-11-03: 4 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Give me a download link for the Hyperliquid fills file of 2026-10-23”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# ask for the link and download the 2026-10-23 fills file in one step
r = requests.get(
    "https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-23&redirect=1",
    headers={"X-API-Key": API_KEY},
)
with open("fills-2026-10-23.parquet", "wb") as f:
    f.write(r.content)
Hyperliquid · API

Try Hyperliquid fills and positions Parquet with no API key

Download a free sample of Hyperliquid fills and positions as Parquet with no key: one BTC hour of fills and one BTC position snapshot.

Uses
/archive/datasets
Verified
live API, 2026-11-03: 4 calls, all 200
Free APIArchiveStreamMCP

The code

python
import requests

# what the free samples are: the sample day, the files and the schema; no API key
r = requests.get(
    "https://data.vike.io/archive/hl-samples/manifest.json",
)
Hyperliquid · API

Download the current open positions of every Hyperliquid asset, refreshed every 5 minutes

One Parquet file holds every open position of every wallet, replaced about every 5 minutes; /v1/hyperliquid/archive/url?dataset=positions&date=latest links to it. The file is about 33 MB (32.7 MB and 425,727 positions at 17:41 UTC on 2026-11-03).

Uses
/archive/datasets, /archive/url, /positions
Verified
live API, 2026-11-03: 3 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Give me a download link for the file of every open Hyperliquid position right now”

The code

python
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 asset 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)
Hyperliquid · API

Is a day of Hyperliquid snapshots complete? Count the 5-minute snapshots and spot gaps

Each day's positions file has a snapshots count and a list of the hours that were rebuilt in /v1/hyperliquid/archive/datasets; the gaps inside a day come from the file's own snapshot_ts values. The positions file of 2026-10-23 is 1.98 GB (122.7 million rows, 286 snapshots): the verification run read its first 1 MB, not the whole file.

Uses
/archive/datasets, /archive/url
Verified
live API, 2026-11-03: 3 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Which days of the Hyperliquid positions archive have fewer than 288 five-minute snapshots?”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# snapshots, rows and rebuilt hours of every published positions day, newest first
r = requests.get(
    "https://data.vike.io/v1/hyperliquid/archive/datasets",
    headers={"X-API-Key": API_KEY},
)
# then: jq '[.dates[] | select(.streams.positions) | {date, snapshots: .streams.positions.snapshots, rows: .streams.positions.rows, reconstructed_hours: .streams.positions.reconstructed_hours}]'
Hyperliquid · API

Load a month of Hyperliquid fills into Polars or your own database

Read the month's file sizes from /archive/datasets, then for each day ask /archive/url for a 7-day link, download it, keep the rows you need and delete the raw file; a month of fills is about 9 to 11 GB, so at most one raw day is on disk at a time. Measured: September 2026 is 30 files and 9.09 GB, the 30 newest days 10.6 GB, 2026-09-01 alone 0.30 GB. The verification run downloaded that first day only, not the whole month.

Uses
/archive/datasets, /archive/url
Verified
live API, 2026-11-03: 6 calls, all 200
Free APIArchiveStreamMCP

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# days and GB of the month's fills files
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)}'
Hyperliquid · API

Backtest a trading strategy on Hyperliquid 1-minute candles

Page /v1/hyperliquid/ohlcv with interval=1m and limit=5000, moving start one minute past each page's last candle, and write the bars to a CSV your backtester reads.

Uses
/ohlcv, /ohlcv/export, /symbols/hourly
Verified
live API, 2026-11-03: 13 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Get the 1-minute BTC candles on Hyperliquid from 2026-10-01 00:00 to 03:00 UTC”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# the first page of a backtest window: up to 5,000 BTC minutes from 2026-10-01 00:00 UTC
r = requests.get(
    "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=1m&start=2026-10-01T00:00:00Z&limit=5000",
    headers={"X-API-Key": API_KEY},
)
Hyperliquid · API

Hyperliquid OHLCV from fills, incl. HIP-3 and spot; CSV/Parquet backfill

Candles built from Hyperliquid's own fills for core perps, HIP-3 builder-dex perps (dex=XYZ and the dex-prefixed symbol) and spot (market=spot), from /v1/hyperliquid/ohlcv; page it with start and turn it into CSV with jq.

Uses
/ohlcv, /ohlcv/latest
Verified
live API, 2026-11-03: 5 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Get hourly candles for xyz:PLATINUM on the XYZ dex of Hyperliquid for the last day”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# hourly candles of a HIP-3 market: the dex-prefixed symbol and its dex
r = requests.get(
    "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=xyz:PLATINUM&dex=XYZ&interval=1h&limit=3",
    headers={"X-API-Key": API_KEY},
)
Hyperliquid · API

Build 1-second candles for a Hyperliquid coin

The API's time bars start at 1 minute; build 1-second bars from the archive's daily fills file by keeping the taker row of each trade, ordering by fill_ts and trade_id, and bucketing by second. Downloads one fills day: 0.36 GB for 2026-10-23.

Uses
/archive/url, /ohlcv
Verified
live API, 2026-11-03: 3 calls, all 200
Free APIArchiveStreamMCP

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# download one UTC day of every fill: redirect=1 answers with the link and -L follows it
r = requests.get(
    "https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-23&redirect=1",
    headers={"X-API-Key": API_KEY},
)
with open("fills-2026-10-23.parquet", "wb") as f:
    f.write(r.content)
Hyperliquid · API

Classify each Hyperliquid fill as open, add, reduce, close or flip

Every fill in the archive's fills file carries start_position, the wallet's signed position just before the fill; add the signed fill size to get the position after, and the pair of numbers names the action. Downloads one fills day: 0.36 GB for 2026-10-23.

Uses
/archive/url
Verified
live API, 2026-11-03: 2 calls, all 200
Free APIArchiveStreamMCP

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# download one UTC day of every fill: redirect=1 answers with the link and -L follows it
r = requests.get(
    "https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-23&redirect=1",
    headers={"X-API-Key": API_KEY},
)
with open("fills-2026-10-23.parquet", "wb") as f:
    f.write(r.content)
Hyperliquid · API

Who traded against whom? Pair both counterparties of every Hyperliquid trade

In the archive's daily fills file both sides of a trade share trade_id; join the buy rows to the sell rows on asset, fill_ts and trade_id to get one row per trade with its buyer and seller. Downloads one fills day: 0.36 GB for 2026-10-23.

Uses
/archive/url
Verified
live API, 2026-11-03: 2 calls, all 200
Free APIArchiveStreamMCP

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# download one UTC day of every fill: redirect=1 answers with the link and -L follows it
r = requests.get(
    "https://data.vike.io/v1/hyperliquid/archive/url?dataset=fills&date=2026-10-23&redirect=1",
    headers={"X-API-Key": API_KEY},
)
with open("fills-2026-10-23.parquet", "wb") as f:
    f.write(r.content)
Hyperliquid · API

Positions of a Hyperliquid wallet or coin at a past time

Pass start and end to /v1/hyperliquid/positions with a symbol or a wallet, and it returns the open positions of the snapshots inside that window, labelled as they stood then.

Uses
/positions
Verified
live API, 2026-11-03: 5 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Which BTC positions were open on Hyperliquid at 12:00 UTC on 2026-10-01?”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# every open BTC position in the snapshots between 12:00 and 12:05 UTC on 2026-10-01
r = requests.get(
    "https://data.vike.io/v1/hyperliquid/positions?symbol=BTC&start=2026-10-01T12:00:00Z&end=2026-10-01T12:05:00Z&limit=3",
    headers={"X-API-Key": API_KEY},
)
FAQ

Hyperliquid historical data FAQ

How do I get Hyperliquid historical data?
Over REST with one free key: candles from the end of 2025-12-31, 5-minute position snapshots kept for one year, and wallet fills kept with no expiry, back to 2025-12-31. Candles also come as an NDJSON export.
How far back do the candles go?
Time bars from the end of 2025-12-31 UTC. Tick bars are built from raw fills, kept without expiry back to 2025-12-31.
Can I get candles for HIP-3 DEXs and spot pairs?
Yes: pass dex for a builder-deployed perp DEX and market=spot for a spot pair. Symbols can be a perp ticker, a spot token or a raw index such as @107.
How do I download a Hyperliquid file?
Ask for a link, then download it. GET /v1/hyperliquid/archive/url?dataset=fills&date=YYYY-MM-DD (or dataset=positions, or date=latest for the current open positions) returns a Cloudflare R2 URL for exactly one file. The URL needs no key and works for 7 days, for any number of requests; download the whole file and read it locally. There is no download quota.
Why is there no folder to browse?
Files are handed out on request. Nothing under the archive path for Hyperliquid is reachable directly, with or without a key; GET /v1/hyperliquid/archive/datasets lists which days exist, and each file is a separate link request. The free samples are the one exception.
Do downloads count against my hourly limit?
The download does not. Asking for the link is one ordinary API request and counts as one; the file transfer behind the link is never counted.
How far back do the files go?
The archive starts on 2026-05-01: fills have a file for every day since; positions start on 2026-05-08, the first day with 5-minute snapshots. Earlier history is not published as files.
Why does a positions day sometimes hold fewer snapshots?
The source captured fewer on some days, and a file is never padded. The snapshots field of GET /v1/hyperliquid/archive/datasets says how many a day holds (286 on 2026-10-23). Summing a positions file over an hour counts each position about 12 times: group by snapshot_ts or take one snapshot.
How current are the files?
A daily file is published in the early UTC morning after its day closes. The latest positions file is replaced about every 5 minutes; download it whole.
Is there Hyperliquid order book data?
Yes: /v1/hyperliquid/orders lists every order resting at one instant for a coin or a wallet, from the node's 5-minute order snapshots, and back to 2026-07-29 rebuilt from checkpoints about 12 minutes apart.