How to consume the Fast Feed
Open an authenticated WebSocket to the Fast Feed on Arbitrum One, read the fields of each message, reconnect after a drop, and troubleshoot rejected or closed connections.
This guide shows you how to connect to the on and read the messages it publishes. To buy the ticket that admits your connection, follow how to buy Fast Feed access first.
Prerequisites
- An API key bound to an active ticket. How to buy Fast Feed access shows how to generate the key and buy the ticket.
- The Fast Feed endpoint for your network, from addresses and endpoints. The examples read it from
$FEED_URLand the raw key from$API_KEY. - A WebSocket client. The examples use wscat or websocat on the command line, the
wspackage for Node.js, and thewebsocketspackage for Python.
Connect
Once the round in which you bought has ended, open a WebSocket to the Fast Feed endpoint and send your raw API key, not its hash, as a bearer token in the Authorization header of the upgrade request:
Authorization: Bearer <your-api-key>The endpoint hashes the key with Keccak-256, compares it against the active tickets, and only then completes the upgrade. Messages start flowing at once. You open one connection per ticket, and each connection receives the full feed. Three rules apply to every client:
- Complete the upgrade within 5 seconds, or the endpoint drops the socket.
- Send only ping and pong frames.
- Read as fast as the feed arrives. The endpoint drops a client that lags behind, so parse and process off the read loop.
Every frame is a binary WebSocket frame that carries one JSON object with one transaction. The what the Fast Feed publishes section lists every field.
wscat -c "$FEED_URL" -H "Authorization: Bearer $API_KEY"import WebSocket from 'ws';
const ws = new WebSocket(process.env.FEED_URL, {
headers: { Authorization: `Bearer ${process.env.API_KEY}` },
});
ws.on('unexpected-response', (req, res) => {
// 401: unknown key or no active ticket. 429: every ticket already has a connection.
console.error(`Rejected: HTTP ${res.statusCode}`);
req.destroy(); // with a listener attached, ws leaves the request open
});
ws.on('message', (data) => {
const msg = JSON.parse(data.toString());
// msg.pga_round, msg.transaction.tx_hash, msg.transaction.receipt, ...
});
ws.on('close', (code, reason) => {
console.log('closed', code, reason.toString());
});import asyncio
import json
import os
import websockets
async def main():
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
try:
async with websockets.connect(os.environ["FEED_URL"], additional_headers=headers) as ws:
async for frame in ws:
msg = json.loads(frame)
# msg["pga_round"], msg["transaction"]["tx_hash"], msg["transaction"]["receipt"], ...
except websockets.InvalidStatus as e:
# 401: unknown key or no active ticket. 429: every ticket already has a connection.
print(f"Rejected: HTTP {e.response.status_code}")
except websockets.ConnectionClosed as e:
print(f"closed {e.rcvd.code} {e.rcvd.reason}")
asyncio.run(main())This example needs websockets 14 or later. Older versions use extra_headers= instead of additional_headers=.
What the Fast Feed publishes
Each message is a FeedMessage envelope that carries one transaction plus the metadata that you need to place it in time and in order. The Sequencer sends each message as a JSON object inside a binary WebSocket frame, so byte fields arrive as hex-encoded strings.
| Field | Type | Description |
|---|---|---|
version | number | Protocol version, for forward compatibility (currently 1) |
timestamp_ms | number | Unix time in milliseconds when the Sequencer created the message |
pga_round | number, optional | The PGA round this transaction belongs to, within the block, starting at 1 |
transaction | object | The transaction data and its partial receipt |
The transaction object carries the transaction itself:
| Field | Type | Description |
|---|---|---|
block_number | number | Tentative block number, not guaranteed to be final |
tx_index | number | Position within the block so far |
raw_tx | string | Hex-encoded, RLP-encoded signed transaction |
tx_hash | string | Hex-encoded transaction hash |
receipt | object | Execution result |
What the receipt reports:
statusgas_usedgas_used_for_l1cumulative_gas_usedeffective_gas_pricebase_fee- Any
contract_addressthe transaction created - The event
logsemitted by the transaction
Each entry in logs carries three fields:
address: the hex-encoded address of the contract that emitted the eventtopics: the hex-encoded topics of the event, in orderdata: the hex-encoded event data
Reconnect after a drop
If your connection closes, reconnect and continue from the current head. The Fast Feed keeps no history, so the messages sent while you were away are gone.
To keep a connection open from one round to the next, buy a ticket for every round, as described in keep the connection across rounds.
Troubleshoot
Connection rejected or closed
| Response | Cause | Fix |
|---|---|---|
HTTP 401 Unauthorized | The Authorization header is missing, or the key's hash has no active ticket. | Check the raw key and its hash. Tickets bought this round activate at roundEnd. |
HTTP 429 Too Many Requests | The key already has as many open connections as it has active tickets. | Close a connection, or buy more tickets for the next round. |
HTTP 426 Upgrade Required | The request was not a WebSocket upgrade, for example a plain HTTPS GET. | Use a WebSocket client. |
Close 1008, authentication expired | The round ended and your key holds no ticket in the new round. | Buy before roundEnd each round, then reconnect. |
Close 1013, client lagged | Your client fell more than 2048 messages behind. | Drain the socket faster. Move parsing and processing off the read loop, then reconnect. |
Close 1003, unexpected client message | Your client sent a data frame. | Send only ping and pong frames. |
Close 1011, server shutting down | The endpoint restarted. | Reconnect with a short backoff. |
FAQ
Do I need a Nitro node? No. The Fast Feed is a stream for your own client. To follow the chain, use the free sequencer feed instead.
How is this guide?
Buy Fast Feed access
Generate an API key, deposit USDG, and buy a ticket each round from the Tickets contract to access the Fast Feed on Arbitrum One, automate renewals with the reference bot, and troubleshoot purchase reverts.
PGA and Fast feed
Detailed explanations of Priority Gas Auction (PGA) and Fast Feed.