Todos os posts
Referência da APIWebSocketsAPI da PolymarketBots de trading

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.

10 min de leituraAtualizado em 24 de setembro de 2026

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

StreamURLTransmiteAutenticação
Marketwss://ws-subscriptions-clob.polymarket.com/ws/marketAtualizações públicas do livro, de preço e de ciclo de vidaNenhuma
Userwss://ws-subscriptions-clob.polymarket.com/ws/userAtualizações das suas ordens e negociaçõesSim
RTDS (legado)wss://ws-live-data.polymarket.comComentários — os preços de referência foram para o PolyBoltNenhuma
PolyBoltwss://ws-live-v2.polymarket.com/wsPreços de referência de cripto, ações e TWAPSim
Sportswss://sports-api.polymarket.com/wsStatus e placares de jogos ao vivoNenhuma

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
}
CampoObrigatórioPadrãoO que faz
assets_idsSim—IDs dos tokens a assinar
typeSim—Precisa ser "market"
initial_dumpNãotrueEnvia um snapshot completo do livro ao assinar
levelNão2Nível da assinatura — 1, 2 ou 3
custom_feature_enabledNãofalseAtiva 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_typeSignificadoPrecisa ativar
bookSnapshot completo do livro de ofertasNão
price_changeAtualização incremental de preço/nívelNão
last_trade_priceUma negociação foi executadaNão
tick_size_changeA grade de ticks do mercado mudouNão
best_bid_askAtualização do topo do livroSim
new_marketUm mercado foi criadoSim
market_resolvedUm mercado foi liquidadoSim

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_for acima 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_dump como 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.

AbordagemCusto de acompanhar 20 mercados por uma hora
Polling de /book a cada segundo72,000 requisições contra um orçamento de 1,500 req/10s
Polling de /books (lote) a cada segundo3,600 requisições contra um orçamento de 500 req/10s
Assinatura WebSocketUma conexão, mais 360 heartbeats
O polling também dá uma resposta pior: você vê o livro como estava no seu último polling, não como estava na última mudança.

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