Replay historical 0xArchive WebSocket streams for backtesting, order-book reconstruction, incident review, and deterministic recovery.
Replay stored Hyperliquid and Lighter market data over the WebSocket, in the order it happened, for backtests, local order-book rebuilds, and incident review. A replay request reads the stored records available when the request starts, emits the requested window, and completes with replay_completed. It does not continue following newly arriving events.Standard replay paces events by speed. L4 and full-depth replay instead uses checkpoint-anchored bulk delivery and ignores speed. Check live and replay availability before you choose a channel.
This example replays the five minutes that ended one hour ago, a window every plan’s history reaches, including Free’s most recent 30 days. Replaying older history needs the full retained archive of Build or above.
const end = Date.now() - 60 * 60_000; // one hour agoconst start = end - 5 * 60_000; // five minutes earlierws.send(JSON.stringify({ op: "replay", channel: "orderbook", symbol: "BTC", start, end, speed: 10}));
start and end are Unix milliseconds. end is optional and defaults to now; replay_started reports the effective window and speed.
Send a channels list instead of channel to replay several channels for one symbol on a single timeline. A multi-channel replay begins with a replay_snapshot for each channel, then interleaves events in timestamp order.
const end = Date.now() - 60 * 60_000; // one hour agoconst start = end - 5 * 60_000; // five minutes earlierws.send(JSON.stringify({ op: "replay", channels: ["orderbook", "trades", "funding"], symbol: "BTC", start, end, speed: 10}));
Keep every channel in one venue family. Do not combine Hyperliquid core channels with Lighter, HIP-3, HIP-4, or Spot channels in one command. The two Lighter deployments are separate replay families too: rh_lighter_* channels replay together, never with lighter_* channels. L4 and full-depth replay is single-channel.
const end = Date.now() - 60 * 60_000; // one hour agoconst start = end - 5 * 60_000; // five minutes earlierws.send(JSON.stringify({ op: "replay", channels: ["rh_lighter_orderbook", "rh_lighter_funding"], symbol: "BTC", start, end, speed: 10}));
L4 replay is available on l4_diffs and l4_orders, and works the same way on the Spot, HIP-3, and HIP-4 L4 channels (spot_l4_diffs, spot_l4_orders, hip3_l4_diffs, hip3_l4_orders, hip4_l4_diffs, hip4_l4_orders) and on the full-depth orderbook_full and hip3_orderbook_full channels. Each run is single-channel.
const end = Date.now() - 5 * 60_000; // five minutes agoconst start = end - 2_000; // two seconds earlierws.send(JSON.stringify({ op: "replay", channel: "l4_orders", symbol: "BTC", start, end}));
The server anchors the run to the latest checkpoint at or before start, sends an l4_snapshot, then sends one or more l4_batch events for the window: pages of up to 5,000 order events in block order on the L4 channels, and price-level changes (side, px, sz, n, bn) in 100 ms windows of event time on the full-depth channels. Spot frames use the dashed pair symbol. For this bulk path, speed is ignored.Apply each batch in order after the snapshot to keep a local book current; a consumer that only needs one point in time can use the snapshot directly. The server collects, backfills, and anchors the data, but your client still applies the events. Bound the window and process batches off the message callback instead of using standard replay speed as backpressure.A request can be refused when no usable checkpoint exists for the symbol and window. Checkpoints start at 2026-03-11 01:03 UTC on Hyperliquid core and HIP-3 (full-depth channels included) and 2026-05-02 07:47 UTC on HIP-4. Spot checkpoints start at 2026-05-05 22:57 UTC for most pairs; PURR-USDC reaches back to 2026-03-11 01:03 UTC and HYPE-USDC starts at 2026-05-13 15:33 UTC. Treat the accepted replay events as the authority rather than assuming one L4 start date for every symbol.
All six Lighter channels support historical replay, and Lighter on Robinhood Chain replays on its own five channels: rh_lighter_orderbook, rh_lighter_trades, rh_lighter_candles, rh_lighter_open_interest, and rh_lighter_funding. On Robinhood Chain, trades and candles replay from 2026-06-26 20:10 UTC; order books, open interest, and funding from 2026-08-22 18:43 UTC.Lighter replay returns historical_data rows in the stored Lighter shape, which differs from the live data payloads. Parse the two separately, or connect with version=2026-10-01 to receive replay rows in the live shapes. Trade replay on both deployments returns finalized trades only, up to meta.finalized_through. Lighter channels has a replay example for every channel.
Pause, resume, and stop work for both standard replay and L4 replay. replay.seek is standard-only and is rejected for L4 and full-depth replay, which also never use speed for pacing.
Pause
{"op":"replay.pause"}
Resume
{"op":"replay.resume"}
Seek
{"op":"replay.seek","timestamp":TIMESTAMP}
Stop
{"op":"replay.stop"}
For replay.seek, TIMESTAMP is a Unix-millisecond time inside the replay window, such as start + 60_000.
Control commands use dotted op values, such as replay.pause. The events the server sends use underscore names, such as replay_paused.
Event
Meaning and what to do
replay_started
The window was accepted. Start the run manifest: record channel, symbol, start, end, and speed for standard timed replay. For L4 and full-depth replay, record delivery: checkpoint_anchored_bulk and checkpoint metadata instead
replay_snapshot
Initial state for a multi-channel replay. Build the baseline before processing historical_data; a single-channel standard replay starts with historical_data
historical_data
A standard replay record in timeline order. Apply it by channel and keep its timestamp
l4_snapshot
L4 or full-depth checkpoint state. Initialize the book before applying batches
l4_batch
L4 or full-depth events for part of the window. Process the array in order, off the socket callback
gap_detected
A missing or discontinuous interval. Mark the output incomplete, stop, or rebuild from a known checkpoint; for L4, also check batch block and order continuity
replay_paused
Replay paused after replay.pause. Keep state; the run clock stops
replay_resumed
Replay resumed after replay.resume. Continue from the current timestamp
replay_completed
The window ended. Close the manifest and label the output complete, partial, or rejected
replay_stopped
Replay stopped after replay.stop. Close the manifest as stopped and keep the reason
Store a manifest beside every replay output so another run can explain the result. It is your application’s record, not part of the 0xArchive wire format.
Field
Record
Surface
WebSocket replay
Venue family and symbol
The exact family and symbol sent to the server
Channels
channel for a single-channel run, or the channels list
Window
start and the requested end, or the effective end from replay_started when end was omitted
Delivery
timed for standard replay, or checkpoint_anchored_bulk for L4 and full-depth replay
Controls
speed for standard replay, plus any pause, resume, seek, or stop commands; omit speed for L4
Baseline
replay_snapshot for multi-channel replay, or the l4_snapshot checkpoint metadata
Gaps and end state
Gap events, replay_completed or replay_stopped, and whether the output is complete, partial, or rejected
Code and output
SDK package and version or client revision, and where the output was written
Start with one channel and a narrow window. Widen only after the consumer keeps messages in order, writes output without a backlog, and handles gaps. Split long jobs into windows you can resume independently, and keep a checkpoint of your output between them.Use REST history instead when you need records from a bounded window and can order them after retrieval. Use replay when the sequence itself is the requirement: maintaining a book, testing a strategy against event cadence, or reproducing a stream.