Short answer: Binance WebSocket means two separate products: WebSocket Streams push market data from wss://stream.binance.com, while the WebSocket API at wss://ws-api.binance.com:443/ws-api/v3 answers requests, including orders. On both, as the Spot documentation read on 4 November 2026 states, a connection lasts at most 24 hours, the server pings every 20 seconds and disconnects without a pong within a minute, and connection attempts are limited to 300 every 5 minutes per IP. Reconnecting is therefore routine, not an edge case.
Searches for the Binance WebSocket documentation often mix up two products with similar names, and older tutorials may describe methods that no longer work. This guide separates them, then covers the limits and the reconnect logic that production code needs. Facts come from the official Spot documentation, whose changelog was last updated on 30 October 2026, read on 4 November 2026. The Python samples ran that day against the public Spot Testnet, without keys.
This is a technical guide, not a recommendation to use Binance or any strategy, and automated trading can lose money. Availability depends on your jurisdiction and the platform's terms. In Turkey, Article 99/A of Capital Markets Law No. 6362 treats activity by foreign-based crypto-asset platforms directed at Turkish residents as unauthorized service provision, and the Capital Markets Board (SPK) has stated that appearing on its list of operating providers does not mean a firm is authorized.
Binance WebSocket API vs streams: which do you need?
Use WebSocket Streams to receive market data as it changes, and the WebSocket API to send a request and get a reply over an open connection, as you would with REST.
| Aspect | WebSocket Streams | WebSocket API |
|---|---|---|
| Job | Server pushes trades, candles, book updates | Request and response: market data, orders, account queries |
| Base URL | wss://stream.binance.com:9443 or :443 | wss://ws-api.binance.com:443/ws-api/v3 (9443 also works) |
| Testnet | wss://stream.testnet.binance.vision | wss://ws-api.testnet.binance.vision/ws-api/v3 |
| Market data only host | wss://data-stream.binance.vision | None documented |
| Authentication | None for market data | Signature per request, or an Ed25519 session.logon; public methods need none |
| Rate limit | 5 incoming messages per second; 1,024 streams per connection | Request weight per IP, shared with REST |
Many systems use streams for prices and either REST or the WebSocket API for orders. The wider comparison of channels is in crypto exchange API integration.
Binance WebSocket stream: connect and subscribe
You can name streams in the URL or subscribe after connecting; a raw connection delivers bare events and a combined one wraps each event with its stream name.
- Raw:
/ws/btcusdt@trade. - Combined:
/stream?streams=btcusdt@trade/ethusdt@trade. Events arrive as{"stream": name, "data": event}. - Live control: send
{"method": "SUBSCRIBE", "params": ["btcusdt@aggTrade"], "id": 1}. Aresultofnullmeans success. - Symbols are lowercase in stream names, unlike REST.
Common names include @trade, @aggTrade, @kline_1m, @bookTicker and @depth. Using a diff depth stream correctly takes a snapshot and sequence checks, which the local order book guide covers. On the testnet on 4 November 2026, both /ws and /stream accepted a SUBSCRIBE and delivered bare and wrapped events respectively.
Binance WebSocket limits
The limits that matter are incoming messages per second, streams per connection, connection attempts and connection lifetime, and they differ between Spot and USD-M futures.
| Limit | Spot streams | Spot WebSocket API | USD-M streams |
|---|---|---|---|
| Connection lifetime | 24 hours | 24 hours | 24 hours |
| Server ping | Every 20 seconds | Every 20 seconds | Every 3 minutes |
| Disconnect with no pong within | 1 minute | 1 minute | 10 minutes |
| Incoming messages | 5 per second | Weight per IP | 10 per second |
| Streams per connection | 1,024 | Not applicable | 1,024 |
| Connection attempts per IP | 300 every 5 minutes | 300 every 5 minutes | Not stated on that page |
On Spot streams, a PING frame, a PONG frame and a JSON control message each count as an incoming message. Going past 5 per second disconnects you, and IPs that are repeatedly disconnected may be banned.
USD-M also routes by path: /public for high-frequency market data, /market for regular market data and /private for user data, and its documentation says unrouted connections receive only public streams. Production behaved that way in our test on 4 November 2026: an unrouted /ws connection delivered bookTicker but no aggTrade or markPrice event within 12 seconds, while /market/ws delivered aggTrade. The demo host wss://demo-fstream.binance.com delivered all three on an unrouted connection, so a stream that works on demo can stay silent in production. For REST budgets, see the Binance API rate limit guide.
Binance WebSocket ping and pong
Your client must answer each server ping with a pong carrying the same payload, and common WebSocket libraries do this for you as long as the event loop is free to run.
Over 65 seconds on the Spot Testnet stream on 4 November 2026, with debug logging on, pings arrived 20 seconds apart with a millisecond timestamp as payload, and the Python websockets library (version 13.1) answered each immediately with no application code involved. Three consequences follow:
- Do not block the loop. A long synchronous call in an async program delays the pong. Keep the receive loop to parsing and queueing.
- Unsolicited pongs do not keep you connected. Binance allows them on Spot but says they will not prevent disconnection.
- Library keepalive is separate. By default
websocketsalso sends its own ping every 20 seconds and treats a missing reply within 20 seconds as a broken connection, which catches silent network failures.
A quiet symbol is not a dead connection, so do not reconnect on silence alone.
Binance WebSocket reconnect loop in Python
Reconnect without delay on planned closures, back off with jitter on failures, and rotate before the 24-hour mark so that the disconnect happens on your schedule.
Besides the 24-hour limit, the server sends a serverShutdown event before it shuts down, and the changelog announced a stream infrastructure upgrade for 9 July 2026 during which connections could drop. This loop handles those cases:
import asyncio, json, random, time
import websockets
URL = ("wss://stream.testnet.binance.vision/stream"
"?streams=btcusdt@bookTicker/btcusdt@miniTicker")
MAX_LIFE = 23.5 * 3600 # rotate before the 24-hour cut-off
async def consume(url, on_event, max_life):
async with websockets.connect(url) as ws: # answers server pings for you
try:
async with asyncio.timeout(max_life): # Python 3.11+
async for raw in ws:
msg = json.loads(raw)
event = msg["data"] if "data" in msg else msg # unwrap combined streams
if isinstance(event, dict) and event.get("e") == "serverShutdown":
return "serverShutdown"
on_event(event)
except TimeoutError:
return "planned rotation"
return "closed by server"
async def run(url, on_event, max_life=MAX_LIFE, sessions=None):
n = failures = 0
while sessions is None or n < sessions:
n += 1
started = time.monotonic()
try:
reason = await consume(url, on_event, max_life)
except (OSError, websockets.WebSocketException) as err:
reason = type(err).__name__
planned = reason in ("planned rotation", "serverShutdown")
stable = time.monotonic() - started > 60
failures = 0 if planned or stable else failures + 1
delay = 0 if planned else min(60, 2 ** failures) * random.uniform(0.5, 1)
print(f"session {n}: {reason}, next connect in {delay:.1f} s")
await asyncio.sleep(delay) # then resync state before trusting it
if __name__ == "__main__":
seen = []
asyncio.run(run(URL, seen.append, max_life=6, sessions=2)) # short test run
print(len(seen), "events")
Output on the testnet on 4 November 2026 (Python 3.11, websockets 13.1), with a 6-second rotation so that the test finishes quickly:
session 1: planned rotation, next connect in 0.0 s
session 2: planned rotation, next connect in 0.0 s
27 events
The failure branches were tested against a local server sending synthetic messages: a serverShutdown event reconnected at once, and refused connections waited 1.2, 3.7 and 7.2 seconds on one run. All-market array streams send lists rather than objects, and the loop accepts those too. Delays double up to 60 seconds, and the random factor stops a fleet from reconnecting in step. At one attempt per second, 300 attempts take 5 minutes, so several restarting processes on one IP can reach the limit. A rotation still leaves a short gap in this version; to close it, open the new connection first and drop the old one once the new one delivers events, discarding duplicates.
What to rebuild after a Binance WebSocket reconnect
A new connection knows nothing about the old one, so everything you subscribed to or derived from it has to be restored before you trust it.
- Subscriptions. Names in the URL come back automatically; live
SUBSCRIBEcalls must be sent again, in batches. - Order books. Discard the local book and resynchronize from a snapshot, as the local order book guide describes.
- Missed data. Events during the gap are gone from the stream. Fetch what you need over REST, keeping weight in mind.
- Session state. A WebSocket API
session.logonand a user data subscription belong to their connection, so repeat both. - Orders. Query open orders and recent fills, because any fill during the gap is news to your program, and place no new orders until this is done.
Hypothetical example. A bot holding 40 streams restarts after a crash. Replaying 40 single SUBSCRIBE messages at once breaks the limit of 5 per second, the connection drops, and the restart loop repeats the burst. Sent as one message with 40 names in params, or as a combined stream URL, the same subscription counts as one message at most.
Binance WebSocket rate limit: requests and replies on the WebSocket API
Each WebSocket API request is a JSON text frame with an id and a method, and each reply reports the current weight, drawn from the same per-IP budget as REST.
import asyncio, json
import websockets
WS_API = "wss://ws-api.testnet.binance.vision/ws-api/v3"
REQUESTS = [{"id": 1, "method": "time"},
{"id": 2, "method": "depth", "params": {"symbol": "BTCUSDT", "limit": 5}},
{"id": 3, "method": "ticker.price", "params": {"symbol": "NOPE"}}]
async def main():
async with websockets.connect(WS_API) as ws:
for request in REQUESTS:
await ws.send(json.dumps(request))
reply = json.loads(await ws.recv())
weight = reply["rateLimits"][0]
print(reply["id"], reply["status"], reply.get("error", {}).get("code"),
f"weight {weight['count']}/{weight['limit']}")
asyncio.run(main())
Output on the testnet on 4 November 2026 (the counts include earlier calls from that IP in the same minute):
1 200 None weight 173/6000
2 200 None weight 178/6000
3 400 -1121 weight 180/6000
The rejected request still used weight, and connecting costs 2 weight, per the documentation. Pass returnRateLimits=false to drop the rateLimits field; you remain limited either way. Going over returns status 429 with a retryAfter value. Be strict about the format too: in a test, an unexpected top-level field returned -1135, and the testnet then closed the connection with code 1008. Error codes are shared with REST; see Binance API error codes.
Signed requests carry apiKey, timestamp and signature in params, computed over parameters sorted by name. Alternatively, session.logon authenticates the connection, for Ed25519 keys only. Signing is covered in the Binance API Python guide.
User data stream and the official Binance WebSocket docs
Account events now arrive through the WebSocket API, so tutorials built on a listenKey for stream.binance.com are out of date.
Per the changelog, the listenKey endpoints stopped being available on 20 February 2026. The current methods are userDataStream.subscribe after a session.logon, and userDataStream.subscribe.signature.
The Binance WebSocket documentation is published on the developer site and in the binance-spot-api-docs repository on GitHub. The pages to bookmark are WebSocket Streams (opens in a new tab), WebSocket API (opens in a new tab), User Data Stream (opens in a new tab) and the changelog (opens in a new tab), which is where changes like these are announced.
Frequently asked questions
What is the difference between the Binance WebSocket API and WebSocket Streams?
Streams push market data to you after you subscribe. The WebSocket API is request and response, like REST over an open connection, and it can place orders and read account data.
How long does a Binance WebSocket connection last?
At most 24 hours, per the Spot and USD-M documentation read on 4 November 2026. On Spot, the server also sends a serverShutdown event when it is about to shut down.
Do I need to send ping messages to Binance?
You need to answer the server's pings with pongs, which libraries such as Python websockets do automatically. Sending unsolicited pongs alone will not prevent disconnection on Spot.
Does a Binance WebSocket stream use request weight?
Not in our test: opening a Spot Testnet market stream and reading events added no weight. WebSocket API connections cost 2 weight, and their requests use the same per-IP budget as REST.
Can I test Binance WebSockets without an account?
Yes for public data. The Spot Testnet stream and WebSocket API hosts serve market data without a key; signed requests need a testnet key.
Sources
- Binance Spot API documentation: WebSocket Streams (opens in a new tab)
- Binance Spot API documentation: WebSocket API (opens in a new tab)
- Binance Spot API documentation: User Data Stream (opens in a new tab)
- Binance Spot API documentation: Market Data Only URLs (opens in a new tab)
- Binance Spot Testnet: General info (hosts and URL table) (opens in a new tab)
- Binance Spot API CHANGELOG (listenKey removal, July 2026 stream upgrade) (opens in a new tab)
- Binance USD-M Futures: WebSocket market streams, Connect (last modified 30 October 2026) (opens in a new tab)
- websockets library documentation: Keepalive and latency (opens in a new tab)
- Capital Markets Law No. 6362, Article 99/A (Turkish, consolidated text) (opens in a new tab)
- SPK: Announcement on crypto-asset service providers, 5 August 2024 (Turkish) (opens in a new tab)
This guide is general information about software and markets, not investment, legal or tax advice. Automated trading can lose money, past or backtested performance does not guarantee future results, and the rules that apply depend on your jurisdiction and your exchange's terms. Sources, checks and corrections: see the editorial policy.