⚠️Blast API (blastapi.io) ends Oct 31. Migrate to Dwellir and skip Alchemy's expensive compute units.
Switch Today →
Skip to main content

Order Book WebSocket API

Overview

Dwellir provides a high-performance WebSocket server delivering real-time order book data from Hyperliquid with ultra-low latency. This service offers Level 2 (L2), Level 4 (L4), and trades streaming directly from Hyperliquid nodes, significantly faster than public API endpoints.

Key Features

  • Ultra-low latency - Direct node connectivity eliminates public API overhead
  • Full order book depth - Access to L4 data with individual order visibility
  • Real-time streaming - WebSocket push model for immediate updates
  • Efficient compression - Optimized bandwidth usage for high-frequency data
  • Institutional grade - Professional infrastructure with monitoring and support

Hosted Service by Dwellir

For production use cases requiring minimum latency, Dwellir offers hosted WebSocket servers with:

  • Direct Hyperliquid node connectivity for fastest possible data access
  • Geographic distribution for optimal routing
  • Professional infrastructure and 24/7 monitoring
  • Significantly faster than public API endpoints (~10-50ms improvement)

📧 Contact: ben@dwellir.com for access to hosted instances

Quick Start

import json
import asyncio
import websockets

async def connect_orderbook():
# Contact ben@dwellir.com for server details
uri = "wss://your-instance.dwellir.com/ws"

async with websockets.connect(uri) as websocket:
# Subscribe to BTC L2 book
await websocket.send(json.dumps({
"method": "subscribe",
"subscription": {
"type": "l2Book",
"coin": "BTC",
"nLevels": 25
}
}))

# Process real-time updates
async for message in websocket:
data = json.loads(message)
if data["channel"] == "l2Book":
print(f"BTC spread: {calculate_spread(data['data'])}")

asyncio.run(connect_orderbook())

API Documentation

WebSocket Endpoint

wss://<your-instance>.dwellir.com/ws

The server exposes a single WebSocket endpoint for all data streaming. Clients send JSON messages to manage subscriptions and receive real-time market data updates.

Connection Management

  1. Connect to the WebSocket endpoint
  2. Subscribe to desired data streams
  3. Receive real-time updates
  4. Handle reconnections gracefully

Message Protocol

Client → Server Messages

Subscribe to Data Stream

{
"method": "subscribe",
"subscription": {
// Subscription configuration (see types below)
}
}

Unsubscribe from Data Stream

{
"method": "unsubscribe",
"subscription": {
// Same subscription object used to subscribe
}
}

Server → Client Messages

Subscription Confirmation

{
"channel": "subscriptionResponse",
"data": {
"method": "subscribe",
"subscription": {
// Echoed subscription details
}
}
}

Error Messages

{
"channel": "error",
"data": "Descriptive error message"
}

Common errors:

  • "Invalid subscription: coin not found" - Unsupported trading pair
  • "Invalid subscription: n_levels too high" - Exceeds 100 level limit
  • "Already subscribed" - Duplicate subscription attempt
  • "Order book not ready" - Server still initializing

Subscription Types

1. Trades Stream

Real-time trade executions for a specific coin.

Subscribe

{
"type": "trades",
"coin": "BTC"
}

Response Stream

{
"channel": "trades",
"data": [
{
"coin": "BTC",
"side": "A", // "A" = Ask (sell), "B" = Bid (buy)
"px": "106296.0", // Execution price
"sz": "0.00017", // Trade size
"time": 1751430933565, // Unix timestamp (ms)
"hash": "0xde93a8a0...", // Transaction hash
"tid": 293353986402527, // Trade ID
"users": [
"0xcc0a3b6e...", // Buyer address
"0xc64cc00b..." // Seller address
]
}
]
}

2. L2 Order Book

Level 2 order book with price level aggregation.

Subscribe

{
"type": "l2Book",
"coin": "BTC",
"nSigFigs": 3, // Optional: 2-5, price aggregation
"nLevels": 50, // Optional: 1-100, default 20
"mantissa": 5 // Optional: 2 or 5, requires nSigFigs=5
}

Response Stream

{
"channel": "l2Book",
"data": {
"coin": "BTC",
"time": 1751427259657,
"levels": [
[ // Bid levels [price, size, order count]
{"px": "106217.0", "sz": "0.001", "n": 1},
{"px": "106215.0", "sz": "0.001", "n": 1},
{"px": "106213.0", "sz": "0.27739", "n": 1}
],
[ // Ask levels
{"px": "106233.0", "sz": "0.26739", "n": 3},
{"px": "106258.0", "sz": "0.001", "n": 1},
{"px": "106270.0", "sz": "0.49128", "n": 2}
]
]
}
}

3. L4 Order Book

Level 4 order book with individual order visibility - the most detailed market microstructure data available.

Subscribe

{
"type": "l4Book",
"coin": "BTC"
}

Initial Snapshot

{
"channel": "l4Book",
"data": {
"coin": "BTC",
"time": 1751427259657,
"height": 123456,
"levels": [
[ // Bid orders (individual)
{
"user": "0xcc0a3b6e...",
"coin": "BTC",
"side": "B",
"limitPx": "106200.0",
"sz": "0.5",
"oid": 12345678,
"timestamp": 1751427259657,
"triggerCondition": "",
"isTrigger": false,
"triggerPx": "",
"isPositionTpsl": false,
"reduceOnly": false,
"orderType": "limit",
"tif": "GTC",
"cloid": null
}
],
[ // Ask orders (individual)
// Individual ask order objects
]
]
}
}

Incremental Updates

{
"channel": "l4Book",
"data": {
"time": 1751427259657,
"height": 123457,
"orderStatuses": [
// Order status changes (fills, cancellations)
],
"bookDiffs": [
// Order book modifications (new, update, remove)
]
}
}

Implementation Examples

Python: Market Making Bot

import json
import asyncio
import websockets
from decimal import Decimal

class MarketMaker:
def __init__(self, uri, coin):
self.uri = uri
self.coin = coin
self.best_bid = None
self.best_ask = None

async def start(self):
async with websockets.connect(self.uri) as ws:
# Subscribe to L2 book
await ws.send(json.dumps({
"method": "subscribe",
"subscription": {
"type": "l2Book",
"coin": self.coin,
"nLevels": 10
}
}))

async for message in ws:
await self.handle_message(json.loads(message))

async def handle_message(self, msg):
if msg["channel"] == "l2Book":
data = msg["data"]
bids = data["levels"][0]
asks = data["levels"][1]

if bids and asks:
self.best_bid = Decimal(bids[0]["px"])
self.best_ask = Decimal(asks[0]["px"])
spread = self.best_ask - self.best_bid

# Market making logic
if spread > Decimal("2"):
await self.place_orders()

async def place_orders(self):
# Implement order placement logic
print(f"Placing orders: Bid {self.best_bid + 1}, Ask {self.best_ask - 1}")

# Run market maker
maker = MarketMaker("wss://your-instance.dwellir.com/ws", "ETH")
asyncio.run(maker.start())

JavaScript: Trade Analytics

const WebSocket = require('ws');

class TradeAnalytics {
constructor(uri, coins) {
this.uri = uri;
this.coins = coins;
this.volumeTracker = {};
this.vwapTracker = {};
}

connect() {
this.ws = new WebSocket(this.uri);

this.ws.on('open', () => {
// Subscribe to trades for multiple coins
this.coins.forEach(coin => {
this.ws.send(JSON.stringify({
method: 'subscribe',
subscription: { type: 'trades', coin }
}));

this.volumeTracker[coin] = 0;
this.vwapTracker[coin] = { volume: 0, value: 0 };
});
});

this.ws.on('message', (data) => {
const msg = JSON.parse(data);
if (msg.channel === 'trades') {
this.processTrades(msg.data);
}
});
}

processTrades(trades) {
trades.forEach(trade => {
const coin = trade.coin;
const size = parseFloat(trade.sz);
const price = parseFloat(trade.px);

// Update volume
this.volumeTracker[coin] += size;

// Update VWAP
this.vwapTracker[coin].volume += size;
this.vwapTracker[coin].value += size * price;

const vwap = this.vwapTracker[coin].value / this.vwapTracker[coin].volume;

console.log(`${coin} - Volume: ${this.volumeTracker[coin].toFixed(4)}, VWAP: ${vwap.toFixed(2)}`);
});
}
}

// Initialize analytics
const analytics = new TradeAnalytics(
'wss://your-instance.dwellir.com/ws',
['BTC', 'ETH', 'SOL']
);
analytics.connect();

TypeScript: Order Book Imbalance

interface L2Level {
px: string;
sz: string;
n: number;
}

interface OrderBookData {
coin: string;
time: number;
levels: [L2Level[], L2Level[]]; // [bids, asks]
}

class OrderBookImbalance {
private ws: WebSocket;
private imbalanceThreshold = 0.7;

constructor(private uri: string) {}

async connect(): Promise<void> {
this.ws = new WebSocket(this.uri);

this.ws.onopen = () => {
this.subscribe('BTC', 50);
};

this.ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.channel === 'l2Book') {
this.calculateImbalance(msg.data);
}
};
}

private subscribe(coin: string, levels: number): void {
this.ws.send(JSON.stringify({
method: 'subscribe',
subscription: {
type: 'l2Book',
coin,
nLevels: levels
}
}));
}

private calculateImbalance(data: OrderBookData): void {
const bidVolume = this.sumVolume(data.levels[0]);
const askVolume = this.sumVolume(data.levels[1]);
const totalVolume = bidVolume + askVolume;

if (totalVolume > 0) {
const imbalance = bidVolume / totalVolume;

if (imbalance > this.imbalanceThreshold) {
console.log(`BUY PRESSURE: ${(imbalance * 100).toFixed(2)}% bid volume`);
} else if (imbalance < (1 - this.imbalanceThreshold)) {
console.log(`SELL PRESSURE: ${((1 - imbalance) * 100).toFixed(2)}% ask volume`);
}
}
}

private sumVolume(levels: L2Level[]): number {
return levels.reduce((sum, level) => sum + parseFloat(level.sz), 0);
}
}

Performance & Technical Specifications

Latency Characteristics

Based on real-world benchmarking of 2,662 matched trades:

MetricPublic APIDwellir WebSocketImprovement
Mean Latency367.60ms338.88ms28.72ms faster (8.5%)
Median Latency263.00ms212.00ms51.00ms faster (24.1%)
Min Latency90.00ms77.00ms13.00ms faster (16.9%)
Max Latency9,118.00ms1,977.00ms7,141.00ms faster (361.2%)

Performance Victory Rate

In head-to-head comparison:

  • WebSocket has lower latency: 75.5% (2,010 out of 2,662 trades)

The WebSocket server delivers data faster in 3 out of 4 cases, with significantly more consistent performance and protection against extreme latency spikes.

Throughput Capabilities

  • Message Rate: Handles thousands of updates per second
  • Concurrent Subscriptions: Multiple coins and data types per connection
  • Compression: Levels 0-9 configurable for bandwidth optimization
  • Connection Limit: Contact for dedicated capacity requirements

Data Guarantees

  • Ordering: Updates delivered in blockchain order
  • Consistency: Block-level atomicity for state changes
  • Reliability: Automatic reconnection with state recovery
  • Completeness: No dropped messages under normal conditions

Use Cases

High-Frequency Trading

  • Direct L4 book access for optimal order placement
  • Minimal latency for arbitrage opportunities
  • Full market depth visibility for advanced strategies

Market Making

  • Real-time spread monitoring and adjustment
  • Order book imbalance detection
  • Individual order tracking via L4 data
  • Inventory management with position tracking

Analytics & Research

  • Complete trade history streaming
  • Order flow analysis and toxicity detection
  • Market microstructure studies
  • Volume and liquidity profiling

Risk Management

  • Real-time position monitoring
  • Liquidity assessment for large orders
  • Market impact modeling
  • Volatility tracking and alerts

Best Practices

Connection Management

import asyncio
import websockets
import logging

class ResilientWebSocket:
def __init__(self, uri):
self.uri = uri
self.reconnect_delay = 5

async def connect_with_retry(self):
while True:
try:
async with websockets.connect(self.uri) as ws:
logging.info("Connected to WebSocket")
await self.handle_connection(ws)
except Exception as e:
logging.error(f"Connection error: {e}")
await asyncio.sleep(self.reconnect_delay)

async def handle_connection(self, ws):
# Your message handling logic here
pass

Rate Limiting & Throttling

  • Batch subscription requests when connecting
  • Implement exponential backoff for reconnections
  • Monitor message queue depth to detect backpressure

Data Processing

  • Use separate threads/processes for heavy computations
  • Implement ring buffers for high-frequency updates
  • Consider using binary protocols for internal distribution

Get Started with Dwellir

Hosted WebSocket Service

Dwellir offers production-ready WebSocket servers with:

Direct node connectivity - Fastest possible data access
Geographic distribution - Servers in key trading locations
99.99% uptime SLA - Enterprise reliability
Dedicated support - Direct access to engineering team
Custom configurations - Tailored to your requirements

Contact Us

Ready to integrate ultra-low latency Hyperliquid data into your trading systems?

📧 Email: ben@dwellir.com
🌐 Website: dwellir.com
📊 Dashboard: dashboard.dwellir.com

Get in touch for:

  • API credentials and server endpoints
  • Custom data requirements
  • Enterprise pricing
  • Technical integration support
  • Performance benchmarks for your use case

Open Source

For self-hosting options and implementation details, see the Hyperliquid Order Book Server repository.


Access institutional-grade Hyperliquid market data with Dwellir's ultra-low latency WebSocket infrastructure. Contact us → to get started.