> ## Documentation Index
> Fetch the complete documentation index at: https://docs.0xarchive.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Mempool channel

> Stream signed Hyperliquid transactions before they are in a block on the live-only mempool channel: endpoint, plans, messages, limits, and errors.

Watch Hyperliquid transactions before they are in a block. The `mempool` channel streams each signed action our Hyperliquid node receives from its peers, such as orders, cancels, modifies, TWAPs, leverage changes and transfers, as soon as it arrives. It covers every Hyperliquid product: perps, HIP-3, HIP-4 and Spot.

<Warning>
  Pending is not executed. A transaction on this channel is not yet in a block, and it can still be rejected, expire or never land. For fills and order outcomes, use the trade and L4 order channels for the product; see [WebSocket channels](/websocket/channels).
</Warning>

The channel is live only. It has no replay, no history, no REST route and no export, and it is never stored: a message you miss while not subscribed cannot be fetched later.

## Endpoint and plans

Connect to `wss://stream.0xarchive.io/ws`, the only endpoint that serves `mempool`. It takes the same API key and the same protocol as `wss://api.0xarchive.io/ws`: send the key in the opening handshake as `Authorization: Bearer $OXARCHIVE_API_KEY`, as [WebSocket connection](/websocket/connection) describes. A `mempool` subscribe on `wss://api.0xarchive.io/ws` returns an `error` with `error_code` `endpoint_unsupported`:

```json theme={"theme":"github-dark"}
{
  "type": "error",
  "message": "The 'mempool' channel is live only and served on wss://stream.0xarchive.io/ws. Subscribe to it there.",
  "error_code": "endpoint_unsupported"
}
```

Most other channels are served only on `wss://api.0xarchive.io/ws`, so a client that also needs them keeps a second connection there. Subscribing to one of them on the stream endpoint returns `endpoint_unsupported` naming the endpoint to use.

The `mempool` channel is included with the Pro, Scale and Enterprise plans. It is the one channel that is not on every plan: every other channel and route is on every plan, Free included. On Free and Build, a `mempool` subscribe returns:

```json theme={"theme":"github-dark"}
{
  "type": "error",
  "message": "The mempool channel is included with the Pro, Scale and Enterprise plans. Upgrade at https://0xarchive.io/pricing.",
  "error_code": "forbidden"
}
```

## Subscribe

Subscribe without a symbol to receive every pending transaction our Hyperliquid node receives:

```json theme={"theme":"github-dark"}
{ "op": "subscribe", "channel": "mempool" }
```

Or add `symbol` to receive only the actions that reference one market:

```json theme={"theme":"github-dark"}
{ "op": "subscribe", "channel": "mempool", "symbol": "BTC" }
```

`symbol` is optional on this channel and on no other. Spell it as on the other channels: `BTC` for perps, `xyz:XYZ100` for HIP-3, `HYPE-USDC` for Spot (`HYPE/USDC` is accepted too), and the outcome side coin, such as `#49720`, for HIP-4. An unknown symbol returns `error_code` `invalid_symbol`.

A symbol subscription receives every action whose asset ids include that market. An action that references several markets, such as an order batch on BTC and ETH, is sent whole to the subscribers of each. If you hold the unfiltered stream and a symbol subscription on one connection, a matching action arrives on both.

The server confirms each subscription. The unfiltered stream is confirmed with `null` in `coin` and `symbol`:

```json theme={"theme":"github-dark"}
{ "type": "subscribed", "channel": "mempool", "coin": null, "symbol": null }
```

A symbol subscription is confirmed with the canonical spelling in both fields, such as `HYPE-USDC` for a subscribe sent as `HYPE/USDC`:

```json theme={"theme":"github-dark"}
{ "type": "subscribed", "channel": "mempool", "coin": "HYPE-USDC", "symbol": "HYPE-USDC" }
```

To stop, send `unsubscribe` with the same fields. Without `symbol`, it stops the unfiltered stream; with `symbol`, it stops that symbol's subscription. The server answers `unsubscribed` with the same `coin` and `symbol`.

```json theme={"theme":"github-dark"}
{ "op": "unsubscribe", "channel": "mempool", "symbol": "BTC" }
```

## Run a first subscription

This Node.js script subscribes to `mempool` for BTC, prints ten pending actions, then unsubscribes and closes. It needs a key on the Pro, Scale or Enterprise plan and the `ws` package (`npm install ws`).

```javascript theme={"theme":"github-dark"}
import WebSocket from "ws";

const apiKey = process.env.OXARCHIVE_API_KEY;
if (!apiKey) throw new Error("Set OXARCHIVE_API_KEY");

const ws = new WebSocket("wss://stream.0xarchive.io/ws", {
  headers: { Authorization: `Bearer ${apiKey}` }
});
let seen = 0;

ws.on("open", () => {
  ws.send(JSON.stringify({ op: "subscribe", channel: "mempool", symbol: "BTC" }));
});

ws.on("message", (raw) => {
  const message = JSON.parse(raw);
  if (message.type === "subscribed") console.log("subscribed", message.channel, message.symbol);
  if (message.type === "error") {
    console.error(message.error_code, message.message);
    ws.close();
    return;
  }
  if (message.type !== "data" || seen >= 10) return;
  for (const item of message.data) {
    console.log(item.received_at, item.action.type, item.symbols.join(","));
    seen += 1;
    if (seen === 10) {
      ws.send(JSON.stringify({ op: "unsubscribe", channel: "mempool", symbol: "BTC" }));
      ws.close();
      break;
    }
  }
});

ws.on("close", (code, reason) => console.log("closed", code, String(reason)));
```

The messages on this page work with any WebSocket client.

## Data messages

Each `data` message carries one batch of transactions, sent as soon as the node receives it from a peer. `coin` and `symbol` are the subscription's symbol, or `null` on the unfiltered stream, and `data` holds one item per signed action:

```json theme={"theme":"github-dark"}
{
  "type": "data",
  "channel": "mempool",
  "coin": "BTC",
  "symbol": "BTC",
  "data": [
    {
      "received_at": "2026-10-08T01:57:23.548737209Z",
      "received_at_ms": 1791424643548,
      "symbols": ["BTC"],
      "action": {
        "type": "order",
        "orders": [
          {
            "a": 0,
            "b": true,
            "p": "83276",
            "s": "0.40011",
            "r": false,
            "t": { "limit": { "tif": "Alo" } },
            "c": "0x7849acc2c6c2f6f0fe4bc80ef13d1504"
          }
        ],
        "grouping": "na"
      },
      "nonce": 1791424643400,
      "vault_address": null,
      "expires_after_ms": null,
      "signature": {
        "r": "0x5afc29701358e4082d744d4332915079664d27d0244565b94b7966adfd2776d9",
        "s": "0x57e2d718fa45c0c191dc0f0c1ad6e6e0fc3e026cdfc4148c3ae8b3b32fd02c8d",
        "v": 28
      }
    }
  ]
}
```

Each item has these fields, in this order:

| Field | Meaning |
| - | - |
| `received_at` | When our Hyperliquid node received the transaction, as an RFC 3339 UTC string with nanosecond precision. It is not a block time. |
| `received_at_ms` | The same time in Unix milliseconds. |
| `symbols` | The markets the action's asset ids reference, in the canonical spelling, in first-seen order and without repeats. `[]` for an action with no market, such as a transfer, `noop`, `scheduleCancel` or a validator action. |
| `action` | The action exactly as it was signed, in Hyperliquid's exchange-action format: markets are asset ids (`a` or `asset`), not symbols, and prices and sizes are strings (`p`, `s`). |
| `nonce` | The action's nonce, an integer. |
| `vault_address` | The vault or subaccount the action acts for, or `null`. |
| `expires_after_ms` | The action's `expiresAfter` time in Unix milliseconds, or `null`. |
| `signature` | The action's signature, as `r`, `s` and `v`. |

`action` and `signature` are passed through byte for byte. The signer's address is not included; you can recover it from the signed fields (`action`, `nonce`, `vault_address`, `expires_after_ms`) and `signature` with Hyperliquid's signing scheme.

`action.type` names the action. Common types are `order`, `cancel`, `cancelByCloid`, `modify`, `batchModify`, `scheduleCancel`, `twapOrder`, `twapCancel`, `updateLeverage`, `updateIsolatedMargin`, `noop`, `evmRawTx`, and transfers such as `usdSend`, `spotSend`, `usdClassTransfer` and `sendAsset`. Hyperliquid adds types over time, so pass over a type you do not recognize instead of failing on it.

The same signed action can occasionally arrive twice. Deduplicate on `signature` when you count or store actions.

## Volume and limits

The unfiltered stream carries every pending transaction our Hyperliquid node receives, several megabytes per second before compression. Use a client that negotiates permessage-deflate compression, as most WebSocket libraries do by default, and subscribe with a symbol where the job allows it.

* **Unfiltered capacity:** unfiltered subscriptions are limited across the service. When they are full, a subscribe without `symbol` returns `error_code` `rate_limited` with `The unfiltered mempool stream is at capacity. Subscribe with a symbol, or try again later.` Symbol subscriptions are not limited this way.
* **Slow consumers:** as on any channel, a connection that reads too slowly is closed after an `error` with `error_code` `slow_consumer`. Read each message off the socket promptly and do heavy work elsewhere.
* **Plan limits:** the unfiltered stream and each symbol count as one subscription toward your plan's limit per connection, and a connection accepts at most 10 subscribe or unsubscribe operations per second. See [WebSocket limits](/websocket/limits).
* **Credits:** each `data` message is billed like any other WebSocket message; see [Credits](/core-concepts/credits). The unfiltered stream sends many messages, so check its usage in the dashboard after a short run.

## Errors

Errors arrive as `error` messages with a stable `error_code`. The connection stays open after each of these except `slow_consumer`.

| `error_code` | Cause and next step |
| - | - |
| `forbidden` | Your plan does not include `mempool`. Move to Pro, Scale or Enterprise on the [pricing page](https://0xarchive.io/pricing). |
| `endpoint_unsupported` | You subscribed on `wss://api.0xarchive.io/ws`. Connect to `wss://stream.0xarchive.io/ws` and subscribe there. |
| `invalid_symbol` | The symbol is not a Hyperliquid market. Check its spelling for the product family. |
| `rate_limited` | The unfiltered stream is at capacity, or the connection reached its subscription or operation limit. Subscribe with a symbol, unsubscribe from something, or slow down. |
| `upstream_unavailable` | `The mempool channel is temporarily unavailable. Please try again shortly.` Retry with capped backoff. |
| `slow_consumer` | The connection fell behind and is closed. Reconnect, subscribe to less, and read faster. |

The channel has no replay: a `replay` command for `mempool` returns an `error`. [Errors](/errors#websocket-errors) lists every code.

## Next step

Size subscriptions and consumers for the stream with [WebSocket limits](/websocket/limits).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.