Polling a scores endpoint every few seconds is wasteful and always slightly stale. The Live Tennis API has a native WebSocket feed that pushes a frame the instant a score changes.
The feed is on the ULTRA plan.
Python
pip install "livetennisapi[ws]"
from livetennisapi import LiveScoreStream
with LiveScoreStream() as stream:
for update in stream:
print(update.match_id, update.score.sets, update.score.points)
That is the whole program. No reconnect loop, no heartbeat handling, no subscribe handshake — the client does all of it.
JavaScript / TypeScript
npm install livetennisapi
import { LiveScoreStream } from 'livetennisapi';
const stream = new LiveScoreStream({ apiKey: process.env.LIVETENNISAPI_KEY });
for await (const update of stream) {
console.log(update.match_id, update.sets, update.points);
}
Watch one match instead of all of them
stream = LiveScoreStream(topics=["match:18953"])
new LiveScoreStream({ topics: ['match:18953'] });
What the client handles for you
Heartbeats. The server sends a ping roughly every 15 seconds to keep the
connection alive. These are consumed internally — iterate the stream and you
only ever see real score changes.
The subscribe deadline. The server drops the socket if the subscribe frame
arrives late, so the client sends it immediately on open and waits for the
subscribed acknowledgement before yielding anything.
Reconnection, with a caveat worth knowing. The stream reconnects with exponential backoff and re-subscribes. But it deliberately does not reconnect on a bad key, an insufficient plan, or the service being disabled — those raise immediately, because retrying them just hammers a closed door.
from livetennisapi import Unauthorized, UpgradeRequired
try:
for update in stream:
...
except UpgradeRequired:
print("the WebSocket feed needs the ULTRA plan")
except Unauthorized:
print("check LIVETENNISAPI_KEY")
The backoff also only resets after a connection has stayed up for a minute. A server that accepts and then immediately drops would otherwise pin the delay at its first step forever and never surface a failure.
Streaming from the terminal
livetennis watch # every live match
livetennis watch --match 18953 # one match
npx livetennisapi watch # same thing, no install
Where to go next
- WebSocket protocol details: https://docs.livetennisapi.com/reference.html
- Python client: github.com/livetennisapi/livetennisapi-python
- JS client: github.com/livetennisapi/livetennisapi-js