Getting Started
This section shows how to connect to Hyperliquid Data Stream and start receiving data.
Quick inspection with JSON mode
By default, the connection starts in JSON mode. In this mode, the server sends text frames with order book diffs for subscribed coins.
Example: subscribe to BTC order book diffs.
# Using websocat: https://github.com/vi/websocat
echo '{"method":"subscribe","coin":"BTC"}' \
| websocat ws://<host>:<port>You should start receiving newline-delimited JSON order book diff events almost immediately.
Example response:
{"coin":"BTC","time":"...","side":"A","px":"72223.0","sz":"0","oid":123,"user":"0x..."}
{"coin":"BTC","time":"...","side":"B","px":"72182.0","sz":"0.3","oid":456,"user":"0x..."}JSON mode only delivers order book diffs.
It does not deliver:
- Block frames
- Ping frames
- Timing metrics
- Mempool transactions
For production use, use binary mode.
Production flow with binary mode
Production clients should use the following connection sequence:
- Connect to the WebSocket endpoint.
- Send
espto upgrade to binary mode. - Send
primeto enable pings, metrics, and server error events. - Subscribe to required coins or streams.
- Read frames continuously.
- On disconnect, reconnect and repeat the full sequence.
Example sequence:
{"method":"esp","version":1}
{"method":"prime"}
{"method":"subscribe","coin":"BTC"}To subscribe to the mempool stream:
{"method":"subscribe","stream":"mempool"}The mempool stream may not be enabled on every Hyperliquid Data Stream instance. If it is not available, the server returns a non-disconnecting error.
Rust client example
A complete Rust client is available in the example client implementation. It connects to the stream, upgrades to binary mode, subscribes to one coin, and prints decoded frames.
Run:
cargo run --example client -- ws://<host>:<port> BTCRequired dependencies:
[dependencies]
tokio = { version = "1", features = ["full"] }
tokio-tungstenite = "0.26"
futures-util = "0.3"Example connection sequence:
let (ws, _) = connect_async(&url).await?;
let (mut tx, mut rx) = ws.split();
// 1. Upgrade to binary protocol.
tx.send(Message::Text(
format!(r#"{{"method":"esp","version":{BINARY_VERSION}}}"#).into(),
))
.await?;
// 2. Enable prime streams: pings, metrics, and server errors.
tx.send(Message::Text(r#"{"method":"prime"}"#.into())).await?;
// 3. Subscribe to order book diffs for one coin.
tx.send(Message::Text(
format!(r#"{{"method":"subscribe","coin":"{coin}"}}"#).into(),
))
.await?;
To add the mempool stream:
tx.send(Message::Text(
r#"{"method":"subscribe","stream":"mempool"}"#.into()
))
.await?;The read loop should continuously consume incoming frames and dispatch them by tag.
What's next?
Updated 3 days ago