HomeBlog › Streaming Pinnacle Odds over WebSocket: When You Need It Instead of SSE
Guides

Streaming Pinnacle Odds over WebSocket: When You Need It Instead of SSE

Streaming Pinnacle Odds over WebSocket: When You Need It Instead of SSE

A practical comparison of WebSocket vs SSE for live Pinnacle odds: how each behaves, when the extra complexity of WebSocket is worth it, and a working client.

Streaming Pinnacle Odds over WebSocket: When You Need It Instead of SSE

We offer live odds over three transports — REST, SSE, and WebSocket — and the most common question we get is "which streaming one should I use?" The honest answer is that most people should use SSE, and WebSocket is for a specific minority of cases. This post is about telling which one you're in, so you don't take on complexity you don't need.

If you haven't read the SSE walkthrough yet, start there; this assumes you know the basic streaming model.

The one-sentence difference

SSE is a one-way stream: the server pushes events to you over a plain HTTP connection. WebSocket is a two-way channel: you can also send messages up to the server mid-connection. For odds data — which flows server → client — that upstream channel is the entire reason to choose WebSocket, and most consumers never use it.

And don't forget the third option: plain REST polling. If your use case is periodic snapshots — prematch scans every few minutes, model recalibration, a dashboard — polling a snapshot endpoint is simpler than either stream and completely adequate. The websocket-vs-REST question only really exists once you need to react to changes as they happen; at that point your polling interval becomes your latency floor, and push transport — either one — wins.

When SSE is the right choice (probably you)

Pick SSE if:

For the large majority of "stream me the drops" use cases, SSE is less code, fewer failure modes, and identical data.

When WebSocket earns its complexity

Pick WebSocket if you genuinely need to talk back to the server on the same connection:

If none of those apply, WebSocket is just SSE with more ways to break. If they do apply, the product side (what the raw feed carries, what it costs, which plans it sits on) is on the Pinnacle WebSocket API page; this post stays on the how.

A working WebSocket client

import WebSocket from "ws";

const ws = new WebSocket("wss://pinnapi.com/ws/feed", {
    headers: { "x-portal-apikey": process.env.PINNAPI_KEY },
});

ws.on("open", () => {
    // the upstream channel: subscribe dynamically (sport_ids use pinnapi sport IDs, 1 = soccer)
    ws.send(JSON.stringify({ type: "subscribe", streams: ["live"], sport_ids: [1] }));
});

ws.on("message", (raw) => {
    const msg = JSON.parse(raw);
    switch (msg.type) {
        case "connected":
        case "subscribed":
        case "ping":     return;                 // control frames
        case "snapshot": return seedState(msg);  // initial state for a subscription
        default:         handleFrame(msg);        // a forwarded raw Pinnacle frame
    }
});

ws.on("close", () => scheduleReconnect());
ws.on("error", (e) => console.error("ws error", e));

The subscribe message is the part SSE can't do cleanly. Later, { type: "unsubscribe", streams: ["live"], sport_ids: [1] } (or event_ids: [...]) narrows your stream without a reconnect.

Reconnection is on you (this is the real cost)

With SSE, EventSource reconnects automatically. With WebSocket, you own the reconnect loop — and getting it wrong is the most common WebSocket bug:

let backoff = 500;
function scheduleReconnect() {
  setTimeout(() => {
      backoff = Math.min(backoff * 2, 15_000); // exponential, capped
      connect(); // your connect() re-auths + re-subscribes
    }, backoff);
}

Two things people forget: re-subscribe after reconnect (the server doesn't remember your subscriptions across a dropped socket), and resync state with a REST snapshot rather than assuming you didn't miss events during the gap. Same recovery principle as SSE — stream for speed, REST for truth.

Latency: basically the same

People assume WebSocket is faster than SSE. For server→client push of small JSON events, the difference is negligible — both ride a warm TCP connection and the payload is tiny. Don't choose WebSocket for speed; choose it for the upstream channel. If latency is your concern, the thing that actually moves the number is region and load, not transport — measure it from your own region and infrastructure.

Takeaway

Default to SSE. Reach for WebSocket only when you need to change your subscription live or otherwise send messages upstream — and when you do, budget for owning the reconnect-and-resubscribe logic yourself. The data and the latency are the same; what differs is how much machinery you're signing up to maintain.

Frequently asked questions

Is WebSocket faster than SSE for odds?

Not meaningfully for server→client push of small events. Choose by feature need (bidirectional), not speed.

Can I change which fixtures I'm watching without reconnecting?

That's exactly what WebSocket is for — send a subscribe/unsubscribe message on the open connection. SSE can't do this cleanly.

What happens to my subscriptions if the socket drops?

They're gone — re-subscribe on reconnect and resync state with a REST snapshot.

Get real-time Pinnacle odds in your code

Live & prematch markets with sub-second odds-drop alerts. Free trial key in seconds — no card.

Start free trial