Hyperliquid WebSocket API
Critical Rules
- WebSocket URL:
wss://hypercore.goldrushdata.com/ws?key=<GOLDRUSH_API_KEY>(note:hypercore, nothyperliquid; auth is a?key=query parameter, not anAuthorizationheader). - Wire-compatible with
wss://api.hyperliquid.xyz/wsfor shared subscription types (e.g.l2Book). - No 1000-subscription-per-IP cap. Multiplex many subscriptions on one connection.
l2Book- aggregated price-level snapshots{px, sz, n}.coinis optional - omit it to stream every asset over a single subscription. Whencoinis omitted,marketTypesdefaults to["perp"](perps only); pass["spot"],["outcome"], a mix, or["*"]to opt into spot, outcome, and any future market types.l2BookDiff- GoldRush-native L2 diff transport. Same aggregated{px, sz, n}shape asl2Book, but emits oneSnapshotper subscribed coin and then per-blockUpdatescarrying only changed levels.coinaccepts a single asset, an array of assets, or can be omitted for wildcard (samemarketTypesdefault — perps only — applies whencoinis omitted). Treatsz: "0"(withn: 0) as level removal. Not available on the public Hyperliquid WebSocket.l4Book- GoldRush-native order-level stream withuser,oid,cloid,tif, and trigger metadata per order.coinis required. Emits a singleSnapshoton subscribe, then per-blockUpdates(order_statuses+book_diffs). Not available on the public Hyperliquid WebSocket.
Available Subscriptions
| Channel | Subscription body | Returns |
|---|---|---|
l2Book | {"type":"l2Book","coin":"BTC"} (or omit coin) | Full L2 book snapshot per tick with bids/asks aggregated by significant figures. Self-healing - every message is a complete snapshot. |
l2BookDiff | {"type":"l2BookDiff","coin":"HYPE"}, {"type":"l2BookDiff","coin":["HYPE","BTC","ETH"]}, or omit coin for wildcard | Initial Snapshot per coin (aggregated {px, sz, n}), then per-block Updates with book_diffs grouped by coin carrying only changed levels. sz: "0" means level removed. GoldRush-native, no upstream equivalent. |
l4Book | {"type":"l4Book","coin":"BTC"} | Initial Snapshot of every resting order, then per-block Updates with order_statuses (lifecycle) and book_diffs (per-order changes). GoldRush-native, no upstream equivalent. |
Subscribe / Unsubscribe Pattern
When to use which channel
| Need | Use |
|---|---|
| Top-of-book, spread, depth-weighted mid, slippage / impact estimator | l2Book |
| Stream every asset on one subscription | l2Book (omit coin) or l2BookDiff (omit coin) |
Aggregated {px, sz, n} book state with diff-only bandwidth, single coin / list / wildcard | l2BookDiff |
| Multi-coin coverage with a fixed list of assets in one subscription | l2BookDiff with coin: ["HYPE","BTC","ETH"] |
| Queue position, per-user flow attribution, microstructure analytics | l4Book |
| Reconstruct an L2-style aggregated view but keep order-level detail | l4Book (aggregate client-side) |
| OHLCV candles instead of raw book state | Streaming API ohlcvCandlesForPair (see streaming.md) |
The GoldRush Hyperliquid WebSocket API is a drop-in replacement for
wss://api.hyperliquid.xyz/ws. Subscription payloads, channel names, and message shapes are byte-for-byte identical to the public Hyperliquid feed. The only difference is the connection URL - authentication is a required key query parameter, so no header changes are needed in your client.
Endpoint
Comparison with the public Hyperliquid WebSocket
| Public WebSocket | GoldRush | |
|---|---|---|
| URL | wss://api.hyperliquid.xyz/ws | wss://hypercore.goldrushdata.com/ws?key= |
| Auth | None | key query parameter (required) |
| Subscriptions per IP | 1000 | No cap |
| Wire compatibility | n/a (it’s the source) | Byte-for-byte |
| Available channels | See Hyperliquid Docs | See Available subscriptions |
Available subscriptions
| Channel | Subscription body | Returns |
|---|---|---|
l2Book | {"type": "l2Book", "coin": "BTC"} | Real-time L2 order book snapshots - bids and asks aggregated by significant figures. coin is optional - omit it to stream every asset on one subscription. |
l2BookDiff | {"type": "l2BookDiff", "coin": "HYPE"} | GoldRush-native L2 diff transport - initial Snapshot per coin plus per-block Updates carrying only changed {px, sz, n} levels. coin accepts a single asset, an array of assets, or can be omitted to stream every asset. Not available on the public Hyperliquid WebSocket. |
l4Book | {"type": "l4Book", "coin": "BTC"} | GoldRush-native order-level book stream - initial Snapshot of every resting order plus per-block Updates with order_statuses and book_diffs. Exposes user, oid, cloid, tif, and trigger metadata per order. coin is required. Not available on the public Hyperliquid WebSocket. |
Limits
No 1000-subscription-per-IP cap. Onl2Book and l2BookDiff, filter parameters are optional - omit coin to stream the full L2 book across every asset on a single subscription. The wildcard defaults to perps only (marketTypes: ["perp"]); pass ["spot"], ["outcome"], a mix, or ["*"] to opt into spot, outcome, and future market types. l2BookDiff additionally accepts an array of coin symbols for a fixed multi-asset subscription. l4Book requires coin and is one-asset-per-subscription. See Limits & Connections for details.
For richer real-time analytics (pre-decoded HyperCore fills, liquidations, vault events, OHLCV across every HIP-3/HIP-4 market), pair the WebSocket with the GraphQL Streaming API.
Moving from the public Hyperliquid WebSocket to GoldRush is one change:
- URL - replace
wss://api.hyperliquid.xyz/wswithwss://hypercore.goldrushdata.com/ws?key=.
key query parameter, so no header swap is needed in your client.
Side-by-side
wscat
Public Hyperliquid
GoldRush
JavaScript / TypeScript
Public Hyperliquid
GoldRush
Python
Public Hyperliquid
GoldRush
Behavioral notes
Things to be aware of when you cut over.Stream payloads are byte-equal, modulo live drift
Thechannel name and data shape match Hyperliquid byte-for-byte - same keys, same nesting, same value types. Numeric fields update independently on each side, so a price level may differ by tens of milliseconds, but the schema is identical.
Auth errors close the connection
A missing or invalidkey query param returns HTTP 401 on the upgrade handshake, so the WebSocket never opens. Public Hyperliquid has no auth and never rejects the handshake.
Filter parameters are optional on GoldRush
Parameters that the public Hyperliquid WebSocket requires (e.g.coin on l2Book) are optional on GoldRush. Omit them to stream the entire channel on a single subscription instead of fanning out one subscription per asset. See Limits.
Existing SDKs work after a wsUrl override
Most popular Hyperliquid SDKs accept a WebSocket base URL override - point them at wss://hypercore.goldrushdata.com/ws?key= and the rest of the SDK works unchanged. See SDK compatibility for the override snippets.
Authentication
The WebSocket API uses your standard GoldRush API key, passed as akey query parameter at connection time. The same key works against the Foundational API, the Streaming API, the Pipeline API, and the Info API. If you don’t have one yet, sign up here.
Never hardcode keys in source. Use environment variables or a secrets manager.
What you gain
- No subscription cap. No 1000-subscription-per-IP limit; multiplex hundreds of subscriptions on a single connection.
- Wildcard subscriptions. Omit filter parameters to stream the entire channel - e.g. the full L2 order book across every asset on one subscription.
- One key for everything Hyperliquid. The same API key unlocks Streaming, Pipeline, the Info API, and HyperEVM via the Foundational API.
The most popular Hyperliquid SDKs work against the GoldRush WebSocket API after a one-line URL override. Authentication is a
key query parameter on the connection URL - no header injection is needed.
JavaScript / TypeScript: nomeida/hyperliquid
Install
npm
yarn
Configure
Note: If your SDK version doesn’t expose a wsUrl option, instantiate the WebSocket client manually and pass it to the SDK, or patch the constant the SDK uses. See the override fallback below.
Manual WebSocket fallback
When the SDK doesn’t expose awsUrl knob, bypass it and drive the raw socket yourself:
Python: hyperliquid-dex/hyperliquid-python-sdk
Install
Configure
Tip: The SDK’sInfoclass manages both REST and WebSocket. If you only need WebSocket, you can skip thesession.headers.update(...)line. If you only need REST, passskip_ws=Trueinstead.
Verification
After cutover, confirm everything is wired correctly:- Diff a known subscription - subscribe to
l2Bookfor the same coin against both endpoints; the streamedchannelanddatashape (keys, nesting, types) should match exactly. - Confirm auth - remove the
keyquery parameter and confirm the WebSocket upgrade fails with HTTP401. If the socket opens, your request isn’t reaching GoldRush. - Confirm wildcard - subscribe to
l2Bookwithout acoinand confirm you receive book snapshots for multiple assets. This call would be rejected on the public Hyperliquid WebSocket.
Other SDKs
The pattern is the same for any WebSocket client: override the connection URL towss://hypercore.goldrushdata.com/ws?key=. If you run into a specific SDK that doesn’t expose a URL override, email us - we’ll publish a recipe.
No subscription cap
The GoldRush Hyperliquid WebSocket API has no per-IP, per-key, or per-connection subscription cap. The 1000-subscription-per-IP limit on the public Hyperliquid WebSocket does not apply. You can:- Open as many concurrent subscriptions as your client supports.
- Multiplex hundreds of
l2Booksubscriptions on a single connection. - Track every active wallet, market, and asset from one process.
Wildcard subscriptions
Filter parameters that the public Hyperliquid WebSocket requires are optional on GoldRush. Omit them to stream the entire channel on one subscription instead of fanning out one subscription per asset.| Channel | Public Hyperliquid | GoldRush |
|---|---|---|
l2Book | coin required - one subscription per asset | coin optional - omit it to stream the full L2 order book across every asset on a single subscription |
How streaming works
Messages are pushed directly from a live Hyperliquid ingestion pipeline - no polling, no cache delay. Latency from upstream Hyperliquid event to your client is dominated by network round-trip from our Tokyo nodes.| Channel | Push trigger |
|---|---|
l2Book | Every L2 update on the subscribed coin (or every coin, if wildcard). |
Connection management
You’re not rate-limited, but a few client-side defaults are worth tuning.| Behavior | Recommended client setting |
|---|---|
| Reconnect | On unexpected close, reconnect with exponential backoff capped at ~30 seconds. Re-send your subscription messages after the new socket opens. |
| Heartbeat | Send an application-level ping every 30 seconds. The server replies with pong. Most WebSocket libraries handle this automatically; verify yours does. |
| Max message size | L2 book snapshots for wildcard subscriptions can exceed 1 MB. Raise your client’s maxPayload (Node ws library) or max_size (Python websockets) if you’re receiving truncated messages. |
| Backpressure | If your handler can’t keep up with incoming messages, your client buffer will fill. Drain to a queue or downstream consumer; don’t block the read loop on application work. |
Reconnect sketch
TypeScript
Python
Watch out for client-side limits
GoldRush has no caps, but the rest of your stack might:- OS file descriptor limits - if you’re opening many connections in parallel, raise
ulimit -n. - Reverse proxy idle timeouts - if you’re terminating WS through nginx, HAProxy, or a cloud load balancer, set the idle timeout above your heartbeat interval (typically 60 seconds minimum).
- Browser concurrency - browsers limit WebSocket connections per origin; one connection multiplexing many subscriptions is always preferable to many connections.
Network and TLS
- HTTP/1.1 Upgrade to WSS is supported (standard WebSocket handshake).
- TLS 1.2+ required.
- Compression (
permessage-deflate) is negotiated when offered by the client.
Need higher guarantees?
Enterprise SLA, dedicated capacity, regional pinning, and on-prem options are all available. Email sales.WebSocket API Reference
L2 Order Book Diff
Credit Cost: 0.1 per coin per minute Processing: RealtimeNote: - GoldRush-native.l2BookDiffis not exposed onwss://api.hyperliquid.xyz/ws. Pointing a client at the public endpoint with this subscription type will fail.
- Snapshot, then diffs. The first message is always a
Snapshot; every message thereafter is anUpdates. Clients must seed local book state from the snapshot and apply diffs from there. On reconnect, drop local state and re-seed from the next snapshot. coinis optional. Omit it to stream the entire L2 order book across every asset on a single subscription.- When
coinis omitted, the optionalmarketTypesfilter selects which market families to include. It defaults to["perp"]only. - Pass
"marketTypes": ["spot"], or"marketTypes":["outcome"], or a mix (e.g."marketTypes": ["perp","spot"]), or use the wildcard"marketTypes": ["*"]to opt into spot, perps, outcome, and any future market types. - No 1000-subscription-per-IP cap - multiplex hundreds of
l2BookDiffsubscriptions on a single connection. - For OHLCV candles instead of raw book state, use the Streaming API OHLCV streams.
coin is omitted, a credit rate of 10 credits per minute subscribed is applied.
Endpoint
Authorization header is used.
Subscribe
Send this JSON message after the connection is established:| Parameter | Type | Required | Description |
|---|---|---|---|
method | string | Yes | Always "subscribe". |
subscription | object | Yes | __RESPONSE_ROW__type string Always "l2BookDiff". __RESPONSE_ROW__coin string | string[] Asset filter. Accepts three shapes: - String - a single asset symbol (e.g. "HYPE", "BTC", "@107" for spot pairs). For HIP-3 markets, include the deployer prefix. - Array of strings - a fixed list of asset symbols (e.g. ["HYPE", "BTC", "ETH"]). Each listed coin gets its own initial Snapshot; subsequent Updates may bundle diffs for any subset of the list per block. - Omitted - wildcard. Streams the full L2 book across every perp asset by default on one subscription (see marketTypes to include spot or outcome markets). The server emits one Snapshot per live coin, then per-block Updates covering only the coins that changed. __RESPONSE_ROW__marketTypes string[] Optional. Selects which market families a wildcard subscription includes. Only valid when coin is omitted. Defaults to ["perp"] — when omitted, only perp markets stream. Spot and outcome markets require explicit opt-in. Accepted values: - "perp" (default) — vanilla perps and HIP-3 deployer-perps (e.g. BTC, ETH, HYPE, SOL, cash, abcd, USA500). - "spot" — @ spot markets and legacy spot pairs (e.g. @1, @107 for HYPE spot, PURR/USDC). Not included by default. - "outcome" — HIP-4 prediction-market outcomes (e.g. #700, #710, #741). Not included by default. - "*" — every current type ("perp" + "spot" + "outcome") and auto-opt-in to any future types the server adds. Mix and match in one subscription, e.g. ["perp", "outcome"]. A second subscribe with a different marketTypes value replaces the previous filter rather than coexisting with it. |
Example
Pick the subscription shape that matches the coverage you want. Every subscription starts with oneSnapshot per coin in scope, then per-block Updates carrying only changed levels:
| Subscribe with | What you receive |
|---|---|
{"type":"l2BookDiff","coin":"HYPE"} | Snapshot + diffs for HYPE only |
{"type":"l2BookDiff","coin":["HYPE","BTC","ETH"]} | Snapshot + diffs for a fixed list of coins |
{"type":"l2BookDiff"} | Snapshot + diffs for every perp coin (default: marketTypes: ["perp"]) |
{"type":"l2BookDiff","marketTypes":["spot"]} | Snapshot + diffs for every spot coin |
{"type":"l2BookDiff","marketTypes":["outcome"]} | Snapshot + diffs for every HIP-4 outcome market |
{"type":"l2BookDiff","marketTypes":["perp","spot"]} | Snapshot + diffs for perps + spot |
{"type":"l2BookDiff","marketTypes":["*"]} | Snapshot + diffs for every coin (perp + spot + outcome, plus future types) |
wscat
TypeScript
Python
Unsubscribe
Send the samesubscription body with method: "unsubscribe":
Note: Unsubscribe matches subscriptions by exact body. A subscription created withYou cannot unsubscribe a partial set of coins from an existing multi-coin subscription. To narrow the set, unsubscribe the originalcoin: ["BTC", "ETH"]is a different subscription from one created withcoin: "BTC"orcoin: "ETH".
coin array in full, then resubscribe with the smaller list:
Streamed messages
Every message haschannel: "l2BookDiff". The data payload contains exactly one of two variants: a Snapshot (emitted once per subscribed coin, immediately after subscribe) or an Updates (emitted on each subsequent HyperCore block where the book for at least one subscribed coin changed).
Initial snapshot
After subscribe, the server emits oneSnapshot message per coin currently in scope. For a single-coin subscription that is one message; for a list or wildcard subscription that is one message per asset. Each entry in levels[0] (bids) and levels[1] (asks) is an aggregated price level, sorted best-first.
Incremental updates
Subsequent messages carry only the levels that changed since the previous block, grouped by coin. A level entry withsz: "0" and n: 0 means the level at that price has been removed; any other entry replaces the current state at that px with the new {sz, n}.
Response fields
| Field | Type | Description |
|---|---|---|
channel | string | Always "l2BookDiff". |
data | object | Contains exactly one of Snapshot or Updates. |
data.coin | string | Asset symbol the snapshot belongs to. |
data.time | int | HyperCore block timestamp in milliseconds. |
data.block_height | int | HyperCore block height the snapshot was taken at. |
data.levels | array> | Tuple [bids, asks]. Each side is an array of aggregated Level objects in best-first order. __RESPONSE_ROW__px string Price for this level (decimal string). __RESPONSE_ROW__data.sz string Aggregate size resting at this level (decimal string, base units). __RESPONSE_ROW__data.n int Number of orders aggregated into this level. HyperCore block timestamp in milliseconds. |
block_height | int | HyperCore block height. |
book_diffs | array | Per-coin lists of changed price levels. One entry per coin that had changes at this block. |
book_diffs.coin | string | Asset symbol the diff applies to. |
book_diffs.levels | array> | Tuple [changed_bids, changed_asks]. Each entry replaces the current state at its px. An entry with sz: "0" and n: 0 removes the level at that price. __RESPONSE_ROW__px string Price for this level (decimal string). __RESPONSE_ROW__book_diffs.sz string New aggregate size at this level (decimal string). "0" means the level is removed. __RESPONSE_ROW__book_diffs.n int New number of orders aggregated into this level. 0 means the level is removed. |
L2 Order Book
Credit Cost: 0.5 per coin per minute Processing: RealtimeNote: - Wire-compatible withwss://api.hyperliquid.xyz/wsl2Booksubscriptions - same channel name, samelevelsshape.
coinis optional on GoldRush. Omit it to stream the entire L2 order book across every asset on a single subscription. The public Hyperliquid API requirescoinand locks each subscription to one asset at a time.- When
coinis omitted, the optionalmarketTypesfilter selects which market families to include. It defaults to["perp"]only. - Pass
"marketTypes": ["spot"], or"marketTypes":["outcome"], or a mix (e.g."marketTypes": ["perp","spot"]), or use the wildcard"marketTypes": ["*"]to opt into spot, perps, outcome, and any future market types. - No 1000-subscription-per-IP cap - multiplex hundreds of
l2Booksubscriptions on a single connection. - For OHLCV candles instead of raw book state, use the Streaming API OHLCV streams.
coin is omitted, a credit rate of 50 credits per minute subscribed is applied.
Endpoint
Authorization header is used.
Subscribe
Send this JSON message after the connection is established:| Parameter | Type | Required | Description |
|---|---|---|---|
method | string | Yes | Always "subscribe". |
subscription | object | Yes | __RESPONSE_ROW__type string Always "l2Book". __RESPONSE_ROW__coin string Asset symbol - e.g. "BTC", "ETH", "@107" for spot pairs. For HIP-3 markets, include the deployer prefix. Omit to receive snapshots for all perp assets (the default; see marketTypes to include spot or outcome markets). __RESPONSE_ROW__marketTypes string[] Optional. Selects which market families a wildcard subscription includes. Only valid when coin is omitted. Defaults to ["perp"] — when omitted, only perp markets stream. Spot and outcome markets require explicit opt-in. Accepted values: - "perp" (default) — vanilla perps and HIP-3 deployer-perps (e.g. BTC, ETH, HYPE, SOL, cash, abcd, USA500). - "spot" — @ spot markets and legacy spot pairs (e.g. @1, @107 for HYPE spot, PURR/USDC). Not included by default. - "outcome" — HIP-4 prediction-market outcomes (e.g. #700, #710, #741). Not included by default. - "*" — every current type ("perp" + "spot" + "outcome") and auto-opt-in to any future types the server adds. Mix and match in one subscription, e.g. ["perp", "outcome"]. A second subscribe with a different marketTypes value replaces the previous filter rather than coexisting with it. __RESPONSE_ROW__nSigFigs int Significant figures used for price aggregation. One of 2, 3, 4, 5, or null for full precision. Defaults to null. __RESPONSE_ROW__mantissa int When nSigFigs is 5, controls the mantissa rounding. One of 1, 2, or 5. Not allowed for other nSigFigs values. |
Example
Pick the subscription shape that matches the coverage you want:| Subscribe with | What you receive |
|---|---|
{"type":"l2Book","coin":"BTC"} | L2 snapshots for BTC only |
{"type":"l2Book"} | L2 snapshots for every perp coin (default: marketTypes: ["perp"]) |
{"type":"l2Book","marketTypes":["spot"]} | L2 snapshots for every spot coin |
{"type":"l2Book","marketTypes":["outcome"]} | L2 snapshots for every HIP-4 outcome market |
{"type":"l2Book","marketTypes":["perp","spot"]} | L2 snapshots for perps + spot |
{"type":"l2Book","marketTypes":["*"]} | L2 snapshots for every coin (perp + spot + outcome, plus future types) |
wscat
TypeScript
Python
Unsubscribe
Send the samesubscription body with method: "unsubscribe":
Note: Unsubscribe matches subscriptions by exact body. A subscription created withYou cannot unsubscribe a partial set of coins from an existing multi-coin subscription. To narrow the set, unsubscribe the originalcoin: ["BTC", "ETH"]is a different subscription from one created withcoin: "BTC"orcoin: "ETH".
coin array in full, then resubscribe with the smaller list:
Streamed message
Each message haschannel: "l2Book" and a data payload with the current book snapshot for the subscribed coin.
| Field | Type | Description |
|---|---|---|
channel | string | Always "l2Book". |
data | object | |
data.coin | string | Asset symbol the snapshot belongs to. |
data.time | int | HyperCore block timestamp in milliseconds. |
data.block_height | int | HyperCore block height the snapshot was taken at. |
data.levels | array> | Tuple [bids, asks]. Each side is an array of price levels in best-first order. __RESPONSE_ROW__px string Price for this level (decimal string). __RESPONSE_ROW__data.sz string Aggregate size resting at this level (decimal string, base units). __RESPONSE_ROW__data.n int Number of orders aggregated into this level. |
L4 Order Book Diff
Credit Cost: 3 per coin per minute (except BTC which is 60 per minute) Processing: RealtimeNote: - GoldRush-native.l4Bookis not exposed onwss://api.hyperliquid.xyz/ws. Pointing a client at the public endpoint with this subscription type will fail.
- Perps only. No spot assets.
coinis required. Unlikel2Bookandl2BookDiff, you cannot omitcointo stream every asset. Open one subscription per asset.- Snapshot, then diffs. The first message is always a
Snapshot; every message thereafter is anUpdates. Clients must seed local book state from the snapshot and apply diffs from there. On reconnect, drop local state and re-seed from the next snapshot. - Per-order detail. Each entry exposes
user,oid,cloid,tif, and trigger metadata - enabling queue-position reconstruction, per-trader flow attribution, and microstructure analytics that are not possible withl2Book. - See the L4 Order Book recipe for patterns to maintain book state, attribute flow by
user, or reconstruct aggregated price levels.
"coin":"BTC" is used, a credit rate of 60 credits per minute subscribed is applied.
Endpoint
Authorization header is used.
Subscribe
Send this JSON message after the connection is established:| Parameter | Type | Required | Description |
|---|---|---|---|
method | string | Yes | Always "subscribe". |
subscription | object | Yes | __RESPONSE_ROW__type string Always "l4Book". __RESPONSE_ROW__coin string Asset symbol - e.g. "BTC", "ETH", "@107" for spot pairs. For HIP-3 markets, include the deployer prefix. Required - unlike l2Book, l4Book does not support wildcard subscriptions; each subscription is locked to a single asset. |
Example
wscat
TypeScript
Python
Unsubscribe
Send the samesubscription body with method: "unsubscribe":
Streamed messages
Every message haschannel: "l4Book". The data payload contains exactly one of two variants: a Snapshot (emitted once, immediately after subscribe) or an Updates (emitted on each subsequent HyperCore block where the book for coin changed).
Initial snapshot
The first message after subscribe carries the full resting book at the current block. Each entry inlevels[0] (bids) and levels[1] (asks) is an individual order - not an aggregated price level.
Incremental updates
Subsequent messages carry only what changed since the previous block.order_statuses describes order lifecycle events (open, etc.); book_diffs carries the corresponding price-level changes.
Response fields
| Field | Type | Description |
|---|---|---|
channel | string | Always "l4Book". |
data | object | Contains exactly one of Snapshot or Updates. |
data.coin | string | Asset symbol the snapshot belongs to. |
data.time | int | HyperCore block timestamp in milliseconds. |
data.block_height | int | HyperCore block height the snapshot was taken at. |
data.levels | array> | Tuple [bids, asks]. Each side is an array of individual Order objects (see below), in queue order at their respective price. |
data.time | int | HyperCore block timestamp in milliseconds. |
data.block_height | int | HyperCore block height. |
data.order_statuses | array | Order lifecycle events at this block. __RESPONSE_ROW__time string ISO-8601 timestamp with nanosecond precision. __RESPONSE_ROW__data.user string Wallet address that owns the order. __RESPONSE_ROW__data.status string Lifecycle status (e.g. "open"). __RESPONSE_ROW__data.order Order The order, in the same shape as a snapshot entry. user inside this nested object is null because it duplicates the parent user. __RESPONSE_ROW__book_diffs array Per-order book changes at this block. __RESPONSE_ROW__book_diffs.user string Wallet address that owns the order. __RESPONSE_ROW__book_diffs.oid int Order id the diff applies to. __RESPONSE_ROW__book_diffs.px string Price level the diff applies to (decimal string). __RESPONSE_ROW__book_diffs.coin string Asset symbol. __RESPONSE_ROW__book_diffs.raw_book_diff object The change descriptor. Observed shape: { "new": { "sz": "" } } for a newly resting order. Other shapes may carry size deltas or cancellations - inspect the keys to discriminate. |
Order object
The Order type appears insideSnapshot.levels[*][*] and Updates.order_statuses[*].order.
| Field | Type | Description | |
|---|---|---|---|
user | `string | null` | Wallet address that owns the order. null when the order is nested inside an order_status (the parent already carries it). |
coin | string | Asset symbol. | |
side | string | "B" for bid, "A" for ask. | |
limitPx | string | Limit price (decimal string). | |
sz | string | Resting size (decimal string, base units). | |
oid | int | Hyperliquid order id - stable for the lifetime of the order. | |
timestamp | int | Order-placement timestamp in HyperCore milliseconds. | |
triggerCondition | string | Trigger condition string (e.g. "N/A" for plain limit orders). | |
isTrigger | boolean | True if this is a stop / take-profit trigger order. | |
triggerPx | string | Trigger price (decimal string, "0.0" for non-trigger orders). | |
isPositionTpsl | boolean | True if this is a position-level TP/SL. | |
reduceOnly | boolean | True if the order is flagged reduce-only. | |
orderType | string | Hyperliquid order type (e.g. "Limit"). | |
tif | string | Time-in-force (e.g. "Alo", "Gtc", "Ioc"). | |
cloid | `string | null` | Client-supplied order id (hex string), or null if none was provided. |
Recipes
Thel2Book channel on wss://hypercore.goldrushdata.com/ws?key= is wire-equal to the public Hyperliquid feed but with coin made optional and the per-IP subscription cap removed. This recipe shows how to turn that stream into common trading and analytics building blocks. For the raw subscription shape see the l2Book reference; for the connection model see the WebSocket API overview.
What you get
- Complete snapshots, not diffs. Every
l2Bookmessage contains the currenttime,coin, and a full[bids, asks]tuple in best-first order, withpx/sz/nper level. Consume each message in isolation - no sequence numbers to track, no diff replay buffer, no REST snapshot to bootstrap. - Self-healing on packet loss. Drop a message, reconnect mid-session, or restart your process - the next message arrives with the full book state, so your in-memory view is correct on the very next tick.
- Upstream-compatible aggregation knobs.
nSigFigsaccepts2,3,4,5, ornull(full precision).mantissaaccepts1,2, or5, and is only valid whennSigFigsis5. - Wildcard coverage. Omit
cointo stream every asset’s book over a single subscription, instead of fanning out one subscription per asset. The wildcard defaults to perps only (marketTypes: ["perp"]); pass["spot"],["outcome"], a mix, or["*"]to opt into spot, outcome, and future market types.
Subscribe and hold book state
The pattern below keeps aMap in memory. Each incoming message replaces the entry for its coin, so the map is always current and never needs reconciliation.
TypeScript
Python
Patterns
Top-of-book tracker
Readbids[0] and asks[0] directly from each message. The spread is Number(asks[0].px) - Number(bids[0].px). No state required - every message is self-contained, so a single-line transformation gives you a live ticker.
Depth-weighted mid quote
Sumpx * sz across the first K levels on each side, then average. This produces a fair-value mid that’s robust to thin top-of-book liquidity, and is useful as a hedging or pricing reference.
TypeScript
Slippage / impact estimator
Walk levels on the relevant side until cumulativesz covers the requested notional. Return the size-weighted average fill price - the difference vs the top-of-book is your expected slippage.
TypeScript
Liquidity heatmap
On each message, append[time, coin, side, px, sz] rows to your time-series store (Clickhouse, TimescaleDB, Parquet). Because every message is a complete snapshot of the top levels, the heatmap rebuilds correctly from any contiguous slice of history - you don’t need a separate “initial book” record to seed the visualisation.
Handling reconnects
Reconnect logic is a one-liner: open a new socket and resend the samesubscribe payload. The first message after subscribe is a full book snapshot, so your books map is correct on the next tick - there’s nothing to replay, nothing to buffer, and no sequence numbers to reconcile against a separately-fetched REST snapshot.
TypeScript
Related
l2BookAPI reference - full subscription and message schema.- WebSocket API overview - endpoint URL, auth, and limits.
clearinghouseState- pair the live book with per-account position and margin state.- OHLCV pairs stream - candles instead of raw book state.
The
l2BookDiff channel on wss://hypercore.goldrushdata.com/ws?key= is a GoldRush-exclusive stream - it has no equivalent on wss://api.hyperliquid.xyz/ws. After subscribing, the server emits one Snapshot per subscribed coin, then per-block Updates carrying only the price levels that changed. The shape per level is the same {px, sz, n} you already get from l2Book, so book-state code only needs to learn how to apply diffs - and coin accepts a single asset, a list, or can be omitted to stream every asset on one subscription. For the raw subscription shape see the l2BookDiff reference; for the connection model see the WebSocket API overview.
What you get
- Snapshot + diff transport. One full
Snapshotper subscribed coin on subscribe, then per-blockUpdatescontaining only the levels that changed. Apply diffs to local state. - Aggregated
{px, sz, n}shape. Identical tol2Booklevels - reuse your existing aggregated-book types and just add a level-apply function. - Multi-coin / wildcard friendly.
coinaccepts a single asset, an array of assets, or can be omitted to stream every asset on one subscription. Whencoinis omitted,marketTypesdefaults to["perp"]— pass["spot"],["outcome"], a mix, or["*"]to opt into spot, outcome, and future market types.l4Bookis one-coin-per-subscription;l2Bookrequires per-asset fan-out on the public feed. - Bandwidth proportional to change. Quiet markets cost almost nothing; only the levels that actually moved arrive over the wire, instead of a full re-snapshot every tick.
- GoldRush-exclusive. Public Hyperliquid has no L2-diff transport -
l2Bookis full-snapshot only.
Subscribe and maintain book state
The pattern below keeps aMap, asks: Map }>. Each Snapshot seeds the per-coin entry; each book_diff inside Updates either deletes a level (when sz === "0") or replaces it with the new {sz, n}.
TypeScript
Python
Patterns
Single coin, list, or wildcard
All three subscription shapes share the same handler - only the payload sent atsubscribe time changes. Use whichever matches your coverage requirements.
TypeScript
Snapshot per live coin before diffs begin, so the books map fills in over the first few messages rather than all at once. marketTypes is only valid when coin is omitted; it defaults to ["perp"], so spot and outcome markets require explicit opt-in. A second subscribe with a different marketTypes value replaces the previous filter rather than coexisting with it.
Reconstruct a top-of-book stream
After each diff is applied, the best bid is the highestpx in book.bids and the best ask is the lowest px in book.asks. Emit only when the top level changes to avoid noise.
TypeScript
Related
l2BookDiffAPI reference - full subscription, snapshot, and update schema.l2Bookreference - full-snapshot transport when diff replay isn’t desirable.l4Bookreference - order-level stream withuser,oid,cloid,tif, and trigger metadata.- WebSocket API overview - endpoint URL, auth, and limits.
The
l4Book channel on wss://hypercore.goldrushdata.com/ws?key= is a GoldRush-exclusive stream - it has no equivalent on wss://api.hyperliquid.xyz/ws. After subscribing, the server sends a single Snapshot of every resting order, then per-block Updates carrying lifecycle events and per-order book changes. Each order arrives with its user, oid, cloid, tif, and trigger metadata, so you can reconstruct queue position, attribute flow to specific wallets, and run microstructure analytics that l2Book’s aggregated {px, sz, n} view hides. For the raw subscription shape see the l4Book reference; for the connection model see the WebSocket API overview.
What you get
- Per-order visibility. Every level in the snapshot is an individual order keyed by
oid, withuser,cloid,tif,orderType, and trigger metadata attached.l2Bookonly exposes{px, sz, n}per price level. - Snapshot + diff transport. One full
Snapshoton subscribe, then per-blockUpdatescontainingorder_statuses(lifecycle events) andbook_diffs(per-order changes). Apply diffs to local state. - Per-block cadence. Updates fire on each HyperCore block where the book for the subscribed
coinchanged. Thetimeandblock_heightfields anchor each message to a specific block. - GoldRush-exclusive. Not available on the public Hyperliquid WebSocket - this stream surfaces user attribution and per-order metadata the public feed never exposes.
- One coin per subscription. Unlike
l2Book,coinis required. To cover multiple assets, open onel4Booksubscription per asset on the same connection.
Subscribe and maintain book state
The pattern below keeps aMap per coin. The snapshot seeds the map; each Updates message applies book_diffs against it. Reconnects drop the map and re-seed from the next snapshot.
TypeScript
Python
Patterns
Track individual orders by oid
oid is the Hyperliquid order id, stable for the lifetime of the order - use it as the primary key in your local map. cloid is the client-supplied id (may be null); index on it when you need to correlate fills back to a specific trading bot’s instructions.
Per-user flow attribution
Every order entry carriesuser. Group orders by wallet to surface market-maker behavior, identify spoofing patterns, or build a per-trader heatmap of resting size. Pair this with clearinghouseState for per-user position and margin context.
TypeScript
Reconstruct aggregated price levels
If a downstream consumer expects anl2Book-style aggregated view, sum sz across all orders sharing a limitPx on the same side. Going the other way isn’t possible - l2Book collapses the per-order detail you’d lose.
TypeScript
Handling reconnects
On reconnect, resend the samesubscribe payload. The first message back is always a fresh Snapshot - drop your local orders map and re-seed from it. Do not attempt to replay missed Updates - the snapshot is authoritative and supersedes anything you held before the disconnect.
TypeScript
Related
l4BookAPI reference - full subscription, snapshot, and update schema.l2Bookreference - aggregated price-level snapshots when per-order detail isn’t needed.- WebSocket API overview - endpoint URL, auth, and limits.
clearinghouseState- pair per-user resting orders with position and margin state.