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

# How to Use preconfSubscribe

> Stream scheduled Solana transactions at the lowest possible latency with the preconfSubscribe WebSocket method. Subscribe, decode the payload, and react before transactions land.

<Tip>
  **Use [Sender Max](/docs/sending-transactions/sender-max) (min tip: 0.001 SOL) to
  act on Preconfirmations.** A preconfirmation only pays off if you land your
  transaction
  first — Sender Max is the fastest way to do that. Build on Sender Max from the
  start to get the full benefit of Preconfirmations.
</Tip>

## What is `preconfSubscribe`?

`preconfSubscribe` is a Helius WebSocket method that streams [Preconfirmations](/docs/pre-confirmations/overview) — transactions delivered at the scheduled-transaction stage, before they are shredded. It is the lowest-latency transaction signal Helius offers. Access requires a [Professional plan or higher](/docs/billing/plans) — see [Pricing](#pricing).

<Note>
  The stream is not continuous. Coverage scales with the share of stake
  forwarding to Helius, so expect slots with no messages — handle these gaps
  gracefully. See [Coverage](/docs/pre-confirmations/overview#coverage).
</Note>

`preconfSubscribe` is served from `wss://beta.helius-rpc.com` — the Helius [Gatekeeper](/docs/gatekeeper/overview) endpoint — rather than `mainnet.helius-rpc.com`. Authenticate with your API key as a query parameter.

```
wss://beta.helius-rpc.com/?api-key=<API_KEY>
```

<Note>
  The `beta` hostname refers to the [Gatekeeper](/docs/gatekeeper/overview) rollout,
  not the maturity of Preconfirmations. Preconfirmations launch on the
  Gatekeeper endpoint first; it will become the standard endpoint as Helius
  migrates traffic to Gatekeeper.
</Note>

## Subscribe

Send a JSON-RPC request with the `preconfSubscribe` method. The server responds with a subscription ID, then streams a notification for each scheduled transaction. Pass an optional [filter](#filtering) as the first `params` element to receive only matching transactions; omit `params` to receive the full stream.

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preconfSubscribe"
}
```

### Subscribe Response

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "result": 24040,
  "id": 1
}
```

Store the `result` — it is the subscription ID you use to [unsubscribe](#unsubscribing). After this acknowledgement, notifications stream as binary frames (see below).

## Filtering

By default `preconfSubscribe` streams every scheduled transaction. To narrow the stream, pass a filter object as the first element of `params`. Filtering happens server-side, so you only pay for and receive the transactions you care about.

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preconfSubscribe",
  "params": [
    {
      "failed": false,
      "regionInclude": ["ewr", "fra"],
      "accountInclude": ["9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"],
      "accountExclude": ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
      "accountRequired": ["11111111111111111111111111111111"]
    }
  ]
}
```

Every field is optional — a missing field means "no constraint" for that predicate, so an empty filter (or no `params`) matches every transaction.

| Field             | Type       | Semantics                                                                                                                                                |
| ----------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `failed`          | `boolean`  | `false` drops failed (reverted) transactions; success and unknown-status transactions still pass. `true` — like omitting the field — keeps every status. |
| `regionInclude`   | `string[]` | If non-empty, the transaction must originate from **one of** these [regions](#location-filtering).                                                       |
| `accountInclude`  | `string[]` | If non-empty, the transaction must reference **at least one** of these accounts.                                                                         |
| `accountExclude`  | `string[]` | The transaction is dropped if it references **any** of these accounts. Takes precedence over `accountInclude`.                                           |
| `accountRequired` | `string[]` | The transaction must reference **all** of these accounts.                                                                                                |

Filter rules:

* All predicates are ANDed together, evaluated in the order `regionInclude` → `accountExclude` → `accountRequired` → `accountInclude`.
* Accounts are base58-encoded pubkeys. An invalid value returns JSON-RPC error `-32602` (invalid params).
* Each account list is capped at **500** entries.

### Address lookup table (ALT) resolution

Account filters match more than the transaction's static account keys — Helius resolves v0 [address lookup tables](/docs/glossary#address-lookup-table-alt) server-side, so `accountInclude`, `accountExclude`, and `accountRequired` also match accounts a transaction loads through an ALT.

This means you can filter on any account a transaction touches, even when it only appears behind a lookup table — no need to maintain ALT mappings or resolve tables yourself. Just pass the account's pubkey and Helius handles the resolution before the filter is applied.

### Location filtering

Use `regionInclude` to receive only transactions that originate from specific Helius regions. Pass one or more region codes; a transaction passes when its origin region matches any of them.

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "preconfSubscribe",
  "params": [{ "regionInclude": ["ewr", "fra"] }]
}
```

Valid region codes:

| Code  | Location       |
| ----- | -------------- |
| `slc` | Salt Lake City |
| `fra` | Frankfurt      |
| `lon` | London         |
| `pit` | Pittsburgh     |
| `sgp` | Singapore      |
| `ewr` | Newark         |
| `tyo` | Tokyo          |
| `ams` | Amsterdam      |
| `dal` | Dallas         |
| `dub` | Dublin         |
| `mia` | Miami          |
| `lax` | Los Angeles    |
| `iad` | Ashburn        |
| `sea` | Seattle        |

<Note>
  When `regionInclude` is set, transactions that don't carry region information are dropped. An unrecognized region code returns JSON-RPC error `-32602` (invalid params).
</Note>

## Notification payload

Notifications are delivered as **binary** WebSocket frames (not JSON). Each frame is a packed byte layout carrying a single scheduled transaction:

| Bytes | Field         | Type                            | Description                                                                                                                                                    |
| ----- | ------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 0     | `version`     | `u8`                            | Payload schema version. Currently `1`.                                                                                                                         |
| 1–8   | `slot`        | `u64` (little-endian)           | The slot the transaction is scheduled in.                                                                                                                      |
| 9–16  | `tx_index`    | `u64` (little-endian)           | Index of the transaction within the slot.                                                                                                                      |
| 17    | `status`      | `u8`                            | Transaction status: `0` = failed, `1` = success, `2` = unknown. Execution status is reported by validators on a best-effort basis — `2` when it's unavailable. |
| 18+   | `transaction` | `bincode(VersionedTransaction)` | The scheduled transaction, bincode-serialized.                                                                                                                 |

Read the fields in order, then [`bincode`](https://docs.rs/bincode)-deserialize the remaining bytes into a `VersionedTransaction` to read instructions, accounts, and the signature.

<Warning>
  **Always read and check the `version` byte first.** It is currently `1`. If
  Helius needs to update the payload format, the version will increment — branch
  on it so your decoder keeps working across schema changes.
</Warning>

<Note>
  A preconfirmation is an early signal, not a guarantee. The transaction has not
  yet landed onchain and could still fail or be dropped. Confirm landing through
  standard commitment checks before treating it as final.
</Note>

## Example

```javascript theme={"system"}
const WebSocket = require('ws');

const ws = new WebSocket('wss://beta.helius-rpc.com/?api-key=<API_KEY>');

ws.on('open', () => {
  ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'preconfSubscribe'
    // Optional: only successful txs from EWR/FRA touching a given account
    // params: [{ failed: false, regionInclude: ['ewr', 'fra'], accountInclude: ['9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM'] }]
  }));

  // Keep the connection alive
  setInterval(() => ws.ping(), 30_000);
});

ws.on('message', (data, isBinary) => {
  // The subscribe acknowledgement arrives as a JSON text frame
  if (!isBinary) {
    const msg = JSON.parse(data.toString());
    if (msg.id === 1) console.log('Subscribed, ID:', msg.result);
    return;
  }

  // Notifications arrive as binary frames:
  // version (u8) | slot (u64 LE) | tx_index (u64 LE) | status (u8) | bincode(VersionedTransaction)
  const buf = Buffer.from(data);
  const version = buf.readUInt8(0); // currently 1 — branch on this if it changes
  if (version !== 1) return; // unknown schema version; update your decoder
  const slot = buf.readBigUInt64LE(1);
  const txIndex = buf.readBigUInt64LE(9);
  const status = buf.readUInt8(17); // 0 = failed, 1 = success, 2 = unknown
  const txBytes = buf.subarray(18); // bincode-serialized VersionedTransaction

  console.log('Scheduled transaction:', { version, slot, txIndex, status, bytes: txBytes.length });
  // Deserialize txBytes (bincode) into a VersionedTransaction with your Solana tooling
});

ws.on('error', console.error);
ws.on('close', () => process.exit(1));
```

## Unsubscribing

To stop receiving notifications, call `preconfUnsubscribe` with the subscription ID returned from `preconfSubscribe`.

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "preconfUnsubscribe",
  "params": [24040]
}
```

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "result": true,
  "id": 2
}
```

## Pricing

Preconfirmations require a **Professional plan or higher** and cost **10 credits per message** — one message per streamed transaction — billed from your plan. See [Credits](/docs/billing/credits) for details.

<Note>
  Preconfirmations is a new product and pricing is subject to change.
</Note>

## Related

<CardGroup cols={2}>
  <Card title="Preconfirmations Overview" icon="bolt" href="/docs/pre-confirmations/overview">
    What Preconfirmations are and where they sit in the validator pipeline.
  </Card>

  <Card title="transactionSubscribe" icon="tower-broadcast" href="/docs/rpc/websocket/transaction-subscribe">
    Stream confirmed-commitment transactions with rich filtering.
  </Card>

  <Card title="preconfSubscribe API reference" icon="code" href="/docs/api-reference/pre-confirmations/preconfsubscribe">
    Request parameters, filter fields, and the binary notification layout.
  </Card>
</CardGroup>
