Skip to main content
Every channel, live or replayed, uses wss://api.0xarchive.io/ws, except the live mempool channel, which is served only on wss://stream.0xarchive.io/ws with the same key and protocol. If one snapshot or a bounded window answers the question, the REST API is simpler to retry.

Before you connect

  • An API key, sent in the opening handshake as Authorization: Bearer $OXARCHIVE_API_KEY. The Free plan works, and replays the most recent 30 days.
  • A server-side runtime. Browsers cannot set the Authorization header, so a browser app connects through your backend. Keep the key out of browser code, logs, and shared notebooks.
  • For the example below, Node.js 18 or later and the ws package: npm install ws.

Subscribe to one channel

Save this as subscribe.mjs and run node subscribe.mjs:
The server first confirms the subscription:
Then each update arrives as a data message. levels holds bids, then asks, up to 20 per side (one each shown here):
An open socket only means the key was accepted; a wrong key fails the handshake with HTTP 401. Wait for subscribed after subscribe, or replay_started after replay, and handle error: an unknown channel, for example, returns an error message with error_code invalid_parameter.

Stream live or replay history

The same socket does both. Each command names its channel and symbol.

Live streaming

The example above is a live subscription; unsubscribe takes the same channel and symbol. Channels lists every channel with its live and replay availability and what each message does to your local state, Real-time streams covers ordering and local books, and L4 order book covers stateful L4 books built from a snapshot and diffs. For Hyperliquid channels and depth choices, see Hyperliquid WebSocket streaming.

Historical replay

Send a replay command with a window in Unix milliseconds. Save this as replay.mjs and run node replay.mjs. It replays five minutes of BTC trades from an hour ago, inside the Free plan’s 30 days, and takes about 30 seconds at speed 10:
It prints the speed the replay runs at, the first fill, and the number of fill rows when the window ends. Two kinds of error reach the client. A failed connection, such as a rejected key, fires the socket’s own error event with the HTTP status of the handshake. A refused command arrives as a message with type error and a stable error_code, and the socket stays open. Standard replay sends replay_started, then historical_data messages in order, gap_detected where the window has an interruption, and replay_completed. A multi-channel replay sends replay_snapshot baselines before its timeline. L4 and full-depth replay sends replay_started, one l4_snapshot, ordered l4_batch messages, and replay_completed; it ignores speed, and replay.seek returns an error. Replay covers each delivery model and the pause, resume, seek, and stop controls. To prepare a backtest from REST windows or replay, see Prepare data for a reproducible backtest.

Commands and events

Client commands use op: subscribe, unsubscribe, replay, replay.pause, replay.resume, replay.seek, replay.stop, and ping. Server messages use type, and the names differ: the command replay.pause is answered by the event replay_paused. The older stream and stream.stop commands return an error; use Bulk Exports for large files. The Protocol reference has every command and event shape.

Channels and limits

Which channels stream live, which replay, and how, is on Channels, venue family by venue family. Subscription, connection, and replay-speed limits per plan are on Limits.

Measure your own latency

Current WebSocket health is an HTTP service check, not a measurement of your connection. These are separate numbers: HTTP service health, server-side REST handler timing, stored-data freshness, ingest lag, WebSocket upgrade/connect time, application ping/pong round-trip time, and client processing lag. In the data-quality response, websocket.current_ms is the latest stored order-book freshness value, not client WebSocket round-trip time. To measure your own path, send {"op":"ping"} and time the {"type":"pong"} reply. The result describes your client and network.

Next step

Connect a production client

Authenticate, keep the socket alive, and reconnect and resubscribe cleanly.
Last modified on October 8, 2026