Skip to main content
This walks the full path: connect, subscribe to a market’s BOOK channel, apply the initial snapshot, then keep it current with delta frames. The client handles the handshake, keepalive, and reconnect for you, so you just handle frames.
subscribe takes an array of markets, so you can open many subscriptions in one call. Each market is a MarketStream, a discriminated union on venue (POLYMARKET needs only a tokenId; KALSHI addresses a book by ticker; LIMITLESS also needs kind and marketId). See the WebSocket API’s Subscriptions & markets for the market shapes and Orderbook channel for price/size units and the gap-free seq guarantee. In Python you can pass a plain dict, as above, or the typed model:
The tokenId above is illustrative. Subscribing to a market that is not live connects and acks the subscription, then delivers no snapshot, which looks like a broken client rather than a stale identifier. Take a real one from discovery (listEventMarkets / list_event_markets, then an outcome’s listings) or from lookupMarket / lookup_market. A Polymarket token id is a decimal string of roughly 77 digits.

Confirming and closing

The server acks each subscription with a SUBSCRIBED frame carrying the subscriptionId that keys every subsequent frame. Capture it if you want to unsubscribe later, and close the client when you’re done.
subscribe and unsubscribe are safe to call before the socket is open, because the client replays your active subscriptions automatically on connect (and on every reconnect). See Events for the full frame set and Reconnection & lifecycle for what happens across disconnects. In Python, subscribe, unsubscribe, list, ping and close are all coroutines, so each one is awaited. Leaving the async with block calls close for you; call it yourself if you hold a client for the life of the process.

Client options

Besides the credentials (see Authentication), each client takes a few optional settings.
baseUrl and base_url default to production. In TypeScript, WebSocket defaults to the runtime’s global, which Node.js provides from 22 onward, so you only pass it on Node 20 or 21 or to supply a custom implementation. In Python, connection lifecycle is reported through the three callbacks rather than as frames, because those events describe the connection rather than the market. See Reconnection & lifecycle.