API Quote Live: quote in tempo reale via WebSocket
Una API di quote live invia al tuo codice il prezzo di un bookmaker nel momento in cui cambia. Odds-API.io trasmette quote pre-match e in-play da 450+ bookmaker in 34 sport su un'unica connessione WebSocket, con punteggi live, stato della partita e cronometro sullo stesso stream.
Lo streaming WebSocket è un add-on per qualsiasi piano a pagamento. REST è incluso in ogni piano.
- Bookmaker
- 450+
- Sport
- 34
- Latenza
- <150ms
- Finestra di replay
- 24h
Perché WebSocket invece del polling
Con il polling chiedi le quote a intervalli regolari e ricevi per lo più dati invariati. Un WebSocket resta aperto e trasporta solo i prezzi che si sono mossi, così vedi una variazione prima e trasferisci molti meno dati.
| Caratteristica | Polling REST | WebSocket |
|---|---|---|
| Come ti arrivano le variazioni | Richiedi di nuovo a intervalli regolari | Inviate appena un prezzo cambia |
| Latenza | L'intervallo di polling più la richiesta | <150ms |
| Connessioni | Una nuova richiesta HTTP a ogni polling | Una sola connessione sempre aperta |
| Mercati ritirati | Devi rileggere l'evento per accorgertene | Messaggi espliciti deleted e no_markets |
| Ideale per | Script, backfill e consultazioni rapide | App di scommesse live, modelli in-play e scanner di arbitraggio |
Connettiti in poche righe
Apri wss://api.odds-api.io/v3/ws con la tua API key e i mercati che ti servono. Il primo messaggio è un benvenuto che conferma i filtri, poi le quote arrivano man mano che cambiano.
// npm i ws
import WebSocket from 'ws'
const API = 'https://api.odds-api.io/v3'
const apiKey = process.env.ODDS_API_KEY
const markets = 'ML,Spread,Totals'
const eventIds = '63017989,63017990' // up to 10, for example from GET /v3/events/live
const bookmakers = 'Bet365,Unibet' // the bookmakers selected on your account
const board = new Map()
let lastSeq = 0
let needsRebuild = false
function connect() {
const params = new URLSearchParams({ apiKey, markets, eventIds, channels: 'odds,scores,status' })
if (lastSeq) params.set('lastSeq', String(lastSeq))
const ws = new WebSocket(`wss://api.odds-api.io/v3/ws?${params}`)
ws.on('message', (raw) => {
const msg = JSON.parse(raw)
if (msg.type === 'resync_required') {
needsRebuild = true
return ws.close()
}
if (msg.seq > lastSeq) lastSeq = msg.seq
const key = `${msg.id}:${msg.bookie}`
if (msg.type === 'created' || msg.type === 'updated') board.set(key, msg.markets)
if (msg.type === 'deleted' || msg.type === 'no_markets') board.delete(key)
if (msg.type === 'score') console.log(msg.id, msg.scores.home, msg.scores.away)
})
ws.on('error', (err) => console.error('WebSocket error:', err.message || err.code))
ws.on('close', async () => {
if (needsRebuild) lastSeq = await rebuildFromRest()
setTimeout(connect, 2000)
})
}
// Replay was not possible: reload the subscription from REST and resume from its seq
async function rebuildFromRest() {
for (let attempt = 1; ; attempt++) {
try {
const params = new URLSearchParams({ apiKey, eventIds, bookmakers, markets, includeSeq: 'true' })
const res = await fetch(`${API}/odds/multi?${params}`)
const seq = Number(res.headers.get('X-OddsAPI-Seq'))
if (!res.ok || !(seq > 0)) throw new Error(`snapshot not usable: ${res.status}`)
const events = await res.json()
board.clear()
for (const event of events) {
for (const [bookie, odds] of Object.entries(event.bookmakers)) board.set(`${event.id}:${bookie}`, odds)
}
needsRebuild = false
return seq
} catch (err) {
console.error(`${err.message}, retry ${attempt}`)
await new Promise((resolve) => setTimeout(resolve, Math.min(30000, 1000 * 2 ** attempt)))
}
}
}
connect()# pip install websockets
import asyncio
import json
import os
from urllib.parse import urlencode
import websockets
params = urlencode({
"apiKey": os.environ["ODDS_API_KEY"],
"markets": "ML,Spread,Totals",
"leagues": "england-premier-league",
"status": "live",
})
async def main():
async with websockets.connect(f"wss://api.odds-api.io/v3/ws?{params}") as ws:
async for message in ws:
msg = json.loads(message)
if msg["type"] == "updated":
for market in msg["markets"]:
print(msg["id"], msg["bookie"], market["name"], market["odds"][0])
asyncio.run(main())La compressione è obbligatoria
Il tuo client deve offrire permessage-deflate in fase di connessione. Riduce la banda da 3 a 5 volte, e una connessione senza compressione viene rifiutata con HTTP 426. La maggior parte delle librerie la gestisce in automatico:
| Piattaforma | Libreria | Compressione |
|---|---|---|
| Node.js | ws | Attiva di default |
| Browser | WebSocket nativo | Attiva di default |
| Python | websockets | Attiva di default |
| Python | websocket-client | Non supportata, usa websockets |
| PHP | amphp/websocket-client | Attiva di default (richiede zlib) |
| PHP | textalk/websocket | Non supportata, usa amphp/websocket-client |
| Go | gorilla/websocket | Imposta EnableCompression = true |
| .NET | ClientWebSocket | Imposta DangerousDeflateOptions (.NET 6+) |
Tipi di messaggio
Ogni messaggio è un oggetto JSON con un campo type. I messaggi di quote usano lo stesso formato dell'endpoint /v3/odds, quindi un solo parser li gestisce entrambi.
created- Un bookmaker ha aggiunto un evento a cui sei iscritto
updated- Le quote sono cambiate. Il messaggio contiene l'insieme completo e attuale dei tuoi mercati per quell'evento e quel bookmaker
deleted- L'evento è stato rimosso, oppure il suo bookmaker non è più disponibile
no_markets- L'evento è ancora in lista ma nessuno dei tuoi mercati è aperto
score- Il punteggio live è cambiato (canale scores)
status- L'evento è passato a pending, live, settled o cancelled, con il punteggio attuale (canale status)
clock- Uno snapshot del cronometro circa ogni 30 secondi per ogni evento live con il cronometro in corsa
Sostituisci, non unire mai
Un mercato sospeso viene escluso dal successivo messaggio updated invece di essere segnalato. A ogni messaggio sovrascrivi ciò che hai per quell'evento e quel bookmaker, e un prezzo ritirato sparisce da solo dalla tua app.
{
"type": "updated",
"seq": 482917,
"timestamp": 1723992773,
"id": "63017989",
"bookie": "Bet365",
"markets": [
{
"name": "ML",
"updatedAt": "2026-11-08T15:42:10Z",
"odds": [{ "home": "1.85", "draw": "3.25", "away": "2.10" }]
},
{
"name": "Totals",
"updatedAt": "2026-11-08T15:42:10Z",
"odds": [{ "hdp": 2.5, "over": "1.85", "under": "2.10" }]
}
]
}Canali e filtri
Scegli gli stream che ti servono con channels, poi restringili con i parametri di query per ricevere solo gli eventi che mostri. Non puoi combinare leagues ed eventIds.
Canali
odds- Il predefinito.
created,updated,deletedeno_marketsper i bookmaker selezionati sul tuo account scores- Messaggi
scorea ogni variazione del punteggio, più gli snapshotclock status- Messaggi
statusper pending, live, settled e cancelled, più gli snapshotclock
Filtri
markets- Obbligatorio per il canale odds. Fino a 40 nomi di mercato, ad esempio
ML,Spread,Totals sport- Fino a 10 sport, ad esempio
football,basketball leagues- Fino a 20 slug di campionato, ad esempio
england-premier-league eventIds- Fino a 50 ID evento
statuslivesolo per gli eventi in-play,prematchsolo per il pre-match
channels è una allowlist. Invia channels=odds,scores,status per avere le quote insieme ai punteggi; channels=scores,status da solo interrompe l'invio delle quote.
Riconnettiti senza buchi
Le reti cadono. Ogni messaggio di quote porta un numero seq, e il feed lo usa per aggiornarti dopo una riconnessione invece di farti ricominciare da capo.
- 1
Conserva l'ultimo seq
Salva il
seqpiù alto che hai ricevuto. Su una connessione i seq crescono soltanto, ma sono condivisi da tutti gli iscritti, quindi un salto non indica un buco. - 2
Riconnettiti con lastSeq
Aggiungi
lastSeqall'URL di connessione. Ricevi lo stato più recente di ogni evento e bookmaker cambiato mentre eri disconnesso, poi lo stream live riprende. - 3
Sappi quando sei live
Aggiungi
replayComplete=trueper ricevere un messaggioreplay_completequando il recupero è terminato. I dati di replay vengono conservati fino a 24 ore. - 4
Ricostruisci se richiesto
Se un replay pulito non è possibile ricevi
resync_required. Scarica uno snapshot da/v3/oddsconincludeSeq=truee riconnettiti con il seq dell'headerX-OddsAPI-Seq.
Ogni API key può tenere aperte due connessioni contemporaneamente, ad esempio una primaria e una di riserva. Altre sono disponibili su richiesta.
Punteggi live e cronometro
Le quote in-play hanno più senso accanto al punteggio. Iscriviti ai canali scores e status sulla stessa connessione, oppure leggi lo stato attuale via REST.
- GET /v3/events/live
- Tutti gli eventi in corso in questo momento, con il punteggio e un oggetto
clock. Filtrabile per sport - clock
minute,playedSeconds,period,runningestatusDetail, più il recupero nel calcio e il giocatore al servizio nel tennis- Punteggi per periodo
- Tempi, quarti, set, supplementari e rigori con un unico set di chiavi per ogni sport
- Cronometro in tempo reale
- Conta in avanti da
playedSecondsfinchérunningè true, e riallinea al valore del server a ogni snapshot
Fallback REST: /odds e /odds/updated
Ogni piano include l'API REST, che serve le stesse quote live. Usala per gli snapshot, o fai polling dove un socket non è adatto.
- GET /v3/odds
- Uno snapshot completo di un evento dai bookmaker che scegli.
/v3/odds/multiaccetta fino a 10 eventi in una richiesta - GET /v3/odds/updated
- Un vero delta: solo i mercati cambiati da
since, che può risalire al massimo a 90 secondi prima. Passa l'header di rispostaX-Next-Sincecomesincealla chiamata successiva per proseguire senza buchi - includeSeq=true
- Aggiunge la posizione attuale dello stream come
X-OddsAPI-Seq, così puoi passare da uno snapshot REST al WebSocket senza perdere un aggiornamento
Un delta non può dirti che un mercato è stato ritirato, quindi un client in polling dovrebbe rileggere periodicamente gli eventi con /v3/odds. Il WebSocket invece invia deleted e no_markets.
Cosa copre il feed di quote live
- Bookmaker
- 450+, tra cui Bet365, DraftKings, FanDuel, BetMGM, Betfair Exchange e bookmaker regionali in Europa, Asia, Australia e America Latina
- Sport
- 34, tra cui calcio, basket, tennis, football americano, baseball, hockey su ghiaccio, cricket ed esport
- In-play
- Quote live da ogni bookmaker che quota in-play, aggiornate circa ogni secondo
- Mercati
- Moneyline, spread, over/under, handicap asiatico, calci d'angolo, cartellini e player props, a seconda del bookmaker
- Latenza
- <150ms per gli aggiornamenti inviati via WebSocket
- Formato
- Lo stesso JSON di
/v3/odds, via WebSocket e REST
Piani e accesso WebSocket
Ogni piano a pagamento include l'API REST con le quote live. Lo streaming WebSocket è un add-on che puoi aggiungere a qualsiasi piano.
- L'add-on costa quanto il piano, quindi in totale 2× il prezzo del piano, mensile o annuale
- Lo stream include tutti i bookmaker selezionati sul tuo account, quindi è il piano a decidere quanti bookmaker ricevi
- Punteggi, stato e cronometro arrivano sulla stessa connessione
- Disdici in qualsiasi mese
FAQ sull'API quote live
Che cos'è una API di quote live?
Una API di quote live fornisce al tuo codice le quote attuali degli eventi in corso, in formato JSON, e le mantiene aggiornate mentre i bookmaker muovono i prezzi. Odds-API.io trasmette quote live e pre-match da 450+ bookmaker via WebSocket e serve le stesse quote via REST.
Quanto sono veloci le quote live?
Gli aggiornamenti WebSocket arrivano con una latenza <150ms, e le quote in-play si aggiornano circa ogni secondo. Il polling REST aggiunge il tuo intervallo di polling, ed è per questo che consigliamo WebSocket per le app in-play.
Cosa succede se la mia connessione WebSocket cade?
Riconnettiti con il parametro lastSeq impostato sull'ultimo seq ricevuto. Il server ti reinvia lo stato più recente di tutto ciò che è cambiato mentre eri disconnesso, per interruzioni fino a 24 ore, poi prosegue in live. Se un replay pulito non è possibile invia resync_required, e ricostruisci lo stato da uno snapshot REST.
Quali client WebSocket posso usare?
Qualsiasi client che supporti la compressione permessage-deflate, che è obbligatoria. ws per Node.js, WebSocket nel browser e websockets per Python la usano di default. websocket-client per Python e textalk/websocket per PHP non la supportano e vengono rifiutati con HTTP 426. In Go, attiva EnableCompression su gorilla/websocket.
Il feed include punteggi live e cronometro?
Sì. Aggiungi channels=odds,scores,status all'URL di connessione per ricevere, accanto alle quote, le variazioni di punteggio e di stato e uno snapshot del cronometro circa ogni 30 secondi. GET /v3/events/live restituisce gli stessi punteggi e cronometro via REST.
Come ottengo l'accesso WebSocket?
Scegli un piano a pagamento e aggiungi lo streaming WebSocket. Costa quanto il piano e trasmette tutti i bookmaker selezionati sul tuo account, con due connessioni per API key. L'API REST, comprese le quote live e /v3/odds/updated, è inclusa in ogni piano.
Ricevi quote live da oggi
Scegli un piano, aggiungi lo streaming WebSocket e apri una sola connessione per le quote live dei 450+ bookmaker del feed.
Disdici quando vuoi · Lo stesso JSON via REST e WebSocket