> For a complete page index, fetch https://docs.conduit.xyz/llms.txt

# Connect to the flashblocks stream

> Subscribe to a G3 chain's flashblocks WebSocket stream and validate the sequence of partial block updates.

G3 sequencers publish **flashblocks** every 10 milliseconds over WebSocket. Each partial block update carries the transactions and receipts added since the previous flashblock, along with account balance metadata, so your app sees state changes hundreds of milliseconds before the block seals.

A WebSocket proxy serves the stream through one endpoint.

If you need the accumulated state instead of each update, [query flashblock state through the public JSON-RPC endpoint](/chains/guides/g3/query-flashblock-state).

> **Note**
>
> Conduit enables the flashblocks stream per chain. Contact your Conduit account team for your chain's WebSocket endpoint and credentials.

## Connect

Start with your chain's RPC endpoint, `https://[YOUR_RPC_HOST]/[YOUR_API_KEY]`. Connect to the same host over WebSocket at `wss://[YOUR_RPC_HOST]/flashblocks/[YOUR_API_KEY]`.

**`Python`**

```python Python
import asyncio
import json

import websockets

WS_URL = "wss://[YOUR_RPC_HOST]/flashblocks/[YOUR_API_KEY]"


async def main():
    async with websockets.connect(
        WS_URL,
        ping_interval=20,
        ping_timeout=30,
    ) as ws:
        while True:
            flashblock = json.loads(await ws.recv())
            print(
                flashblock["metadata"]["block_number"],
                flashblock["index"],
                len(flashblock["diff"]["transactions"]),
            )


asyncio.run(main())
```

**`TypeScript`**

```typescript TypeScript
import WebSocket from "ws";

const ws = new WebSocket("wss://[YOUR_RPC_HOST]/flashblocks/[YOUR_API_KEY]");

ws.on("message", (raw) => {
  const flashblock = JSON.parse(raw.toString());
  console.log(
    flashblock.metadata.block_number,
    flashblock.index,
    flashblock.diff.transactions.length,
  );
});
```

Configure your client to accept messages large enough for your chain's busiest flashblocks. Each message can include every raw transaction and receipt added in that update.

## Read a flashblock

Every message is one JSON flashblock:

```json
{
  "payload_id": "0x038c03e80f2fd41d",
  "index": 0,
  "base": {
    "parent_hash": "0xea7f...",
    "fee_recipient": "0x4200000000000000000000000000000000000011",
    "block_number": "0x1254e",
    "gas_limit": "0x2540be400",
    "timestamp": "0x69d83fac",
    "base_fee_per_gas": "0x3b9aca00"
  },
  "diff": {
    "state_root": "0x0000...0000",
    "receipts_root": "0x0000...0000",
    "gas_used": "0xb466",
    "block_hash": "0x0000...0000",
    "transactions": ["0x7ef90106a0488f...0190"],
    "withdrawals": []
  },
  "metadata": {
    "block_number": 75086,
    "new_account_balances": { "0x0000f908...": "0x0" },
    "receipts": { "0x6b034f...": { "status": "0x1", "logs": [] } }
  }
}
```

| Field        | Notes                                                                                                                                                                                                           |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `payload_id` | Identifies the block the sequencer is building. Stable across every flashblock of one block.                                                                                                                    |
| `index`      | Position within the block, starting at 0. Increases by 1 per flashblock.                                                                                                                                        |
| `base`       | Header fields fixed for the block. Present only on `index` 0.                                                                                                                                                   |
| `diff`       | Incremental transactions plus fields for the partial block. `transactions` holds the raw, RLP-encoded transactions added in this flashblock and can be empty. `gas_used` is cumulative through this flashblock. |
| `metadata`   | `block_number` as an integer, `new_account_balances` keyed by account address, and incremental `receipts` keyed by transaction hash. Balance entries can repeat across flashblocks.                             |

Two properties are worth planning around:

* **`index` 0 opens a block.** It carries `base` and always contains at least the L1 deposit transaction.
* **Intermediate roots and hashes remain zero.** `state_root`, `receipts_root`, and `block_hash` remain zero while the block is under construction. Only the final flashblock of a block, the seal, carries their completed values.

## Flashblock reorgs

A flashblock reorg replaces transactions or state published in an earlier flashblock before the block seals. Conduit targets fewer than three flashblock reorgs per year. G3's durability design aims to limit these reorgs to scenarios involving major hardware faults.

Even with this durability target, flashblocks remain preconfirmations. Before treating flashblock data as settled, verify against the canonical block with `eth_getBlockByNumber` once the chain tip has moved past it.

## Handle gaps

Track `(metadata.block_number, index)` to detect skipped updates. Wait for an `index` of 0 before processing to begin at a clean block boundary. If a connection gap leaves you without finalized data, backfill it from canonical blocks over RPC.