Binance Futures wire format
How Binance USDⓈ-M Futures messages become rows in our Parquet files. Each data type below shows a real message next to the rows we publish for it, with the source and the rule for every column. Hover a line or a column to see how they connect.
Checked against our pipeline
These messages were captured from Binance USDⓈ-M Futures on 2026-10-05. Our test suite replays each one through the production collector parser and postprocessor, and fails if the published rows differ from the rows on this page. Files written before a change to the pipeline can differ; see Known Gaps & Corrections.
- Public WebSocket (depth, trades):
wss://fstream.binance.com/public/stream?streams=<symbol>@depth@0ms/<symbol>@trade - Market WebSocket (ticker, mark price, liquidations):
wss://fstream.binance.com/market/stream?streams=!ticker@arr/!markPrice@arr@1s/!forceOrder@arr - REST:
https://fapi.binance.com
Exchange API reference: developers.binance.com. Conventions shared by every exchange are on the wire formats overview.
Trades
One row per trade from the <symbol>@trade stream.
- WebSocket <symbol>@trade
Trade
{"stream": "btcusdt@trade","data": {"e": "trade","E": 1791226908849,→ event_time"T": 1791226908849,→ trade_time"s": "BTCUSDT",→ symbol"t": 8148200197,→ trade_id"p": "85583.20",→ price"q": "0.064",→ quantity"X": "MARKET",→ order_type"m": true,→ is_buyer_maker"st": 1}}
Published row
true means the seller was the aggressor.MARKET if Binance omits the field.Non-market trade (X: "NA")
Binance also sends trade events with order type NA and price and quantity 0. Their trade IDs belong to the same sequence as market trades. We publish them unchanged.
{"stream": "btcusdt@trade","data": {"e": "trade","E": 1791226491521,→ event_time"T": 1791226491521,→ trade_time"s": "BTCUSDT",→ symbol"t": 8148193400,→ trade_id"p": "0",→ price"q": "0",→ quantity"X": "NA",→ order_type"m": false,→ is_buyer_maker"st": 1}}
Published row
true means the seller was the aggressor.MARKET if Binance omits the field.Notes
- Rows with
order_typeNAhavepriceandquantity0. Exclude them before you compute volume, VWAP or price statistics. Keep them if you usetrade_idto detect gaps.
Column types and descriptions: Trades schema.
Order Book
One row per price level. Updates come from the <symbol>@depth@0ms stream; REST snapshots anchor the book.
- WebSocket <symbol>@depth@0ms
- REST GET /fapi/v1/depth
Depth update
Abridged: Binance sent 14 bid and 8 ask levels in this message; the two highest bids and the three lowest asks are shown.
{"stream": "btcusdt@depth@0ms","data": {"e": "depthUpdate",→ event_type"E": 1791226898196,→ event_time"T": 1791226898194,→ transaction_time"s": "BTCUSDT",→ symbol"ps": "BTCUSDT","U": 11742309239582,→ first_update_id"u": 11742309241602,→ final_update_id"pu": 11742309239523,→ prev_final_update_id"b": [→ side["85547.70", "0.020"],→ side · price · quantity["85580.30", "0.355"]→ side · price · quantity],"a": [→ side["85601.90", "2.784"],→ side · price · quantity["85605.10", "0.001"],→ side · price · quantity["85723.10", "0.000"]→ side · price · quantity],"st": 1}}
Published rows · 5
update for every depthUpdate message.u; a mismatch is a gap.bid for levels in b, ask for levels in a. One row per level.0.000 removes the level.REST depth snapshot
The collector fetches a REST snapshot when it connects and when it has to re-anchor the book after a sequence gap. Only snapshots the collector applied to its book are published, as one snapshot row per level.
Abridged: Requested with limit=5 to keep the example short; the collector requests limit=500.
{"lastUpdateId": 11742279126574,→ final_update_id · last_update_id"E": 1791226529372,→ event_time"T": 1791226529369,→ transaction_time"bids": [→ side["85583.10", "4.900"],→ side · price · quantity["85583.00", "0.016"],→ side · price · quantity["85582.90", "0.002"],→ side · price · quantity["85582.50", "0.001"],→ side · price · quantity["85582.40", "0.002"]→ side · price · quantity],"asks": [→ side["85583.20", "5.022"],→ side · price · quantity["85583.30", "0.003"],→ side · price · quantity["85583.40", "0.060"],→ side · price · quantity["85583.50", "0.006"],→ side · price · quantity["85583.70", "0.002"]→ side · price · quantity]}
Published rows · 10
snapshot for every REST snapshot.first_update_id ≤ this value ≤ final_update_id, or whose prev_final_update_id equals it.bid for levels in bids, ask for levels in asks. One row per level.Notes
- Update rows whose
final_update_idequals a snapshot'slastUpdateIdin the same hour are not published: the snapshot already contains them. - A depth update with no levels becomes one row with
sidenoopandpriceandquantity0. It carries the update IDs and does not change the book. An empty REST snapshot becomes onenoopsnapshotrow: clear the book on it. - Binance can send a removal (quantity
0) for a level that is not in the book. Its documentation says this is normal; ignore it when you replay. - A file can start with a checkpoint: our replayed book at the hour boundary, as
snapshotrows withreceived_timeat the hour start, theevent_timeof the last exchange event before it, nulltransaction_time, and the last applied update ID infinal_update_idandlast_update_id. A checkpoint is written only when the book is proven current. Without one, continue from the previous hour's book or wait for the next snapshot.
Column types and descriptions: Order Book schema.
Ticker
One row per entry of each !ticker@arr frame. Binance includes only the symbols whose statistics changed, at most once per second.
- WebSocket !ticker@arr
Abridged: The all-market frame carried 185 tickers; only BTCUSDT is shown. Each entry becomes its own row.
{"stream": "!ticker@arr","data": [{"e": "24hrTicker","E": 1791226905514,→ event_time"s": "BTCUSDT",→ symbol"ps": "BTCUSDT","p": "283.20",→ price_change"P": "0.332",→ price_change_percent"w": "85961.44",→ weighted_average_price"c": "85583.20",→ last_price"Q": "0.033",→ last_quantity"o": "85300.00",→ open_price"h": "86976.10",→ high_price"l": "84910.00",→ low_price"v": "175409.143",→ base_asset_volume"q": "15078422443.55",→ quote_asset_volume"O": 1791140460000,→ statistics_open_time"C": 1791226905514,→ statistics_close_time"F": 8144678472,→ first_trade_id"L": 8148200173,→ last_trade_id"n": 3507274,→ total_trades"st": 1}]}
Published row
0.332 means +0.332 %.Notes
- A symbol whose statistics did not change gets no row for that second. Carry the last row forward.
- Only symbols listed in USDⓈ-M
exchangeInfoare published. Binance's all-market streams also carry COIN-M contracts (such asBTCUSD_PERP) and delisted symbols; their rows are dropped. Before the 2026-09 data-integrity release they were published.
Column types and descriptions: Ticker schema.
Mark Price
One row per symbol per !markPrice@arr@1s frame, about one per second.
- WebSocket !markPrice@arr@1s
Abridged: The all-market frame carried 745 symbols; only BTCUSDT is shown. Each entry becomes its own row.
{"stream": "!markPrice@arr@1s","data": [{"e": "markPriceUpdate","E": 1791226902000,→ event_time"s": "BTCUSDT",→ symbol"p": "85583.30000000",→ mark_price"ap": "85583.30000000","P": "85612.13024722",→ estimated_settle_price"i": "85633.04043478",→ index_price"r": "0.00000563",→ funding_rate"T": 1791244800000,→ next_funding_time"st": 1}]}
Published row
0.00000563 is 0.000563 %.Notes
- Only symbols listed in USDⓈ-M
exchangeInfoare published. Binance's all-market streams also carry COIN-M contracts (such asBTCUSD_PERP) and delisted symbols; their rows are dropped. Before the 2026-09 data-integrity release they were published.
Column types and descriptions: Mark Price schema.
Open Interest
One row per 5-minute open interest point from REST polling.
- REST GET /futures/data/openInterestHist
Binance's USDⓈ-M WebSocket streams do not include open interest. The collector polls the 5-minute open interest history every 5 minutes. Each point is published once, in the hour of the first poll that returned it.
Abridged: Requested with limit=3 to keep the example short; the collector requests limit=500.
[{"symbol": "BTCUSDT",→ symbol"sumOpenInterest": "95006.41500000",→ sum_open_interest"sumOpenInterestValue": "8130409421.87865450",→ sum_open_interest_value"CMCCirculatingSupply": "20093487.00000000","timestamp": 1791225600000→ timestamp},{"symbol": "BTCUSDT",→ symbol"sumOpenInterest": "94973.61800000",→ sum_open_interest"sumOpenInterestValue": "8127186910.47580000",→ sum_open_interest_value"CMCCirculatingSupply": "20093487.00000000","timestamp": 1791225900000→ timestamp},{"symbol": "BTCUSDT",→ symbol"sumOpenInterest": "94930.31000000",→ sum_open_interest"sumOpenInterestValue": "8122474649.37500000",→ sum_open_interest_value"CMCCirculatingSupply": "20093487.00000000","timestamp": 1791226200000→ timestamp}]
Published rows · 3
Notes
- Each poll returns up to 500 points (about 41 hours). After a pause in polling, points that no earlier hour published appear in the next hour's file, so
timestampcan be hours beforereceived_time.
Column types and descriptions: Open Interest schema.
Liquidations
One row per forceOrder event on the !forceOrder@arr stream.
- WebSocket !forceOrder@arr
{"stream": "!forceOrder@arr","data": {"e": "forceOrder","E": 1791226913155,→ event_time"o": {"s": "RLCUSDT",→ symbol"S": "BUY",→ side"o": "LIMIT",→ order_type"f": "IOC",→ time_in_force"q": "809.3",→ quantity"p": "0.7135",→ price"ap": "0.7048",→ average_price"X": "FILLED",→ order_status"l": "0.8",→ last_filled_quantity"z": "809.3",→ filled_quantity"T": 1791226913110,→ trade_time"ps": "RLCUSDT","st": 1}}}
Published row
BUY closes a liquidated short, SELL a liquidated long.Notes
- Binance pushes at most one liquidation per symbol per 1,000 ms. Rows are a sample, not every liquidation: counts and totals are a lower bound.
- Only symbols listed in USDⓈ-M
exchangeInfoare published. Binance's all-market streams also carry COIN-M contracts (such asBTCUSD_PERP) and delisted symbols; their rows are dropped. Before the 2026-09 data-integrity release they were published.
Column types and descriptions: Liquidations schema.