Overview
Hyperliquid streaming APIs support powerful filtering capabilities to help you receive only the data you need. Filters work across gRPC, JSON-RPC, and WebSocket protocols, allowing you to subscribe to specific events, users, trading pairs, and more.
Supported Protocols:
- gRPC Streaming API - High-performance streaming with filters
- JSON-RPC over WebSocket - Standard WebSocket filtering
- WebSocket API - Real-time filtered subscriptions
Why Use Filtering?
Without filtering, streaming from Hyperliquid can generate massive amounts of data. The exchange processes thousands of trades, orders, and events per minute across hundreds of trading pairs. Filtering is essential because it allows you to:
- Reduce bandwidth and improve performance - Receive only relevant data instead of processing everything, significantly reducing network traffic and processing overhead
- Focus on specific data - Track particular trading pairs, users, or event types instead of consuming all market data
- Build efficient applications - Create focused applications without overwhelming data streams that could impact performance
- Enable real-time decision making - Process targeted data faster for alerts, notifications, and trading decisions
Basic Filtering Concepts
Before diving into syntax, here are the key concepts:
- Streams - Different data types (trades, orders, events, etc.)
- Fields - Properties within each stream that can be filtered
- Values - Specific criteria you want to match
- Logic - How multiple filters combine (AND/OR)
Simple Example:
"I want to see only BTC trades that are buys (not sells)"
WebSocket Filter: {"coin": ["BTC"], "side": ["B"]}
gRPC Filter: {"coin": {"values": ["BTC"]}, "side": {"values": ["B"]}}
Available Streams
| Stream Name | Description | Data Format |
|---|---|---|
| trades | Filled trades/executions | Tuple: [user_address, fill_data] |
| orders | Order status updates | Object with order fields |
| book_updates | Order book changes | Object with price/size |
| twap_orders | TWAP order statuses | Flexible object |
| events | Ledger updates, deposits, withdrawals, funding | Nested object |
| writer_actions | System actions, spot sends | Object with action type |
| mempool_txs | Pending mempool transactions (gRPC only, testnet only) | Tuple: [timestamp, transaction_data] |
| blocks | Raw replica commands (gRPC only, NO FILTERING) | Full block data |
| StreamL2Book | Aggregated price levels (gRPC only - coin specified in request) | L2BookUpdate protobuf |
| StreamL4Book | Individual orders (gRPC only - coin specified in request) | L4BookUpdate protobuf |
Filter Syntax
WebSocket and gRPC APIs use similar filter logic, but with different syntax:
- WebSocket (JSON-RPC)
- gRPC
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"<field_name>": ["<value1>", "<value2>"]
},
"filterName": "optional_name"
},
"id": 1
}
Key points:
streamType: Stream name (trades, events, etc.)filters: Each field maps directly to an array of valuesfilterName: Optional name for this filter (enables OR logic, unsubscribe by name)- Multiple streams require separate subscription requests
Subscribe {
stream_type: <STREAM_TYPE_ENUM>,
filters: {
"<field_name>": FilterValues { values: ["<value1>", "<value2>"] }
}
}
Filter Logic
AND Across Fields
When multiple fields are specified, ALL must match:
// WebSocket
{"filters": {"coin": ["BTC"], "side": ["B"]}}
Returns events where coin=BTC AND side=B
OR Within Field
When multiple values are specified for one field, ANY can match:
// WebSocket
{"filters": {"coin": ["BTC", "ETH", "HYPE"]}}
Returns events where coin=BTC OR coin=ETH OR coin=HYPE
Combined Example
// WebSocket
{"filters": {"coin": ["BTC", "ETH"], "side": ["B"]}}
Returns events where (coin=BTC OR coin=ETH) AND side=B
OR Across Named Filters (Advanced)
Multiple subscriptions with different filterName values on the same stream = OR logic between them.
Request 1:
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"coin": ["BTC"],
"side": ["B"]
},
"filterName": "btc_buys"
},
"id": 1
}
Request 2:
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"coin": ["ETH"],
"side": ["A"]
},
"filterName": "eth_sells"
},
"id": 2
}
Returns (BTC AND side=B) OR (ETH AND side=A)
This is impossible with a single filter since AND applies across all fields.
Recursive Field Matching
Filters automatically search through nested JSON objects:
// This data:
{"inner": {"LedgerUpdate": {"users": ["0xABC"], "delta": {"type": "deposit"}}}}
// Matches this WebSocket filter:
{"filters": {"type": ["deposit"]}}
Special Filter Values
| Value | Meaning | Use Case |
|---|---|---|
| "*" | Field exists (any value) | Find all liquidations: {"liquidation": {"values": ["*"]}} |
| "exists" | Same as "*" | Alternative syntax: {"liquidation": {"values": ["exists"]}} |
| "null" | Field is null | Find unfilled TWAPs: {"twapId": {"values": ["null"]}} |
Existence Filter Examples
// Find all trades that are liquidations (WebSocket)
{"filters": {"liquidation": ["*"]}}
// Find all trades with a builder (WebSocket)
{"filters": {"builder": ["*"]}}
// Find trades without TWAP ID (WebSocket)
{"filters": {"twapId": ["null"]}}
Stream-Specific Fields
Trades Stream
Filter completed trades and fills by user, trading pair, side, price, and execution details.
Format: Each event is a tuple [user_address, fill_data]
| Field | Type | Description | Example Filter |
|---|---|---|---|
| user | string | Wallet address (matches tuple first element) | {"user": {"values": ["0x123..."]}} |
| coin | string | Trading pair | {"coin": {"values": ["BTC", "ETH"]}} |
| side | string | "A" (ask/sell) or "B" (bid/buy) | {"side": {"values": ["B"]}} |
| px | string | Execution price | {"px": {"values": ["50000"]}} |
| sz | string | Size executed | - |
| dir | string | Direction | {"dir": {"values": ["Open Long", "Close Short"]}} |
| crossed | boolean | Crossed the spread | {"crossed": {"values": ["true"]}} |
| fee | string | Fee amount | - |
| feeToken | string | Fee token | {"feeToken": {"values": ["USDC"]}} |
| hash | string | Transaction hash | {"hash": {"values": ["0xabc..."]}} |
| oid | number | Order ID | {"oid": {"values": ["12345"]}} |
| tid | number | Trade ID | - |
| cloid | string | Client order ID (optional) | {"cloid": {"values": ["0x..."]}} |
| twapId | number/null | TWAP ID if from TWAP | {"twapId": {"values": ["*"]}} |
| builder | string | Builder address (optional) | {"builder": {"values": ["0x999..."]}} |
| builderFee | string | Builder fee (optional) | - |
| liquidation | object | Liquidation data (optional) | {"liquidation": {"values": ["*"]}} |
| liquidation.liquidatedUser | string | Liquidated user address | {"liquidatedUser": {"values": ["0x..."]}} |
| liquidation.method | string | Liquidation method | {"method": {"values": ["market"]}} |
| liquidation.markPx | string | Mark price at liquidation | - |
Trades Filter Examples
// Get all BTC buys (WebSocket)
{"streamType": "trades", "filters": {"coin": ["BTC"], "side": ["B"]}}
// Get liquidations only (WebSocket)
{"streamType": "trades", "filters": {"liquidation": ["*"]}}
// Get trades for specific user (WebSocket)
{"streamType": "trades", "filters": {"user": ["0x727956612a8700627451204a3ae26268bd1a1525"]}}
// Get TWAP executions only (WebSocket)
{"streamType": "trades", "filters": {"twapId": ["*"]}}
Orders Stream
Monitor order status updates including placements, cancellations, and partial fills.
| Field | Type | Description | Example Filter |
|---|---|---|---|
| coin | string | Trading pair | {"coin": {"values": ["ETH"]}} |
| side | string | "A" or "B" | {"side": {"values": ["A"]}} |
| limit_px | string | Limit price | - |
| sz | string | Current size | - |
| orig_sz | string | Original size | - |
| oid | number | Order ID | {"oid": {"values": ["12345"]}} |
| timestamp | number | Order timestamp | - |
Orders Filter Examples
// Get all ETH orders (WebSocket)
{"streamType": "orders", "filters": {"coin": ["ETH"]}}
// Get sell orders only (WebSocket)
{"streamType": "orders", "filters": {"side": ["A"]}}
Book Updates Stream
Track order book changes including price level updates and size modifications for bid and ask sides.
| Field | Type | Description | Example Filter |
|---|---|---|---|
| coin | string | Trading pair | {"coin": {"values": ["BTC"]}} |
| side | string | "A" (ask) or "B" (bid) | {"side": {"values": ["B"]}} |
| px | string | Price level | - |
| sz | string | Size at level | - |
Book Updates Filter Examples
// Get BTC bid updates only (WebSocket)
{"streamType": "book_updates", "filters": {"coin": ["BTC"], "side": ["B"]}}
// Get updates for multiple coins (WebSocket)
{"streamType": "book_updates", "filters": {"coin": ["BTC", "ETH", "SOL"]}}
Events Stream
Filter ledger updates including deposits, withdrawals, transfers, vault operations, and funding events.
Note: Events have nested structure with various types.
| Field | Type | Description | Example Filter |
|---|---|---|---|
| users | array | Affected users | {"users": {"values": ["0x..."]}} |
| type | string | Event type | {"type": {"values": ["deposit", "withdraw"]}} |
| usdc | string | USDC amount | - |
| token | number | Token ID | {"token": {"values": ["124"]}} |
Common Event Types:
deposit- USDC depositwithdraw- USDC withdrawalinternalTransfer- Internal transferspotTransfer- Spot transferliquidation- Liquidation eventfunding- Funding paymentvaultDeposit/vaultWithdraw- Vault operations
Events Filter Examples
// Get deposits only (WebSocket)
{"streamType": "events", "filters": {"type": ["deposit"]}}
// Get all events for a user (WebSocket)
{"streamType": "events", "filters": {"users": ["0xabc..."]}}
// Get vault operations (WebSocket)
{"streamType": "events", "filters": {"type": ["vaultDeposit", "vaultWithdraw"]}}
Writer Actions Stream
Monitor system actions including spot token transfers, perps operations, and core system activities.
| Field | Type | Description | Example Filter |
|---|---|---|---|
| user | string | User address | {"user": {"values": ["0x200..."]}} |
| nonce | number | Action nonce | - |
| evm_tx_hash | string | EVM transaction hash | {"evm_tx_hash": {"values": ["0x..."]}} |
| action.type | string | Action type | {"type": {"values": ["SystemSpotSendAction"]}} |
| action.destination | string | Destination address | {"destination": {"values": ["0x..."]}} |
| action.token | number | Token ID | {"token": {"values": ["124"]}} |
| action.wei | number | Amount in wei | - |
Common Action Types:
SystemSpotSendAction- Spot token transferSystemPerpsAction- Perps system actionCoreWriterAction- Core writer action
Writer Actions Filter Examples
// Get spot sends only (WebSocket)
{"streamType": "writer_actions", "filters": {"type": ["SystemSpotSendAction"]}}
// Get actions for specific token (WebSocket)
{"streamType": "writer_actions", "filters": {"token": ["124"]}}
// Get actions for specific user (WebSocket)
{"streamType": "writer_actions", "filters": {"user": ["0x200..."]}}
TWAP Orders Stream
Track Time-Weighted Average Price order status updates including running, completed, and cancelled TWAP orders.
| Field | Type | Description | Example Filter |
|---|---|---|---|
| user | string | User address | {"user": {"values": ["0x..."]}} |
| coin | string | Trading pair | {"coin": {"values": ["BTC"]}} |
| side | string | "A" or "B" | {"side": {"values": ["B"]}} |
| status | string | TWAP status | {"status": {"values": ["running", "completed"]}} |
MEMPOOL_TXS Stream (Testnet Only)
Monitor pending mempool transactions before block confirmation. Available only on Hyperliquid Testnet via gRPC.
Format: Each event is an array [timestamp, transaction_data]
| Field | Type | Description | Example Filter |
|---|---|---|---|
| tx_hash | string | Transaction hash | {"tx_hash": {"values": ["0x450e9f..."]}} |
| type | string | Action type (order, noop, etc.) | {"type": {"values": ["order", "noop"]}} |
| a | number | Asset ID (for orders) | {"a": {"values": ["122", "6"]}} |
| b | boolean | Buy side (true=buy, false=sell) | {"b": {"values": ["true"]}} |
| p | string | Price (for orders) | - |
| s | string | Size (for orders) | - |
| r | boolean | Reduce only flag | {"r": {"values": ["true"]}} |
| c | string | Client order ID (optional) | {"c": {"values": ["0xf7d966..."]}} |
| nonce | number | Transaction nonce | - |
MEMPOOL_TXS Filter Examples
// Get pending orders for specific asset (gRPC)
{"filters": {"type": {"values": ["order"]}, "a": {"values": ["122"]}}}
// Get buy orders only (gRPC)
{"filters": {"b": {"values": ["true"]}, "type": {"values": ["order"]}}}
// Get all order actions (gRPC)
{"filters": {"type": {"values": ["order"]}}}
StreamL2Book and StreamL4Book (OrderBookStreaming)
The StreamL2Book and StreamL4Book streams are part of a separate gRPC service (OrderBookStreaming) and use a different filtering model. Instead of the filter object syntax used by StreamData, these streams accept the coin directly as a request parameter:
// L2 - coin specified as a request field
L2BookRequest { coin: "BTC", n_levels: 20 }
// L4 - coin specified as a request field
L4BookRequest { coin: "ETH" }
Key differences from StreamData filtering:
- gRPC only -
StreamL2Book/StreamL4Bookare not available via WebSocket or JSON-RPC - Same coin filtering capabilities - The node accepts the same coin parameters as
StreamData
See the StreamL2Book and StreamL4Book dataset pages for full details.
Filter Limits
Three independent dimensions control what you can subscribe to. The same limits apply to both WebSocket and gRPC:
- Concurrent streams - how many active streams you can run simultaneously. Plan-tiered.
- Named filters per stream - how many
filterNameslots a single stream supports. Plan-tiered. - Filter values per field - how many values you can specify per field within one named filter. Server-side constants, the same for all plans.
See Plan Access & FAQ for the full limits table.
Limit error responses
Exceeding the field value cap returns -32602:
{
"error": {
"code": -32602,
"message": "Filter validation failed: Too many values for field 'user': 101 (max: 100)"
}
}
Exceeding the named-filter cap returns -32000:
{
"error": {
"code": -32000,
"message": "Too many named filters per stream: 11 (max: 10)"
}
}
Complete Examples
WebSocket Examples
Basic Subscription
// Subscribe to trades stream
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades"},"id":1}
// Response
{"jsonrpc":"2.0","result":{"subscribed":["trades"]},"id":1}
Filtered Subscriptions
// Filter trades by coin and side
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"coin": ["BTC", "ETH"],
"side": ["B"]
}
},
"id": 1
}
// Get all liquidations
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"liquidation": ["*"]
}
},
"id": 1
}
// Get deposits for specific user
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "events",
"filters": {
"type": ["deposit"],
"users": ["0xabc..."]
}
},
"id": 1
}
// Get SystemSpotSendAction events
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "writer_actions",
"filters": {
"type": ["SystemSpotSendAction"]
}
},
"id": 1
}
Unsubscribe
// Unsubscribe from specific filter
{"jsonrpc":"2.0","method":"hl_unsubscribe","params":{"filterName":"btc_trades"},"id":2}
// Unsubscribe from stream type
{"jsonrpc":"2.0","method":"hl_unsubscribe","params":{"streamType":"trades"},"id":3}
wscat One-Liners
Quick Testing Commands
# All trades (no filter)
wscat -c wss://endpoint/ws -w 9999
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades"},"id":1}
# BTC trades only
wscat -c wss://endpoint/ws -w 9999
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades","filters":{"coin":["BTC"]}},"id":1}
# Liquidations only
wscat -c wss://endpoint/ws -w 9999
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades","filters":{"liquidation":["*"]}},"id":1}
# Specific user's trades
wscat -c wss://endpoint/ws -w 9999
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades","filters":{"user":["0x123..."]}},"id":1}
gRPC Examples
gRPC Filter Examples
// JavaScript gRPC example
const request = {
subscribe: {
stream_type: 'TRADES',
filters: {
"coin": { values: ["BTC", "ETH"] },
"side": { values: ["B"] }
}
}
};
// Python gRPC example
request = {
"subscribe": {
"stream_type": "TRADES",
"filters": {
"liquidation": {"values": ["*"]},
"coin": {"values": ["BTC"]}
}
}
}
// Go gRPC example
request := &pb.SubscribeRequest{
Subscribe: &pb.Subscribe{
StreamType: pb.StreamType_TRADES,
Filters: map[string]*pb.FilterValues{
"coin": {Values: []string{"BTC", "ETH"}},
"user": {Values: []string{"0x123..."}},
},
},
}
Response Format
Subscription Confirmation
{"jsonrpc":"2.0","result":{"subscribed":["trades"]},"id":1}
Stream Data
{
"stream": "trades",
"block_number": 817824278,
"data": {
"block_number": 817824278,
"block_time": "2025-12-04T17:00:15.929034389",
"local_time": "2025-12-04T17:00:16.076556955",
"events": [
["0x727956612a8700627451204a3ae26268bd1a1525", {"coin": "HYPE", "side": "B", ...}]
]
}
}
Important Notes
- Case Sensitivity: Field names and values are case-insensitive (
"Coin" = "coin" = "COIN","btc" = "BTC") - Address Matching: Addresses are case-insensitive (
"0xABC" = "0xabc") - Empty Filters: No filters = receive all events (no filtering applied)
- Whitespace: Values are automatically trimmed of whitespace
- Per-Stream Filters: Each stream can have independent filters
- Recursive Matching: Filters search through nested JSON structures automatically
- Tuple Format: TRADES stream uses
[user, data]format; user filter matches the first element - Blocks Stream: The blocks stream does NOT support filtering (gRPC only, raw data)
Related Documentation
- Data Streams Overview - Learn about available data streams
- gRPC API - gRPC streaming implementation
- JSON-RPC API - WebSocket subscription methods
- StreamL2Book - Aggregated depth via OrderBookStreaming (gRPC only)
- StreamL4Book - Individual order book via OrderBookStreaming (gRPC only)