When to use WebSocket vs polling
The simplest rule: use WebSocket for live/in-play events, use polling for pre-match.WebSocket is available on all plans. Free plan: 30 connections/day. Pro plan: not included. Pro+ RT and Pro+ Live: unlimited. Check your plan at oddsstream.io/dashboard.
Prerequisites
- An API key starting with
os_live_(get one here) - Free, Pro+ RT, or Pro+ Live plan (Pro plan does not include WebSocket)
- Node.js 18+ or Python 3.10+ depending on your stack
Step 1: Get a short-lived token
WebSocket connections require a short-lived token (5-minute TTL) rather than your API key directly. This is because:- Browsers cannot set custom headers on WebSocket connections
- The WS server is separate from the API auth gateway — the token is the signed credential that crosses this boundary
- Node.js
- Python
- curl
Step 2: Connect with the token
Pass the token as a?token= query parameter on the WebSocket URL:
- Node.js
- Browser
- Python
Step 3: Filter the stream
Without filters, you receive every odds change across all sports and bookmakers — potentially thousands of messages per minute. Filter at connection time to only receive what you care about. Append filters as additional query parameters after the token:
Combine them freely:
Step 4: Handle messages
Each message is a JSON object representing one selection’s odds changing. One market update (e.g. a moneyline with 3 outcomes) produces 3 separate messages — one per selection.
A simple handler that builds a local price cache:
Step 5: Keepalive
The server drops idle connections after ~5 minutes. Send a"ping" string every 30 seconds. The server responds with "pong".
- Node.js
- Python
Step 6: Reconnect automatically
The server restarts for deployments. Your client must handle disconnects gracefully using exponential backoff — start with a 1-second retry delay and double it up to 30 seconds. Re-fetch the token on every reconnect attempt. Tokens expire after 5 minutes, so the old token may be invalid when you reconnect.- Node.js (production class)
- Python (production)
Complete working example
A minimal but complete app that connects, filters to EPL Football, maintains a live price table, and prints best available odds per selection.- Node.js
- Python
Common errors
403 on token request (websocket_not_on_plan)
403 on token request (websocket_not_on_plan)
Your plan doesn’t include WebSocket streaming. Pro plan does not include WebSocket — upgrade to Pro+ RT or Pro+ Live at oddsstream.io/pricing. The Free plan has a 30 connections/day limit.
429 on token request (rate_limit_exceeded)
429 on token request (rate_limit_exceeded)
Free plan: 30 WS token requests per day. Each connection attempt counts. Implement keepalive (Step 5) to avoid unnecessary reconnects. To remove the limit, upgrade to Pro+ RT or Pro+ Live.
Connection closes immediately (code 4001)
Connection closes immediately (code 4001)
Your token is missing, expired, or invalid. Tokens expire after 5 minutes — always fetch a fresh token immediately before connecting. Never cache and reuse tokens across reconnects.
No messages arriving
No messages arriving
If you connect but receive nothing, your filters may be too narrow. Try removing all filter params to connect unfiltered — if you see messages, your filter value is wrong. Use
GET /api/sports to check valid sport names and GET /api/bookmakers for valid bookmaker names.Messages lag behind / high latency
Messages lag behind / high latency
Normal scrape-to-push latency is 1–3 seconds. Higher latency usually means a bookmaker’s scraper is running slowly. Check
scraped_at in the message — if it’s consistently >30 seconds old, contact support.WebSocket Reference
Full technical spec for the stream endpoint.
Best Practices
Production patterns for reliability and efficiency.