WebSockets da Polymarket: dados em tempo real que não caem
Fazer polling do livro de ofertas é a forma mais comum de queimar o orçamento de limite de requisições sem ganhar nada. Veja os quatro streams, as opções de assinatura que ninguém documenta e o modo de falha em que seu bot recebe silêncio e acha que é calmaria.
Se o seu bot faz polling de GET /book com um timer, esta página vai poupar a maior parte do seu orçamento de limite de requisições e um bom pedaço de latência. A Polymarket envia as atualizações do livro por WebSocket, e uma assinatura custa uma conexão em vez de milhares de requisições.
A versão curta
Conecte-se a wss://ws-subscriptions-clob.polymarket.com/ws/market, envie uma assinatura indicando seus assets_ids e depois envie um PING a cada 10 segundos, ou você será desconectado. Defina custom_feature_enabled: true se quiser os eventos best_bid_ask, new_market ou market_resolved — eles vêm desativados por padrão, e a ausência deles parece exatamente um mercado parado.
Os quatro streams
| Stream | URL | Transmite | Autenticação |
|---|---|---|---|
| Market | wss://ws-subscriptions-clob.polymarket.com/ws/market | Atualizações públicas do livro, de preço e de ciclo de vida | Nenhuma |
| User | wss://ws-subscriptions-clob.polymarket.com/ws/user | Atualizações das suas ordens e negociações | Sim |
| RTDS (legado) | wss://ws-live-data.polymarket.com | Comentários — os preços de referência foram para o PolyBolt | Nenhuma |
| PolyBolt | wss://ws-live-v2.polymarket.com/ws | Preços de referência de cripto, ações e TWAP | Sim |
| Sports | wss://sports-api.polymarket.com/ws | Status e placares de jogos ao vivo | Nenhuma |
O canal User é o que as pessoas esquecem
Se o seu bot faz polling de /data/orders para descobrir se a ordem foi executada, você está gastando orçamento de limite de requisições com informação que o canal User envia no instante em que acontece — e com menor latência. Qualquer bot que envia ordens deveria estar neste stream.
Os preços de referência mudaram em 15 de setembro de 2026
A Polymarket lançou o PolyBolt e transformou o RTDS em legado para preços de referência. crypto_prices, crypto_prices_chainlink e equity_prices agora ficam em wss://ws-live-v2.polymarket.com/ws, a fonte mudou de Binance/Chainlink para a Pyth, os símbolos são btcusd em minúsculas em vez de btcusdt ou btc/usd, e agora é preciso autenticação. O mapeamento completo está no guia de migração para o PolyBolt. Todo o resto desta página — os canais market e user do CLOB — não foi afetado.
Assinando o canal market
Conecte-se e envie uma mensagem JSON de assinatura. assets_ids recebe IDs de tokens — os mesmos que você obtém dos metadados do mercado — e type precisa ser "market".
{
"assets_ids": ["65818619657568813474341868652308942079804919287380422192892211131408793125422"],
"type": "market",
"initial_dump": true,
"level": 2,
"custom_feature_enabled": true
}| Campo | Obrigatório | Padrão | O que faz |
|---|---|---|---|
assets_ids | Sim | — | IDs dos tokens a assinar |
type | Sim | — | Precisa ser "market" |
initial_dump | Não | true | Envia um snapshot completo do livro ao assinar |
level | Não | 2 | Nível da assinatura — 1, 2 ou 3 |
custom_feature_enabled | Não | false | Ativa os eventos best_bid_ask, new_market e market_resolved |
custom_feature_enabled vem como false por padrão
Esta é a pegadinha da assinatura que custa uma tarde às pessoas. Três tipos de evento — best_bid_ask, new_market e market_resolved — não são entregues a menos que você os ative. Não há erro nem aviso; você simplesmente nunca os recebe. Se você está esperando um evento market_resolved que nunca chega, é por isso.
Mantenha initial_dump: true, a menos que tenha um motivo específico para não fazer isso. Sem ele, você começa sem nenhum estado do livro e precisa esperar as atualizações incrementais para reconstruí-lo, o que significa que seu bot começa a vida com uma visão incompleta.
Tipos de mensagem
Toda mensagem traz um event_type. Trate todos os casos — um tipo desconhecido deve ser registrado em log, não descartado em silêncio, porque é assim que você descobre que o protocolo mudou.
event_type | Significado | Precisa ativar |
|---|---|---|
book | Snapshot completo do livro de ofertas | Não |
price_change | Atualização incremental de preço/nível | Não |
last_trade_price | Uma negociação foi executada | Não |
tick_size_change | A grade de ticks do mercado mudou | Não |
best_bid_ask | Atualização do topo do livro | Sim |
new_market | Um mercado foi criado | Sim |
market_resolved | Um mercado foi liquidado | Sim |
Não ignore tick_size_change
O tick size é definido por mercado e pode ficar menor à medida que o mercado amadurece. Se você guarda o tick size em cache na inicialização e o mercado o altera, todas as ordens limitadas seguintes são rejeitadas por violação do tick size mínimo — um 400 que parece um bug na sua lógica de preços. Trate o evento e atualize seu cache.
Mantendo a conexão: PING a cada 10 segundos
Esta é a exigência que pega todo mundo. O cliente precisa enviar um PING a cada 10 segundos; o servidor responde PONG. Perca o heartbeat e a conexão cai.
Repare na direção: é um heartbeat do cliente. Você não está esperando o servidor mandar ping para você. O keepalive embutido de uma biblioteca WebSocket em outro intervalo não substitui isso — envie você mesmo o PING no nível da aplicação.
import asyncio, json, time
import websockets
URL = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
STALE_AFTER = 30 # seconds without any message = treat as dead
async def stream(token_ids, on_event):
backoff = 1
while True:
try:
async with websockets.connect(URL) as ws:
await ws.send(json.dumps({
"assets_ids": token_ids,
"type": "market",
"initial_dump": True,
"custom_feature_enabled": True, # or lose 3 event types
}))
backoff = 1 # reconnected cleanly
last_msg = time.monotonic()
async def heartbeat():
while True:
await asyncio.sleep(10) # required cadence
await ws.send("PING")
hb = asyncio.create_task(heartbeat())
try:
while True:
# Silence is a failure mode, not a quiet market.
raw = await asyncio.wait_for(ws.recv(), timeout=STALE_AFTER)
last_msg = time.monotonic()
if raw == "PONG":
continue
for msg in json.loads(raw) if raw.startswith("[") else [json.loads(raw)]:
on_event(msg)
finally:
hb.cancel()
except Exception as exc:
# Reconnect with capped exponential backoff + jitter.
wait = min(backoff, 30) * (0.5 + 0.5 * asyncio.get_event_loop().time() % 1)
print(f"ws down ({exc}); reconnecting in {wait:.1f}s")
await asyncio.sleep(wait)
backoff = min(backoff * 2, 30)Use o SDK, a menos que tenha um motivo para não usar
O polymarket-client (Python) e o @polymarket/client (TypeScript) implementam o heartbeat, a reconexão e os frames das mensagens, e juntam vários feeds em um único stream de eventos tipados. Fazer tudo à mão só vale a pena se você precisar de um controle que o SDK não expõe. Note que as assinaturas são só assíncronas — os clientes síncronos não implementam subscribe().
Mudando as assinaturas sem reconectar
Mercados de cinco minutos vencem o tempo todo, então um bot que acompanha os “mercados BTC 5m atuais” precisa mudar o conjunto de assinaturas continuamente. Você não precisa derrubar a conexão para isso — o canal market aceita assinar e cancelar assinaturas em uma conexão ativa.
Isso importa mais do que parece. Reconectar a cada rotação de mercado significa pagar repetidamente o custo de abrir a conexão, pedir de novo os initial dumps e criar uma janela em que você não recebe nada justamente no momento em que um novo mercado abre.
O modo de falha que custa dinheiro
Um WebSocket que caiu não lança exceção. Ele para de entregar mensagens. Para um bot ingênuo, “nenhuma atualização” é indistinguível de “o mercado não está se mexendo” — então um bot com uma posição aberta vai ficar parado em um preço defasado indefinidamente, certo de que nada mudou.
- Acompanhe a idade da última mensagem. Se nada chegou em ~30 segundos em um mercado ativo, você está desconectado, não em calmaria. O timeout de
asyncio.wait_foracima faz exatamente esse trabalho. - Trate a defasagem como condição de erro. Pare de cotar, zere a posição se as suas regras de risco exigirem e reconecte — não continue operando com um livro congelado.
- Use backoff na reconexão, com jitter. Um loop de reconexão apertado durante uma queda é o jeito de ser limitado por taxa além de desconectado, e uma frota reconectando em sincronia piora tudo.
- Ressincronize o estado depois de reconectar. Você perdeu atualizações enquanto esteve fora. Tome o novo
initial_dumpcomo verdade e descarte seu livro anterior, em vez de juntar atualizações incrementais a um snapshot defasado. - Reconcilie as posições depois de qualquer lacuna. Se você ficou desconectado do canal User, pode ter perdido uma execução. Leia as posições de novo antes de agir com base em um estado presumido.
WebSockets e limites de requisições
Uma pergunta frequente, e a resposta é o objetivo de todo o exercício: uma assinatura não consome o orçamento de limite por requisição como o polling consome. Os limites documentados da Polymarket são limites HTTP por endpoint, e o streaming os contorna quase por completo.
| Abordagem | Custo de acompanhar 20 mercados por uma hora |
|---|---|
Polling de /book a cada segundo | 72,000 requisições contra um orçamento de 1,500 req/10s |
Polling de /books (lote) a cada segundo | 3,600 requisições contra um orçamento de 500 req/10s |
| Assinatura WebSocket | Uma conexão, mais 360 heartbeats |
Você ainda vai fazer chamadas HTTP — descoberta de mercados, tick sizes, envio de ordens, reconciliação de posições — e elas continuam sujeitas aos limites de requisições documentados. O streaming só elimina a maior e menos útil fonte de volume de requisições.
Latência é limitação disfarçada
Como a camada da Cloudflare limita atrasando em vez de rejeitar, um bot de polling acima do limite não vê 429 — ele vê seus tempos de resposta subirem em silêncio. Se os seus dados do livro passaram de 40ms para 3 segundos, você não está passando por uma queda; está passando pela sua própria taxa de requisições.
O que os streams não vão dar a você
Um limite que vale dizer com clareza, porque é a próxima coisa que as pessoas tentam. Um WebSocket dá a você o livro a partir do momento em que você assina. Ele não consegue dar o livro da última terça-feira.
A Polymarket não guarda livro de ofertas histórico. Depois que um mercado é resolvido, o livro dele retorna 404, e prices-history guarda só cerca de um ponto por minuto. Se você quer testar uma estratégia contra como os mercados realmente foram negociados, precisa de snapshots que alguém gravou na hora. A PolyTest faz isso para os mercados cripto Up/Down, com 8 níveis de profundidade por lado e mercados resolvidos mantidos. Ou comece hoje o seu próprio coletor, aceite que você parte de zero histórico e espere.
Perguntas frequentes
- Qual é a URL do WebSocket da Polymarket?
- O canal público market é wss://ws-subscriptions-clob.polymarket.com/ws/market e o canal autenticado user é wss://ws-subscriptions-clob.polymarket.com/ws/user. Há também dois outros streams: o RTDS em wss://ws-live-data.polymarket.com para preços de referência, comentários e atividade de negociação, e um feed de esportes em wss://sports-api.polymarket.com/ws.
- Existe limite de requisições no WebSocket da Polymarket?
- Uma assinatura WebSocket não consome o orçamento de limite por requisição como o polling HTTP consome — os limites documentados da Polymarket são limites HTTP por endpoint. O streaming é justamente a forma recomendada de evitá-los. A exigência que vale para uma conexão é o heartbeat: envie um PING a cada 10 segundos, ou a conexão cai. As chamadas HTTP que você ainda faz para descoberta, tick sizes e envio de ordens continuam sujeitas aos limites normais.
- Como mantenho viva uma conexão WebSocket da Polymarket?
- Envie uma mensagem PING a cada 10 segundos; o servidor responde com PONG. Esse é um heartbeat no nível da aplicação, do lado do cliente, então o keepalive embutido de uma biblioteca WebSocket em outro intervalo não o substitui. Acompanhe também a idade da última mensagem recebida — uma conexão caída para de entregar dados sem gerar erro, então trate cerca de 30 segundos de silêncio em um mercado ativo como uma desconexão, e não como um mercado parado.
- Por que não recebo eventos best_bid_ask ou market_resolved?
- Esses eventos vêm desativados por padrão. Defina custom_feature_enabled como true na sua mensagem de assinatura para ativar best_bid_ask, new_market e market_resolved. Não há erro nem aviso quando a flag está ausente — os eventos simplesmente nunca chegam, o que é fácil de confundir com um mercado inativo.
- Meu bot da Polymarket deve usar WebSockets ou fazer polling da API REST?
- Use WebSockets para dados ao vivo do livro e de preços. Acompanhar 20 mercados com polling de /book uma vez por segundo custa 72,000 requisições por hora contra um orçamento de 1,500 req/10s, enquanto uma assinatura custa uma conexão mais os heartbeats — e o polling ainda devolve uma resposta mais defasada, já que você vê o livro como estava no último polling e não na última mudança. Use REST para descoberta de mercados, tick sizes, envio de ordens e reconciliação de posições.
- Posso mudar os mercados que assino sem reconectar?
- Sim. O canal market aceita assinar e cancelar assinaturas de ativos em uma conexão ativa, o que importa para mercados de vida curta, como os contratos Up/Down de 5 minutos, que mudam o tempo todo. Reconectar a cada rotação paga repetidamente o custo de abrir a conexão e deixa uma lacuna na cobertura justamente no momento em que um novo mercado abre.
Tenha os dados históricos que a Polymarket não guarda
A PolyTest registra os mercados cripto Up/Down da Polymarket enquanto estão ativos — mais de 240M de snapshots com 8 níveis de profundidade do livro de ofertas, timestamps abaixo de um segundo e mercados resolvidos preservados. Comece com um teste grátis de 3 dias.
Continue lendo
A Polymarket substituiu o RTDS: migrando para o PolyBolt
Em 15 de setembro, a Polymarket transformou discretamente o RTDS em legado para preços de referência. Se você faz streaming de spot para um bot, seis coisas mudaram de uma vez — incluindo a fonte de preços e o formato dos símbolos — e a maioria delas falha em silêncio, não com alarde.
Como criar um bot de trading para a Polymarket
A maioria dos tutoriais de bots para a Polymarket usa SDKs que não existem mais. Este é o caminho atual de ponta a ponta — o que instalar em 2026, como a autenticação realmente funciona, onde estão as lacunas de dados e os modos de falha que matam bots na primeira semana.
Limites de requisições da API da Polymarket: a referência completa
A Polymarket publica seus limites de requisições em várias páginas, em dois sistemas completamente diferentes, usando uma janela de 10 segundos que quase ninguém espera. Aqui está tudo em um só conjunto de tabelas — mais o que realmente acontece quando você passa de um limite.
O SDK Python da Polymarket em 2026 (e como sair do py-clob-client)
Se o seu código ainda importa ClobClient de py_clob_client, ele está construído sobre um pacote substituído — assim como a maior parte do código da Polymarket que um assistente de IA vai escrever para você. Veja o SDK atual e como migrar.