Blocks
The raw Hyperliquid L1 block stream.
Every L1 block as produced: height, timestamp, and the raw block content. The base layer if you want to run your own decoding, indexing, or verification on top of our node fleet.
- Method
- hyperliquid.BlockStreaming/StreamBlocks
- Also via
- hyperliquid.Streaming/StreamData (stream_type: BLOCKS)
- Endpoint
- stream.hyperliquidrpc.com:443 · gRPC over TLS (HTTP/2)
- Auth
- API key in x-api-key metadata
- Volume
- One message per L1 block. Individual blocks can be large; raise your client's max receive size.
When to use it
The blocks stream is for teams that want the source material, not our decodings: custom indexers with their own schemas, verification pipelines that audit derived feeds against the chain, and research that needs transaction types the decoded streams don't carry. You get every L1 block as produced, riding on our node fleet instead of operating your own.
If a decoded stream already carries what you need (trades, orders, book changes, events), use it. Decoding raw blocks is real work; the derived streams exist so you don't have to do it.
Method
// stream.hyperliquidrpc.com:443 — gRPC over TLS (HTTP/2)// auth: API key in x-api-key metadata · server reflection enabledpackage hyperliquid; service BlockStreaming { // Raw L1 blocks as produced. timestamp: 0 streams from the head. rpc StreamBlocks (Timestamp) returns (stream Block);}Also reachable QuickNode-compatibly via hyperliquid.Streaming/StreamData with stream_type: BLOCKS. That route accepts start_block for height-based replay.
Subscribe
# Streams JSON-encoded messages until you disconnect.grpcurl -H 'x-api-key: YOUR_KEY' \ -max-msg-sz 268435456 \ -d '{"timestamp":0}' \ stream.hyperliquidrpc.com:443 \ hyperliquid.BlockStreaming/StreamBlocksMessage fields
Fields typed string that carry numbers are byte-exact decimal strings, verbatim from the node. Compare and store them as strings or arbitrary-precision decimals. Never parseFloat a price you intend to reconcile.
Server-side filters
- replay from a block height
Filters are applied on the server, so filtered-out messages never leave our edge. You only pay for what you subscribe to. Request shapes for every stream family are on Filtering; backfill semantics on Replay & backfill.
Semantics & gotchas
Sequential stream of blocks; replay from any height to backfill, then continue live.
- The payload is raw. Block content arrives verbatim from the node; your pipeline owns parsing and interpretation. Schema changes on the L1 side surface here first.
- Heights are contiguous; verify them. Track the last
heightyou processed and treat any jump as a gap. Replay from the missing height viaStreamDatawithstream_type: BLOCKSrather than guessing. - One message per block, but bursts happen on catch-up. After a reconnect with replay, blocks arrive as fast as you can read them until you reach the head. Make ingestion backpressure- aware.
Sample message
{ "height": 612408133, "block_time": "2026-06-09T08:14:02.418Z", "num_txs": 1742, "raw": "<bytes: 1.8 MB>"}One message per L1 block. Individual blocks can be large; raise your client's max receive size.
Recipes
Feed a custom indexer
Consume blocks, decode the transaction types you care about, and write to your own store. You inherit our node operations (peers, upgrades, disk) and keep full control of the schema.
for block in stub.StreamBlocks(request, metadata=meta): txs = decode(block.raw) # your decoder, your schema index(block.height, block.block_time, txs) checkpoint(block.height) # persist progress for gap-free restartGap-free ingestion across restarts
Persist the last processed height. On restart, replay from the checkpoint via the StreamData route, then continue live. This is the backfill-then-live pattern, applied to blocks.
# Resume from a checkpointed height (height-based replay)grpcurl -H 'x-api-key: YOUR_KEY' -max-msg-sz 268435456 \ -d '{"subscribe":{"stream_type":"BLOCKS","start_block":612408133}}' \ stream.hyperliquidrpc.com:443 \ hyperliquid.Streaming/StreamDataAudit a derived feed
Decode fills from raw blocks for one market and diff them against the trades stream for the same heights. Byte-exact decimal strings on both sides make the comparison a string equality, not a tolerance check.