Skip to main content

L2 Book Diff Dataset

Updated on
Jun 10, 2026

Overview

The StreamL2BookDiff stream delivers incremental L2 price-level changes for one or more coins instead of full snapshots. Each message contains only the levels that changed since the previous block, allowing clients to maintain a local L2 order book efficiently with far less bandwidth than full snapshots.

gRPC Service: OrderBookStreaming
gRPC Method: StreamL2BookDiff
Update Model: Initial per-coin snapshot (optional), then incremental diffs per block with sequence numbers

How It Works

  1. On subscribe: Unless skip_initial_snapshot is set, the first update for each coin contains the current price levels as a snapshot (snapshot: true on the message and the per-coin diff)
  2. Per block thereafter: Each L2BookDiffUpdate contains only the price levels that changed. A level with sz: "0" means the level was removed
  3. Apply diffs to your local copy of the book, using seq/prev_seq to verify continuity: each coin's diff carries a sequence number, and prev_seq should match the seq of the previous diff you applied for that coin

A single stream can cover multiple coins (or all coins with an empty coins list). The maximum tracked depth per side defaults to 20 levels, matching StreamL2Book, and the same price-bucketing parameters (n_sig_figs, mantissa) are supported.

Data Structure

Initial snapshot (first message per coin)

{
"time": 1781109048255,
"height": 586404776,
"snapshot": true,
"diffs": [
{
"coin": "BTC",
"seq": 1,
"snapshot": true,
"bids": [
{ "px": "62963", "sz": "0.00072", "n": 2 },
{ "px": "62959", "sz": "0.001", "n": 1 }
],
"asks": [
{ "px": "63054", "sz": "0.00008", "n": 1 },
{ "px": "63082", "sz": "0.00035", "n": 1 }
]
}
]
}

Diff (subsequent messages)

{
"time": 1781109048660,
"height": 586404778,
"diffs": [
{
"coin": "BTC",
"seq": 2,
"prev_seq": 1,
"asks": [
{ "px": "63168", "sz": "0.00001", "n": 1 },
{ "px": "63210", "sz": "0" }
]
}
]
}

A level with sz: "0" has been removed from the book; any other level value replaces the previous state at that price.

Request Parameters

FieldTypeRequiredDescription
coinsrepeated stringNoList of symbols to subscribe to (e.g., "BTC", "ETH"). Empty means all coins
n_levelsuint32YesMaximum number of price levels tracked per side (default 20, max 100)
n_sig_figsuint32NoSignificant figures for price bucketing (2–5). Omit for exact price-level aggregation.
mantissauint64NoMantissa for price bucketing (1, 2, or 5). Used with n_sig_figs to control bucket width.
skip_initial_snapshotboolNoIf false (default), the first update per coin contains the current levels as a snapshot

Coin Naming

The coins parameter follows Hyperliquid's naming convention, which unambiguously distinguishes perpetuals from spot:

  • Perpetuals: Human-readable names, such as "BTC", "ETH", "HYPE", "SOL"
  • Spot tokens: @{index} format, such as "@1", "@107", "@142", "@166"
  • Outcome markets (HIP-4): #N format. Each outcome has two #N coins, one per side (Yes and No). Multi-price question markets consist of multiple grouped outcomes (price buckets plus a fallback), each with its own Yes/No coin pair. Use the outcomeMeta endpoint to map coin indices to market names and sides.
  • Exception: "PURR/USDC" is the only spot coin with a readable name

There is no overlap between formats. "BTC" always refers to the BTC perpetual; spot BTC is "@142". To discover @index mappings for spot tokens, query the meta or spotMeta info endpoints.

Response Fields

L2BookDiffUpdate

FieldTypeDescription
timeuint64Block timestamp in milliseconds
heightuint64Block height
snapshotboolTrue when this update carries the initial levels as a snapshot for any coin
diffsL2CoinDiff[]Per-coin diffs of changed price levels

L2CoinDiff

FieldTypeDescription
coinstringSymbol (e.g., "BTC", "ETH")
sequint64Per-coin sequence number of this diff
prev_sequint64Sequence number of the previous diff for this coin. Compare against the last applied seq to detect gaps
bidsL2Level[]Changed bid levels. A level with sz "0" was removed
asksL2Level[]Changed ask levels. A level with sz "0" was removed
snapshotboolTrue when this diff carries the initial levels for the coin as a snapshot

L2Level

FieldTypeDescription
pxstringPrice as a decimal string
szstringTotal size across all orders at this price level, as a decimal string. "0" means the level was removed
nuint32Number of individual orders at this price level (0/omitted on removed levels)

Proto Definition

StreamL2BookDiff is defined in orderbook.proto:

service OrderBookStreaming {
rpc StreamL2BookDiff (L2BookDiffRequest) returns (stream L2BookDiffUpdate);
}

message L2BookDiffRequest {
repeated string coins = 1;
uint32 n_levels = 2;
optional uint32 n_sig_figs = 3;
optional uint64 mantissa = 4;
bool skip_initial_snapshot = 5;
}

message L2BookDiffUpdate {
uint64 time = 1;
uint64 height = 2;
bool snapshot = 3;
repeated L2CoinDiff diffs = 4;
}

message L2CoinDiff {
string coin = 1;
uint64 seq = 2;
uint64 prev_seq = 3;
repeated L2Level bids = 4;
repeated L2Level asks = 5;
bool snapshot = 6;
}

message L2Level {
string px = 1;
string sz = 2;
uint32 n = 3;
}

Example Updates

Initial Snapshot (first message)
{
"time": 1781109048255,
"height": 586404776,
"snapshot": true,
"diffs": [
{
"coin": "BTC",
"seq": 1,
"snapshot": true,
"bids": [
{ "px": "62963", "sz": "0.00072", "n": 2 },
{ "px": "62959", "sz": "0.001", "n": 1 },
{ "px": "62955", "sz": "0.00015", "n": 1 },
{ "px": "62922", "sz": "0.00074", "n": 1 },
{ "px": "62892", "sz": "0.00035", "n": 1 }
],
"asks": [
{ "px": "63054", "sz": "0.00008", "n": 1 },
{ "px": "63082", "sz": "0.00035", "n": 1 },
{ "px": "63146", "sz": "0.00035", "n": 1 },
{ "px": "63187", "sz": "0.00074", "n": 1 },
{ "px": "63210", "sz": "0.00035", "n": 1 }
]
}
]
}
Incremental Diff (level added and level removed)

A level with sz: "0" means the level was removed:

{
"time": 1781109048660,
"height": 586404778,
"diffs": [
{
"coin": "BTC",
"seq": 2,
"prev_seq": 1,
"asks": [
{ "px": "63168", "sz": "0.00001", "n": 1 },
{ "px": "63210", "sz": "0" }
]
}
]
}
Level Size Change Only
{
"time": 1781109050268,
"height": 586404788,
"diffs": [
{ "coin": "BTC", "seq": 3, "prev_seq": 2,
"bids": [ { "px": "62963", "sz": "0.00052", "n": 2 } ] }
]
}

When skip_initial_snapshot is true, the first message is a plain diff (no snapshot flags) with seq starting at 1.

API Usage

gRPC Streaming
// Single coin
const request = {
coins: ['BTC'],
n_levels: 20
};

// Multiple coins with price bucketing
const bucketedRequest = {
coins: ['BTC', 'ETH'],
n_levels: 20,
n_sig_figs: 3,
mantissa: 1
};

// Diffs only, no initial snapshot
const diffOnlyRequest = {
coins: ['BTC'],
n_levels: 20,
skip_initial_snapshot: true
};

gRPC Only

StreamL2BookDiff is only available via the gRPC Streaming API (OrderBookStreaming service). It is not available through JSON-RPC or WebSocket.

Comparison with StreamL2Book

FeatureStreamL2BookDiffStreamL2Book
Data per messageOnly changed price levelsFull snapshot every block
Includes current book stateYes (initial per-coin snapshot)Yes (every message)
Client-side state managementApply diffs to local book, track seqNone
Gap detectionseq / prev_seq per coinNot needed
Coins per streamMultiple (or all coins)One coin per stream
BandwidthLow (diffs only)Medium (capped by n_levels)
Price bucketingSupported (n_sig_figs, mantissa)Supported (n_sig_figs, mantissa)
Best forEfficient local book maintenance at scaleSimplest depth consumption

Important Notes


  • sz: "0" means removed: A changed level with size "0" (and n 0/omitted) has been removed from the book. Delete it from your local state
  • Track sequence numbers: Verify prev_seq matches the last seq you applied per coin; on a gap, resubscribe to receive a fresh snapshot
  • Default depth matches StreamL2Book: n_levels defaults to 20 tracked levels per side (max 100)
  • Multi-coin in one stream: A single subscription can cover multiple coins (or all coins). Demultiplex by the coin field on each diff
  • zstd compression recommended: Enable zstd compression on your gRPC channel to reduce bandwidth, especially when streaming multiple coins

  • StreamL2Book - Aggregated price-level depth, full snapshot every block
  • StreamBboBook - Top-of-book best bid/ask, emitted only when the BBO changes
  • Book Updates - Forward-only incremental diffs via StreamData
Share this doc