Hyperliquid WebSocket API real-time data streaming diagram

Why WebSocket Matters for Hyperliquid Trading

REST APIs are fine for placing occasional orders or checking your balance. But if you are running an algorithmic trading strategy — market making, scalping, arbitrage, or even just monitoring positions — you need real-time data. Every REST API call adds latency, and polling adds unnecessary load on both your system and Hyperliquid's servers.

Hyperliquid's WebSocket API provides persistent, bidirectional connections that push data to your application the moment it changes. You get order book snapshots, trade streams, position updates, and order status changes in real time — with latency measured in tens of milliseconds, not seconds.

Here is everything you need to start streaming live trading data from Hyperliquid.

WebSocket Endpoints and Authentication

Hyperliquid has two WebSocket endpoints:

  • Public WebSocket: wss://api.hyperliquid.xyz/ws — for market data, order books, and trade streams. No authentication required.
  • Private WebSocket: Same endpoint, but requires authentication for user-specific data like order updates, position changes, and fill notifications.

Authentication uses the same API key and secret from your Hyperliquid account. You sign a payload with your private key and send it as the first message after connecting. The WebSocket connection then stays authenticated until you disconnect — no need to re-authenticate for each message.

Setting Up a WebSocket Connection

Here is how to connect to Hyperliquid's public WebSocket and subscribe to order book data. The pattern is: connect, send a subscription message, and process incoming data in an event loop.

A basic connection in Python using the websockets library:

import asyncio
import websockets
import json

async def stream_orderbook():
    uri = "wss://api.hyperliquid.xyz/ws"
    async with websockets.connect(uri) as ws:
        # Subscribe to BTC-PERP order book (L2 updates)
        subscribe_msg = json.dumps(dict(
            method="subscribe",
            subscription=dict(
                type="l2Book",
                coin="BTC"
            )
        ))
        await ws.send(subscribe_msg)
        
        # Process incoming messages
        async for message in ws:
            data = json.loads(message)
            channel = data.get("channel")
            if channel == "l2Book":
                levels = data.get("data", dict()).get("levels")
                print(f"BTC Order Book: levels received")
                
asyncio.run(stream_orderbook())

This gives you real-time Level 2 order book updates for BTC perpetuals. Each update contains the current bid and ask levels with sizes, pushed to you as the order book changes — no polling required.

Available Subscription Channels

Hyperliquid's WebSocket supports these subscription types:

  • l2Book: Level 2 order book snapshots and incremental updates. Specify coin (e.g., "BTC", "ETH", "SOL"). Updates arrive whenever the order book changes — typically hundreds of times per second on active markets.
  • trades: Real-time trade stream. Every executed trade on the specified coin is pushed to you with price, size, side (buy/sell), and timestamp. Essential for volume analysis and trade signal generation.
  • ticker: 24-hour rolling statistics — last price, 24h change, high, low, volume. Updates every few seconds. Lighter weight than full order book data.
  • userFills (authenticated): Your trade fills in real time. Each message contains the order ID, fill price, fill size, fee paid, and whether you were the maker or taker.
  • userFundings (authenticated): Funding rate payments credited to or debited from your account, streamed as they occur.
  • userNonFundingLedgerUpdates (authenticated): All account changes — deposits, withdrawals, PnL realizations — in real time.
  • webData2 (authenticated): Comprehensive position and order status. Use this to maintain a local mirror of your entire account state, updated on every change.

Building a Real-Time Position Monitor

One of the most practical uses of the private WebSocket is a position monitor. Instead of polling the REST API every few seconds to check your liquidation price and unrealized PnL, you subscribe to webData2 and receive updates the moment your position changes.

The authenticated subscription pattern adds a signature step:

import asyncio
import websockets
import json
import hmac
import hashlib
import time

API_KEY = "your_api_key_here"
API_SECRET = "your_api_secret_here"

async def stream_positions():
    uri = "wss://api.hyperliquid.xyz/ws"
    async with websockets.connect(uri) as ws:
        # Authentication payload
        timestamp = int(time.time() * 1000)
        sign_payload = "websocket-auth" + str(timestamp)
        signature = hmac.new(
            API_SECRET.encode(),
            sign_payload.encode(),
            hashlib.sha256
        ).hexdigest()
        
        auth_msg = json.dumps(dict(
            method="auth",
            apiKey=API_KEY,
            signature=signature,
            timestamp=timestamp
        ))
        await ws.send(auth_msg)
        
        # Subscribe to position and order data
        sub_msg = json.dumps(dict(
            method="subscribe",
            subscription=dict(type="webData2")
        ))
        await ws.send(sub_msg)
        
        async for message in ws:
            data = json.loads(message)
            if data.get("channel") == "webData2":
                positions = data.get("data", dict()).get("assetPositions", [])
                for pos in positions:
                    coin = pos.get("position", dict()).get("coin")
                    size = float(pos.get("position", dict()).get("szi", 0))
                    pnl = float(pos.get("position", dict()).get("unrealizedPnl", 0))
                    liq_price = pos.get("position", dict()).get("liquidationPx")
                    if abs(size) > 0:
                        print(f"Position: coin=value size=value PnL=value liq=value")

asyncio.run(stream_positions())

WebSocket Best Practices for Production

  • Implement automatic reconnection. WebSocket connections can drop. Wrap your connection logic in a retry loop with exponential backoff (1s, 2s, 4s, up to 60s max). On reconnect, re-subscribe to all channels and re-authenticate.
  • Maintain a local order book. l2Book gives you incremental updates, not snapshots. On first connection, request a full snapshot via REST, then apply WebSocket deltas to keep your local book in sync.
  • Throttle downstream processing. On active markets like BTC-PERP, you can receive hundreds of l2Book updates per second. If your processing logic is slower than the update rate, use a ring buffer or sample every Nth update to avoid backlog.
  • Use separate connections for market data and orders. If your market data connection gets throttled by heavy order book traffic, you do not want your order submission connection to slow down. Use two WebSocket connections — one for data, one for authenticated operations.
  • Monitor connection health. Send a ping message every 30 seconds and expect a pong response. If no response within 10 seconds, assume the connection is dead and reconnect.

Start Algorithmic Trading on Hyperliquid

Use referral code HOLYGRAIL to get started with Hyperliquid's WebSocket API — the fastest DEX data feeds in crypto

Join Hyperliquid →

Related Reading