API de odds ao vivo: odds em tempo real via WebSocket
Uma API de odds ao vivo envia ao seu código a odd de uma casa de apostas no momento em que ela muda. A Odds-API.io transmite odds pré-jogo e ao vivo de 450+ casas de apostas em 34 esportes por uma única conexão WebSocket, com placares ao vivo, status e relógio da partida no mesmo stream.
O streaming via WebSocket é um add-on para qualquer plano pago. O REST está incluído em todos os planos.
- Casas de apostas
- 450+
- Esportes
- 34
- Latência
- <150ms
- Janela de reenvio
- 24h
Por que WebSocket em vez de polling
No polling você pede as odds em intervalos fixos e recebe, na maioria das vezes, dados sem mudança. Um WebSocket fica aberto e só transporta os preços que mudaram, então você vê cada mudança antes e trafega muito menos dados.
| Recurso | Polling REST | WebSocket |
|---|---|---|
| Como as mudanças chegam até você | Você pergunta de novo a cada intervalo | Enviadas assim que um preço muda |
| Latência | Seu intervalo de polling mais a requisição | <150ms |
| Conexões | Uma nova requisição HTTP a cada consulta | Uma conexão que fica aberta |
| Mercados retirados | É preciso reler o evento para perceber | Mensagens explícitas deleted e no_markets |
| Ideal para | Scripts, cargas históricas e consultas rápidas | Apps de apostas ao vivo, modelos in-play e scanners de arbitragem |
Conecte-se em poucas linhas
Abra wss://api.odds-api.io/v3/ws com sua API key e os mercados que você quer. A primeira mensagem é uma boas-vindas que confirma seus filtros e, depois disso, as odds chegam conforme mudam.
// 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())A compressão é obrigatória
Seu cliente precisa oferecer permessage-deflate ao se conectar. Isso reduz a banda de 3 a 5 vezes, e uma conexão sem ela é recusada com HTTP 426. A maioria das bibliotecas cuida disso para você:
| Plataforma | Biblioteca | Compressão |
|---|---|---|
| Node.js | ws | Ativada por padrão |
| Navegador | WebSocket nativo | Ativada por padrão |
| Python | websockets | Ativada por padrão |
| Python | websocket-client | Não suportada, use websockets |
| PHP | amphp/websocket-client | Ativada por padrão (requer zlib) |
| PHP | textalk/websocket | Não suportada, use amphp/websocket-client |
| Go | gorilla/websocket | Defina EnableCompression = true |
| .NET | ClientWebSocket | Defina DangerousDeflateOptions (.NET 6+) |
Tipos de mensagem
Toda mensagem é um objeto JSON com um type. As mensagens de odds usam o mesmo formato do endpoint /v3/odds, então um único parser atende os dois.
created- Uma casa de apostas adicionou um evento que você assina
updated- As odds mudaram. A mensagem traz o conjunto atual completo dos seus mercados para aquele evento e aquela casa
deleted- O evento foi removido ou a casa de apostas ficou fora do ar
no_markets- O evento continua listado, mas nenhum dos seus mercados está aberto
score- O placar ao vivo mudou (canal scores)
status- O evento passou para pendente, ao vivo, liquidado ou cancelado, com o placar atual (canal status)
clock- Um snapshot do relógio da partida a cada 30 segundos, aproximadamente, para cada evento ao vivo com o relógio rodando
Substitua, nunca mescle
Um mercado suspenso fica de fora da próxima mensagem updated, em vez de vir sinalizado. Sobrescreva a cada mensagem o que você tem para aquele evento e aquela casa, e uma odd retirada some do seu app sozinha.
{
"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" }]
}
]
}Canais e filtros
Escolha os streams que você quer com channels e restrinja-os com parâmetros de consulta para receber só os eventos que você exibe. Não é possível combinar leagues e eventIds.
Canais
odds- O padrão.
created,updated,deletedeno_marketspara as casas de apostas selecionadas na sua conta scores- Mensagens
scorea cada mudança de placar, além de snapshotsclock status- Mensagens
statuspara pendente, ao vivo, liquidado e cancelado, além de snapshotsclock
Filtros
markets- Obrigatório para o canal odds. Até 40 nomes de mercado, como
ML,Spread,Totals sport- Até 10 esportes, como
football,basketball leagues- Até 20 slugs de liga, como
england-premier-league eventIds- Até 50 IDs de evento
statuslivesó para ao vivo,prematchsó para pré-jogo
channels é uma lista de permissões. Envie channels=odds,scores,status para manter as odds junto com os placares; só channels=scores,status interrompe as odds.
Reconecte sem lacunas
Redes caem. Toda mensagem de odds traz um número seq, e o feed o usa para colocar você em dia após uma reconexão, em vez de obrigar você a começar do zero.
- 1
Guarde o último seq
Armazene o maior
seqque você recebeu. Os seqs só aumentam dentro de uma conexão, mas são compartilhados por todos os assinantes, então um salto não é uma lacuna. - 2
Reconecte com lastSeq
Adicione
lastSeqà URL de conexão. Você recebe o estado mais recente de cada evento e casa de apostas que mudou enquanto você estava fora, e depois o stream ao vivo continua. - 3
Saiba quando você está ao vivo
Adicione
replayComplete=truepara receber uma mensagemreplay_completequando a atualização terminar. Os dados de reenvio ficam guardados por até 24 horas. - 4
Reconstrua quando solicitado
Se não for possível um reenvio limpo, você recebe
resync_required. Busque um snapshot em/v3/oddscomincludeSeq=truee reconecte com o seq do headerX-OddsAPI-Seq.
Cada API key pode manter duas conexões ao mesmo tempo, por exemplo uma principal e uma de reserva. Mais conexões sob solicitação.
Placares ao vivo e relógio da partida
Odds ao vivo fazem mais sentido ao lado do placar. Assine os canais scores e status na mesma conexão, ou consulte o estado atual via REST.
- GET /v3/events/live
- Todos os eventos em andamento agora, com o placar e um objeto
clock. Filtre por esporte - clock
minute,playedSeconds,period,runningestatusDetail, além dos acréscimos no futebol e de quem saca no tênis- Placares por período
- Tempos, quartos, sets, prorrogação e pênaltis com o mesmo conjunto de chaves para todos os esportes
- Relógio correndo
- Conte a partir de
playedSecondsenquantorunningfor true, e ajuste para o valor do servidor a cada snapshot
REST como alternativa: /odds e /odds/updated
Todo plano inclui a API REST, que entrega as mesmas odds ao vivo. Use-a para snapshots ou faça polling onde um socket não se encaixa.
- GET /v3/odds
- Um snapshot completo de um evento nas casas de apostas que você escolher.
/v3/odds/multiaceita até 10 eventos em uma requisição - GET /v3/odds/updated
- Um delta de verdade: só os mercados que mudaram desde
since, que pode ter no máximo 90 segundos. Passe o header de respostaX-Next-Sincecomosincena próxima chamada para continuar sem lacunas - includeSeq=true
- Adiciona a posição atual do stream como
X-OddsAPI-Seq, para você passar de um snapshot REST para o WebSocket sem perder nenhuma atualização
Um delta não consegue avisar que um mercado foi retirado, então um cliente que faz polling deve reler os eventos com /v3/odds de tempos em tempos. O WebSocket envia deleted e no_markets no lugar disso.
O que o feed de odds ao vivo cobre
- Casas de apostas
- 450+, incluindo Bet365, DraftKings, FanDuel, BetMGM, Betfair Exchange e casas regionais na Europa, Ásia, Austrália e América Latina
- Esportes
- 34, incluindo futebol, basquete, tênis, futebol americano, beisebol, hóquei no gelo, críquete e esports
- Ao vivo
- Odds ao vivo de todas as casas de apostas que oferecem apostas ao vivo, atualizadas aproximadamente a cada segundo
- Mercados
- Moneyline, spreads, totais, handicap asiático, escanteios, cartões e props de jogadores, conforme a casa de apostas
- Latência
- <150ms para as atualizações enviadas via WebSocket
- Formato
- O mesmo JSON de
/v3/odds, via WebSocket e REST
Planos e acesso ao WebSocket
Todo plano pago inclui a API REST com odds ao vivo. O streaming via WebSocket é um add-on que você pode adicionar a qualquer plano.
- O add-on custa o valor do plano de novo, ou seja, 2× o valor do plano no total, mensal ou anual
- O stream traz todas as casas de apostas selecionadas na sua conta, então é o plano que define quantas casas você recebe
- Placar, status e relógio da partida chegam na mesma conexão
- Cancele em qualquer mês
Perguntas frequentes sobre a API de odds ao vivo
O que é uma API de odds ao vivo?
Uma API de odds ao vivo entrega ao seu código as odds atuais dos eventos em andamento, em JSON, e as mantém atualizadas conforme as casas de apostas mexem nos preços. A Odds-API.io transmite odds ao vivo e pré-jogo de 450+ casas de apostas via WebSocket e entrega as mesmas odds via REST.
Quão rápidas são as odds ao vivo?
As atualizações via WebSocket chegam com latência de <150ms, e as odds ao vivo são atualizadas aproximadamente a cada segundo. O polling via REST soma o seu intervalo de consulta, por isso recomendamos WebSocket para apps ao vivo.
O que acontece se minha conexão WebSocket cair?
Reconecte com o parâmetro lastSeq igual ao último seq que você recebeu. O servidor reenvia o estado mais recente de tudo o que mudou enquanto você estava fora, para quedas de até 24 horas, e depois continua ao vivo. Se não for possível um reenvio limpo, ele envia resync_required e você reconstrói a partir de um snapshot REST.
Quais clientes WebSocket posso usar?
Qualquer cliente que suporte a compressão permessage-deflate, que é obrigatória. ws do Node.js, WebSocket do navegador e websockets do Python fazem isso por padrão. websocket-client do Python e textalk/websocket do PHP não suportam e são recusados com HTTP 426. Em Go, ative EnableCompression no gorilla/websocket.
O feed inclui placares ao vivo e o relógio da partida?
Sim. Adicione channels=odds,scores,status à URL de conexão para receber mudanças de placar, mudanças de status e um snapshot do relógio da partida a cada 30 segundos, aproximadamente, junto com as odds. GET /v3/events/live retorna os mesmos placares e relógio via REST.
Como obtenho acesso ao WebSocket?
Escolha um plano pago e adicione o streaming via WebSocket. Ele custa o valor do plano de novo e transmite todas as casas de apostas selecionadas na sua conta, com duas conexões por API key. A API REST, incluindo odds ao vivo e /v3/odds/updated, faz parte de todos os planos.
Receba odds ao vivo hoje
Escolha um plano, adicione o streaming via WebSocket e abra uma única conexão para receber odds ao vivo das 450+ casas de apostas do feed.
Cancele quando quiser · O mesmo JSON via REST e WebSocket