Tutti gli articoli
Riferimento APIWebSocketAPI di PolymarketBot di trading

WebSocket di Polymarket: dati in tempo reale che non cadono

Fare polling dell’order book è il modo più comune di bruciare un budget di rate limit senza alcun beneficio. Ecco i quattro stream, le opzioni di sottoscrizione che nessuno documenta e il guasto in cui il tuo bot riceve silenzio e lo scambia per calma.

10 min di letturaAggiornato il 24 settembre 2026

Se il tuo bot fa polling di GET /book a intervalli regolari, questa pagina ti farà risparmiare gran parte del budget di rate limit e un bel po’ di latenza. Polymarket invia gli aggiornamenti del book via WebSocket, e una sottoscrizione ti costa una connessione invece di migliaia di richieste.

La versione breve

Connettiti a wss://ws-subscriptions-clob.polymarket.com/ws/market, invia una sottoscrizione con i tuoi assets_ids, poi invia un PING ogni 10 secondi o verrai disconnesso. Imposta custom_feature_enabled: true se vuoi gli eventi best_bid_ask, new_market o market_resolved: sono disattivati per impostazione predefinita e la loro assenza sembra esattamente un mercato tranquillo.

I quattro stream

StreamURLTrasportaAutenticazione
Marketwss://ws-subscriptions-clob.polymarket.com/ws/marketAggiornamenti pubblici di book, prezzi e ciclo di vitaNessuna
Userwss://ws-subscriptions-clob.polymarket.com/ws/userAggiornamenti dei tuoi ordini e tradeSì
RTDS (legacy)wss://ws-live-data.polymarket.comCommenti; i prezzi di riferimento sono passati a PolyBoltNessuna
PolyBoltwss://ws-live-v2.polymarket.com/wsPrezzi di riferimento di crypto, equity e TWAPSì
Sportswss://sports-api.polymarket.com/wsStato e punteggi delle partite in direttaNessuna

Il canale User è quello che molti trascurano

Se il tuo bot fa polling di /data/orders per sapere se il suo ordine è stato eseguito, stai spendendo budget di rate limit per un’informazione che il canale User ti invia nell’istante in cui accade, e con meno latenza. Qualsiasi bot che piazza ordini dovrebbe essere su questo stream.

I prezzi di riferimento si sono spostati il 15 settembre 2026

Polymarket ha rilasciato PolyBolt e ha reso RTDS legacy per i prezzi di riferimento. crypto_prices, crypto_prices_chainlink ed equity_prices ora si trovano su wss://ws-live-v2.polymarket.com/ws, la fonte è passata da Binance/Chainlink a Pyth, i simboli sono in minuscolo btcusd invece di btcusdt o btc/usd, e ora è richiesta l’autenticazione. La mappatura completa è nella guida alla migrazione a PolyBolt. Tutto il resto di questa pagina, cioè i canali market e user del CLOB, non è toccato.

Sottoscriversi al canale market

Connettiti, poi invia un messaggio di sottoscrizione JSON. assets_ids accetta token ID (gli stessi che ottieni dai metadati del mercato) e type deve essere "market".

{
  "assets_ids": ["65818619657568813474341868652308942079804919287380422192892211131408793125422"],
  "type": "market",
  "initial_dump": true,
  "level": 2,
  "custom_feature_enabled": true
}
CampoObbligatorioPredefinitoCosa fa
assets_idsSì—Token ID a cui sottoscriversi
typeSì—Deve essere "market"
initial_dumpNotrueInvia uno snapshot completo del book alla sottoscrizione
levelNo2Livello di sottoscrizione: 1, 2 o 3
custom_feature_enabledNofalseAbilita gli eventi best_bid_ask, new_market e market_resolved

custom_feature_enabled è false per impostazione predefinita

È il tranello della sottoscrizione che costa un pomeriggio a molti. Tre tipi di evento (best_bid_ask, new_market e market_resolved) non vengono consegnati a meno che tu non li attivi. Nessun errore e nessun avviso; semplicemente non li ricevi mai. Se stai aspettando un evento market_resolved che non arriva mai, il motivo è questo.

Mantieni initial_dump: true a meno che tu non abbia un motivo specifico per non farlo. Senza, parti senza alcuno stato del book e devi aspettare gli aggiornamenti incrementali per ricostruirlo, il che significa che il tuo bot inizia la sua vita con un quadro incompleto.

Tipi di messaggio

Ogni messaggio ha un event_type. Gestiscili tutti in modo esaustivo: un tipo non riconosciuto va registrato nei log, non scartato in silenzio, perché è così che scopri che il protocollo è cambiato.

event_typeSignificatoRichiede attivazione
bookSnapshot completo dell’order bookNo
price_changeAggiornamento incrementale di prezzo/livelloNo
last_trade_priceÈ stato eseguito un tradeNo
tick_size_changeLa griglia dei tick del mercato è cambiataNo
best_bid_askAggiornamento del top of bookSì
new_marketÈ stato creato un mercatoSì
market_resolvedUn mercato si è regolatoSì

Non ignorare tick_size_change

La dimensione del tick è per mercato e può restringersi man mano che un mercato matura. Se metti in cache una dimensione del tick all’avvio e il mercato la cambia, ogni ordine limite successivo viene rifiutato per violazione della dimensione minima del tick: un 400 che sembra un bug nella tua logica di prezzo. Gestisci l’evento e aggiorna la cache.

Restare connessi: PING ogni 10 secondi

È il requisito che coglie tutti impreparati. Il client deve inviare un PING ogni 10 secondi; il server risponde PONG. Salta l’heartbeat e la connessione viene chiusa.

Nota la direzione: è un heartbeat del client. Non stai aspettando che sia il server a mandarti un ping. Il keepalive WebSocket integrato in una libreria, a un altro intervallo, non lo sostituisce: invia tu il PING a livello applicativo.

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)

Usa l’SDK, a meno che tu non abbia un motivo per non farlo

polymarket-client (Python) e @polymarket/client (TypeScript) implementano heartbeat, riconnessione e framing dei messaggi, e uniscono più feed in un unico stream di eventi tipizzati. Scriverlo a mano conviene solo se ti serve un controllo che l’SDK non espone. Nota che le sottoscrizioni sono solo async: i client sincroni non implementano subscribe().

Cambiare le sottoscrizioni senza riconnettersi

I mercati a cinque minuti scadono di continuo, quindi un bot che segue i "mercati BTC 5m correnti" deve cambiare continuamente il suo insieme di sottoscrizioni. Non devi chiudere la connessione per farlo: il canale market supporta sottoscrizione e annullamento della sottoscrizione su una connessione attiva.

Conta più di quanto sembri. Riconnettersi a ogni rotazione dei mercati significa pagare ripetutamente il costo di apertura della connessione, richiedere di nuovo gli initial dump e creare una finestra in cui non ricevi nulla proprio nel momento in cui si apre un nuovo mercato.

Il guasto che costa soldi

Un WebSocket caduto non genera un’eccezione. Smette di consegnare messaggi. Per un bot ingenuo, "nessun aggiornamento" è indistinguibile da "il mercato non si muove", quindi un bot con una posizione aperta resterà a tempo indeterminato su un prezzo vecchio, convinto che non sia cambiato nulla.

  • Tieni traccia dell’età dell’ultimo messaggio. Se su un mercato attivo non arriva nulla da ~30 secondi, sei disconnesso, non in una fase tranquilla. Il timeout di asyncio.wait_for qui sopra fa esattamente questo lavoro.
  • Tratta i dati vecchi come una condizione di errore. Smetti di quotare, chiudi le posizioni se le tue regole di rischio lo richiedono e riconnettiti: non continuare a fare trading su un book congelato.
  • Usa un backoff con jitter in riconnessione. Un loop di riconnessione stretto durante un disservizio è il modo per farti limitare oltre a essere disconnesso, e una flotta che si riconnette tutta insieme peggiora le cose.
  • Risincronizza lo stato dopo la riconnessione. Mentre eri via hai perso degli aggiornamenti. Prendi il nuovo initial_dump come verità e scarta il book precedente, invece di fondere aggiornamenti incrementali in uno snapshot vecchio.
  • Riconcilia le posizioni dopo ogni interruzione. Se eri disconnesso dal canale User, potresti aver perso un’esecuzione. Rileggi le posizioni prima di agire su uno stato presunto.

WebSocket e rate limit

Una domanda frequente, e la risposta è il senso di tutto l’esercizio: una sottoscrizione non consuma budget di rate limit per richiesta come fa il polling. I limiti documentati di Polymarket sono limiti HTTP per endpoint, e lo streaming li aggira quasi del tutto.

ApproccioCosto per seguire 20 mercati per un’ora
Polling di /book ogni secondo72,000 richieste su un budget di 1,500 req/10s
Polling di /books (batch) ogni secondo3,600 richieste su un budget di 500 req/10s
Sottoscrizione WebSocketUna connessione, più 360 heartbeat
Il polling ti dà anche una risposta peggiore: vedi il book com’era al tuo ultimo polling, non all’ultima modifica.

Continuerai a fare chiamate HTTP (scoperta dei mercati, dimensioni dei tick, invio degli ordini, riconciliazione delle posizioni), e quelle restano soggette ai rate limit documentati. Lo streaming elimina solo la fonte di volume di richieste più grande e meno utile.

La latenza è un rallentamento travestito

Poiché il livello Cloudflare rallenta ritardando invece di rifiutare, un bot che fa polling oltre il limite non vede 429: vede i suoi tempi di risposta salire in silenzio. Se i dati del tuo book sono passati da 40ms a 3 secondi, non stai vivendo un disservizio; stai vivendo la tua stessa frequenza di richieste.

Cosa gli stream non ti daranno

Un confine che vale la pena dichiarare chiaramente, perché è la cosa che la gente prova subito dopo. Un WebSocket ti dà il book dal momento in cui ti sottoscrivi. Non può darti il book di martedì scorso.

Polymarket non conserva alcun order book storico. Una volta che un mercato si risolve, il suo book restituisce 404, e prices-history conserva solo circa un punto al minuto. Se vuoi testare una strategia su come i mercati sono stati davvero scambiati, ti servono snapshot registrati da qualcuno all’epoca. PolyTest lo fa per i mercati crypto Up/Down, con 8 livelli di profondità per lato e i mercati risolti conservati. Oppure avvia oggi il tuo collector, accetta di partire con zero storico e aspetta.

Domande frequenti

Qual è l’URL del WebSocket di Polymarket?
Il canale pubblico market è wss://ws-subscriptions-clob.polymarket.com/ws/market e il canale autenticato user è wss://ws-subscriptions-clob.polymarket.com/ws/user. Ci sono anche altri due stream: RTDS su wss://ws-live-data.polymarket.com per prezzi di riferimento, commenti e attività di trading, e un feed sportivo su wss://sports-api.polymarket.com/ws.
C’è un rate limit sul WebSocket di Polymarket?
Una sottoscrizione WebSocket non consuma budget di rate limit per richiesta come fa il polling HTTP: i limiti documentati di Polymarket sono limiti HTTP per endpoint. Lo streaming è proprio il modo consigliato per evitarli. Il requisito vincolante su una connessione è l’heartbeat: invia un PING ogni 10 secondi o la connessione viene chiusa. Le chiamate HTTP che fai comunque per scoperta dei mercati, dimensioni dei tick e invio degli ordini restano soggette ai limiti normali.
Come mantengo attiva una connessione WebSocket con Polymarket?
Invia un messaggio PING ogni 10 secondi; il server risponde con PONG. È un heartbeat a livello applicativo lato client, quindi il keepalive integrato di una libreria WebSocket a un intervallo diverso non lo sostituisce. Tieni traccia anche dell’età dell’ultimo messaggio ricevuto: una connessione caduta smette di consegnare dati senza generare errori, quindi tratta circa 30 secondi di silenzio su un mercato attivo come una disconnessione e non come un mercato tranquillo.
Perché non ricevo gli eventi best_bid_ask o market_resolved?
Questi eventi sono disattivati per impostazione predefinita. Imposta custom_feature_enabled a true nel messaggio di sottoscrizione per abilitare best_bid_ask, new_market e market_resolved. Quando il flag manca non c’è alcun errore o avviso: gli eventi semplicemente non arrivano mai, il che è facile da scambiare per un mercato inattivo.
Il mio bot per Polymarket dovrebbe usare i WebSocket o fare polling dell’API REST?
Usa i WebSocket per i dati live di book e prezzi. Seguire 20 mercati facendo polling di /book una volta al secondo costa 72,000 richieste all’ora su un budget di 1,500 req/10s, mentre una sottoscrizione costa una connessione più gli heartbeat; e il polling restituisce anche una risposta più vecchia, perché vedi il book com’era al tuo ultimo polling e non all’ultima modifica. Tieni REST per la scoperta dei mercati, le dimensioni dei tick, l’invio degli ordini e la riconciliazione delle posizioni.
Posso cambiare i mercati a cui sono iscritto senza riconnettermi?
Sì. Il canale market supporta sottoscrizione e annullamento della sottoscrizione degli asset su una connessione attiva, il che conta per i mercati di breve durata come i contratti Up/Down a 5 minuti, che ruotano di continuo. Riconnettersi a ogni rotazione fa pagare ripetutamente il costo di apertura della connessione e lascia un buco di copertura proprio nel momento in cui si apre un nuovo mercato.

Ottieni i dati storici che Polymarket non conserva

PolyTest registra i mercati crypto Up/Down di Polymarket mentre sono attivi: 240M+ snapshot con 8 livelli di profondità dell’order book, timestamp sotto il secondo e mercati risolti conservati. Inizia con una prova gratuita di 3 giorni.

Continua a leggere