Skip to main content
Optimism produces Subblocks, formerly called Flashblocks: partial blocks with pre-confirmed transactions, about every 200 ms. Optimism exposes them through the standard pending block tag, not through dedicated WebSocket subscriptions. To follow transactions in real time on Optimism, poll the pending block roughly every 200 ms and track the transactions that are new since the last poll. This guide does that with tested Python and JavaScript, then covers the pre-confirmed read methods.
For how Subblocks work on Optimism, see Subblocks on Optimism. For Base, which exposes Flashblocks as WebSocket subscriptions, see Stream real-time transactions on Base with Flashblocks.

Prerequisites

  • An Optimism mainnet HTTPS endpoint. On Chainstack, copy it from your Optimism node’s Access and credentials tab — it looks like https://optimism-mainnet.core.chainstack.com/<key>. The examples use YOUR_OPTIMISM_HTTPS_ENDPOINT as a placeholder.
  • Python 3.8+ with the requests library (pip install requests), or Node.js 18+ (the fetch API is built in, so there are no dependencies to install).

Why Optimism uses the pending tag, not eth_subscribe

On Optimism, the Flashblocks subscriptions that exist on Base — eth_subscribe("newFlashblockTransactions"), newFlashblocks, and pendingLogs — are not exposed; calling them returns -32602 Invalid params. Like every OP Stack chain, Optimism has no public mempool (see Mempool configurations), so eth_subscribe("newPendingTransactions") reports only transaction hashes as the sequencer includes them in subblocks. The pending block tag gives you the transactions themselves and the pre-confirmed state, and it reflects the latest subblock and advances every ~200 ms.

Track pre-confirmed transactions

Poll eth_getBlockByNumber("pending", false) every 200 ms and emit transaction hashes you have not seen before. Each poll returns the block the sequencer is currently building; within one block number the transaction list grows every ~200 ms as new subblocks arrive.
You get a continuous flow of newly pre-confirmed transaction hashes:
The seen set de-duplicates hashes that repeat across polls of the same in-progress block. In a 30-second test against Optimism Mainnet, the script emitted 230 transaction hashes, about 8 per second.

How the pending block evolves

Each poll of the pending tag returns the same block number with more transactions and a different pre-confirmation hash, until the block seals and the number advances. Polled with a 200 ms pause between requests:
Unlike Base, where the streamed block carries a zero hash until it seals, Optimism’s pending hash is non-zero and changes with each subblock. The pending hash is not the hash of the sealed block, and the pending block’s stateRoot is all zeros. Track transactions by their own hash, not by the block hash.

Read pre-confirmed state

The pending tag also serves request-response reads against pre-confirmed state, which updates about every 200 ms instead of every 2 s with each canonical block:
  • eth_getBlockByNumber, eth_call, eth_getBalance, eth_getTransactionCount, eth_getCode, eth_getStorageAt, and eth_estimateGas with the pending tag.
  • eth_getTransactionReceipt and eth_getTransactionByHash return the pre-confirmed receipt or transaction as soon as it lands in a subblock.
  • eth_sendRawTransactionSync submits a signed transaction and returns its pre-confirmed receipt in the same response.

Production considerations

  • Pre-confirmations are not final. The sequencer can abandon or reorganize the block in progress until the 2-second canonical block seals, so for settlement confirm against latest or a finalized block.
  • Poll at ~200 ms. That matches the subblock cadence; polling much faster mostly returns the same state.
  • De-duplicate by transaction hash. The same transaction appears in every poll of the block it belongs to until that block seals.
  • A poll that lands after a block seals misses the transactions added to that block since the previous poll. To capture every transaction, also read each sealed block with eth_getBlockByNumber.
  • newPendingTransactions carries transaction hashes only. Optimism has no public mempool, so the subscription reports a transaction when the sequencer includes it in a subblock. For transaction details, receipts, and pre-confirmed state, use the pending tag.
Last modified on October 30, 2026