Quick answer: You will install free Python on your PC, create a small project folder, save a secret API key, run one short script to list live matches, then run a second script so your browser shows a personal tennis scoreboard (formatted sets, games, points — not raw API lists). No coding experience required — copy, paste, and follow the steps in order. If you only want live scores next to Betfair today, skip the build and open our free tennis trader board instead.

Disclosure: Links to Live Tennis API are affiliate links. We may earn a commission if you subscribe. Use our link or checkout code botblog for 10% off. Live Tennis API also gave BotBlog Ultra access for testing. The how-to steps are independent. Full disclosure.

You will need an API key before the scripts work. Get one first, then come back to Step 0.

Subscribe to Live Tennis API (10% off) →

Affiliate link — or type botblog at checkout. Disclosure

Before we start — please read this

I’m Stephane. I run BotBlog and I’m a keen tennis player. I wrote this for people who have never built an app. If a word looks scary, we explain it the first time it appears.

This guide is for you if:

  • You can download and install a program from a website
  • You can create a folder and save a text file
  • You are happy to copy code exactly (do not “improve” it until it works once)

This guide is not: betting tips, a tipster service, or a Betfair trading bot. For bots and licences later, see Betfair tennis trading bots — live scores & API cost.

Want live tennis scores without installing anything? We built a free hosted board on BotBlog — same Live Tennis API data, plus break-point alerts (15–40 / 0–40), ATP/WTA filters and optional P1 odds vs model win %. No API key, no Python.

Open the free Tennis Trader Board →

Then come back here when you want to build your own private scoreboard on your PC.

Expect about 45–90 minutes the first time (installs included). After that, starting the dashboard takes under a minute.

Personal live tennis scoreboard in the browser with sets, games, points and serving indicators
What you are building: a TV-style personal scoreboard on your own PC (real screenshot from the finished Step 4 app).

Tiny glossary (keep this handy)

WordPlain meaning
APIA way for your computer to ask a website for data (here: live tennis scores)
API keyYour private password for that service — never share it publicly
Terminal / PowerShellA black/blue window where you type commands and press Enter
Virtual environment (.venv)A private toolbox for this project only, so Python packages do not mess up your PC
pipThe tool that downloads Python packages (Flask, requests, …)
FlaskA package that shows a web page from your Python script
127.0.0.1 / localhost“This computer” — not the public internet

What you need (equipment)

Computer

  • A Windows 10/11 PC or laptop, or a Mac, or a normal Linux desktop
  • About 4 GB RAM minimum (8 GB is more comfortable)
  • About 500 MB free disk space
  • Not a phone or tablet alone — you need a real desktop system for this tutorial

Browser

  • Chrome, Edge, Firefox, or Safari (up to date)
  • You will use it to open your dashboard and to sign up for the API

Internet

  • Normal home Wi‑Fi or broadband is fine
  • Scores are live — if Wi‑Fi drops, the board stops updating

Accounts / money

  • A Live Tennis API subscription (code botblog = 10% off)
  • Basic plan is enough for Steps 1–4 (dashboard that refreshes every few seconds)
  • Ultra plan is needed only for the optional Step 5 (instant updates)

Step 0 — Install Python (do this once)

  1. Open your browser and go to python.org/downloads.
  2. Download the latest Python 3 installer for your system (3.11 or 3.12 is ideal).
  3. Windows — important: on the first installer screen, tick Add python.exe to PATH, then click Install Now.
  4. Finish the installer. If Windows offers “Disable path length limit”, you can accept it.
  5. Check it worked:
    • Windows: press Win key, type powershell, open Windows PowerShell
    • Mac: open Terminal from Spotlight
  6. Type this and press Enter:
    python --version
    
    On some Macs use python3 --version.
  7. You should see something like Python 3.12.x. If you see an error, restart the PC and try again, or reinstall with “Add to PATH” ticked.

Also install a simple editor if you want (optional but helpful): VS Code — or use Notepad on Windows / TextEdit on Mac.

Windows tip: In File Explorer → View → enable File name extensions so you can see .py and .txt endings. That stops you saving list_live.py.txt by mistake.

Step 1 — Get your Live Tennis API key

  1. In your browser, open this Live Tennis API link (keeps your 10% off).
  2. Or go to their site and enter code botblog at checkout.
  3. Create an account and choose a plan (Basic is fine to start).
  4. Copy your API key. It often looks like twjp_ followed by letters and numbers.
  5. Paste it into Notepad temporarily if you need — but do not post it on social media, Discord, or GitHub.

Optional check (no coding yet): in the browser address bar, paste this and replace YOUR_KEY with your real key, then press Enter:

https://api.livetennisapi.com/api/public/v1/scoreboard?token=YOUR_KEY

If you see a live scoreboard page, your key works. Official docs (for later): docs.livetennisapi.com.

Step 2 — Make a project folder and two small files

  1. On your Desktop (or Documents), create a new folder named exactly:
    tennis-dashboard
    
  2. Open that folder.
  3. Create a new text file named exactly:
    .env
    
    (Yes, it starts with a dot. On Windows Notepad: Save as → “All files” → name .env)
  4. Put one line inside (paste your real key after the equals sign, no spaces):
    LIVETENNISAPI_KEY=twjp_paste_your_real_key_here
    
  5. Save and close.
  6. Create another file named exactly:
    requirements.txt
    
  7. Put these four lines inside (copy exactly):
    flask>=3.0
    python-dotenv>=1.0
    websocket-client>=1.8
    requests>=2.32
    
  8. Save and close.

Create the private toolbox (virtual environment)

A virtual environment is a folder named .venv that holds Python packages for this project only.

Next you will use a terminal (on Windows that is usually PowerShell). A terminal is a text window where you type a command and press Enter — it is not Notepad and not your web browser.

How to open a terminal in your project folder (Windows)

Pick one method — Method A is the easiest.

Method A — from File Explorer (recommended)

  1. Open File Explorer (yellow folder icon on the taskbar).
  2. Go into your tennis-dashboard folder so you can see .env and requirements.txt inside it.
  3. Click once in the address bar at the top (where the folder path is shown) so the path text becomes highlighted.
  4. Type exactly:
    powershell
    
    then press Enter.
  5. A blue or black window opens. That is your terminal. It should already be “inside” tennis-dashboard.

Method B — right‑click menu

  1. In File Explorer, open tennis-dashboard.
  2. Hold Shift and right‑click on empty space in the folder (not on a file).
  3. Click Open PowerShell window here or Open in Terminal.

Method C — start PowerShell first, then move into the folder

  1. Press the Windows key, type powershell, open Windows PowerShell.
  2. Type a cd command to move into your folder, then press Enter. Examples (pick the one that matches where you put the folder):
    cd Desktop\tennis-dashboard
    
    or
    cd Documents\tennis-dashboard
    
    or a full path, for example:
    cd C:\Users\YourName\Desktop\tennis-dashboard
    
    Replace YourName with your Windows user name.

Check you are in the right place — type this and press Enter:

dir

You should see .env and requirements.txt in the list. If you do not, you are in the wrong folder — use cd again until dir shows those files.

What “run” means from here: click in the terminal window so it is active, type the command carefully, then press Enter. Wait for it to finish before typing the next one. You can copy commands from this page and paste into PowerShell with right‑click → Paste (or Ctrl+V).

Commands to type (Windows) — one at a time

  1. Create the toolbox folder:
    python -m venv .venv
    
    Press Enter and wait (10–60 seconds). When the prompt comes back, a new folder named .venv appears in File Explorer. If python fails, try:
    py -m venv .venv
    
  2. Turn the toolbox on (do this every time you open a new terminal for this project):
    .venv\Scripts\activate
    
  3. Check the start of the line now shows (.venv). That means it worked.
  4. If Windows says scripts are disabled, run this once, press Enter, then run the activate command again:
    Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
    
  5. Download the Python packages (needs internet — may take a minute):
    pip install -r requirements.txt
    
    Wait until you see messages about packages being successfully installed and your prompt comes back.

Mac — open Terminal in the folder

  1. Open Terminal (press Cmd+Space, type Terminal, press Enter).
  2. Move into your folder, for example:
    cd ~/Desktop/tennis-dashboard
    
  3. Check with:
    ls
    
    You should see .env and requirements.txt.
  4. Then run these one at a time:
    python3 -m venv .venv
    source .venv/bin/activate
    pip install -r requirements.txt
    

When source .venv/bin/activate works, the line starts with (.venv) — same idea as Windows.

Your folder should now contain at least: .env, requirements.txt, and .venv.

Step 3 — First win: list live matches

We will create a small program that asks Live Tennis API: “Which matches are live right now?” and prints the names in the terminal.

  1. In tennis-dashboard, create a new file named exactly:
    list_live.py
    
  2. Open it and paste all of this code (do not skip lines):
import os
import requests
from dotenv import load_dotenv

load_dotenv()
KEY = os.environ["LIVETENNISAPI_KEY"]
URL = "https://api.livetennisapi.com/api/public/v1/matches"
HEADERS = {
    "Authorization": f"Bearer {KEY}",
    "User-Agent": "TennisDashboardTutorial/1.0",
}

r = requests.get(URL, params={"status": "live"}, headers=HEADERS, timeout=30)
r.raise_for_status()
matches = r.json().get("data") or []

print(f"Live matches: {len(matches)}\n")
for m in matches[:15]:
    p1 = (m.get("players") or {}).get("p1", {}).get("name", "?")
    p2 = (m.get("players") or {}).get("p2", {}).get("name", "?")
    print(f"{m.get('id')}: {p1} vs {p2} ({m.get('format')})")
  1. Save the file.

How to run it (Windows)

  1. Open PowerShell in the tennis-dashboard folder (address bar → type powershell → Enter).
  2. Activate the toolbox:
    .venv\Scripts\activate
    
    You must see (.venv).
  3. Type this exactly and press Enter:
    python list_live.py
    
    There is a space between python and list_live.py.
  4. If Windows says python is not recognised, try:
    py list_live.py
    

Do not paste python list_live.py into Chrome’s address bar. That only works for website addresses.

How to run it (Mac)

  1. Open Terminal.
  2. cd ~/Desktop/tennis-dashboard (change the path if your folder is elsewhere).
  3. source .venv/bin/activate
  4. python list_live.py or python3 list_live.py

What “it worked” looks like

Live matches: 24

20978: Player A vs Player B (BO3)
21201: Player C vs Player D (BO3)
PowerShell window showing python list_live.py output with live tennis match IDs and player names
Real PowerShell output after python list_live.py — live match IDs and player names from the live scores API.

The script then stops by itself. That is normal.

If you see thisDo this
can't open file 'list_live.py'You are in the wrong folder — open PowerShell from inside tennis-dashboard
No module named 'requests'Activate .venv, then run pip install -r requirements.txt again
KeyError: 'LIVETENNISAPI_KEY'Check .env is in the same folder and the line spelling is exact
401 errorWrong API key — copy it again from your Live Tennis account
Live matches: 0The script worked — there may simply be no live matches right now. Try later in the day

When you see player names, you have successfully used a live scores API. Take a breath — the hard part of “first contact” is done.

Need a key before this step works?

Get Live Tennis API (10% off) →

Step 4 — Show scores in your browser (Flask)

What Flask is

Flask is a free add-on for Python. It does not appear in the Windows Start menu as its own program. You already installed it with pip in Step 2.

When you run our next file, Flask starts a tiny website only on your PC. Your browser opens it like any other page.

Quick check (with (.venv) active):

python -c "import flask; print(flask.__version__)"

You should see a version number. If not, run pip install flask and try again.

Why raw API lists look ugly (and how we fix that)

Before you paste the big file, it helps to know why we do not dump the API numbers straight onto the page.

What the live scores API actually returns

When your script asks for one match score, Live Tennis API answers with JSON — structured data, not a pretty TV graphic. A real example looks like this:

{
  "sets": [1, 0],
  "games": [[7, 2], [5, 2]],
  "points": ["0", "30"],
  "server": 2
}
FieldMeaningPlain English
sets[1, 0]Player 1 has won 1 set, player 2 has won 0
games[[7, 2], [5, 2]]First set finished 7–2; current set is 5–2
points["0", "30"]Current game: 0–30 (tennis point labels, not always numbers)
server1, 2, or nullWho is serving — or unknown

If you print those lists in the browser as-is, you get ugly text like [1, 0] and ['40', 'AD']. That is honest data — but it is not a scoreboard. So we add small helper functions that turn lists into separate columns per player.

How the formatting helpers work (read this once)

  1. pair_or_dash(values, index) — Sets and points arrive as a two-item list: index 0 is player 1, index 1 is player 2. This helper safely picks one side. If the list is missing or short, it shows an em dash () instead of crashing.
  2. games_by_set(games) — Games are trickier. Sometimes the API sends [[7, 2], [5, 2]] (one [p1, p2] pair per set). Sometimes it sends something like [[3], [2]] (player 1’s games list and player 2’s games list). The function detects which shape it got and always returns a clean list of pairs such as [(7, 2), (5, 2)].
  3. format_match_score(...) — Builds one scoreboard “card”:
    • Sets won → sets_p1 / sets_p2
    • Current games → last pair in the games list
    • Points → points_p1 / points_p2 (keeps labels like AD)
    • Set history line → joins every set as 7–2 · 5–2
    • Server number stays as 1 or 2 so the HTML can show a yellow serve dot and a “serving” badge on the right row
  4. The HTML template — Each match is a card with two rows (one per player), like a TV scoreboard. CSS lines up Sets / Games / Points in columns. The page auto-refreshes about every 8 seconds using <meta http-equiv="refresh" content="8"/>.
  5. Faster loading — We only show 12 live matches, and ThreadPoolExecutor asks for several match scores at the same time (instead of one-after-another). That is why the first paint is usually a few seconds, not half a minute.

You do not need to invent this from scratch. Copy the full app.py below. After it works, re-read the helpers above and you will recognise each piece.

Close-up of live tennis scoreboard cards with sets, games, points and serving indicator
Close-up: each match is a mini TV-style scoreboard — two player rows, columns for sets / games / points, yellow serve dot.

Create app.py

  1. In tennis-dashboard, create app.py.
  2. Paste everything below and save (it is long on purpose — helpers + HTML + Flask in one file):
import os
from concurrent.futures import ThreadPoolExecutor, as_completed

import requests
from dotenv import load_dotenv
from flask import Flask, render_template_string

load_dotenv()
KEY = os.environ["LIVETENNISAPI_KEY"]
API = "https://api.livetennisapi.com/api/public/v1"
HEADERS = {
    "Authorization": f"Bearer {KEY}",
    "User-Agent": "TennisDashboardTutorial/1.0",
}

app = Flask(__name__)

PAGE = """
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8"/>
  <meta http-equiv="refresh" content="8"/>
  <title>My Live Tennis Dashboard</title>
  <style>
    :root {
      --bg: #0b1220;
      --panel: #121a2b;
      --line: #243147;
      --text: #e8eef7;
      --muted: #8fa0b8;
      --accent: #3dd68c;
      --serve: #f5c542;
    }
    * { box-sizing: border-box; }
    body {
      margin: 0;
      font-family: "Segoe UI", Tahoma, sans-serif;
      background: radial-gradient(1200px 600px at 20% -10%, #1a2740, var(--bg));
      color: var(--text);
      padding: 1.5rem;
    }
    h1 { margin: 0 0 0.35rem; font-size: 1.75rem; font-weight: 650; letter-spacing: -0.02em; }
    .meta { color: var(--muted); margin: 0 0 1.25rem; }
    .board { display: grid; gap: 0.75rem; max-width: 820px; }
    .match {
      background: var(--panel);
      border: 1px solid var(--line);
      border-radius: 10px;
      padding: 0.85rem 1rem;
    }
    .cols, .row {
      display: grid;
      grid-template-columns: 1fr 52px 64px 72px 56px;
      gap: 0.35rem;
      align-items: center;
    }
    .cols {
      font-size: 0.78rem;
      color: var(--muted);
      text-transform: uppercase;
      letter-spacing: 0.04em;
      margin-bottom: 0.35rem;
    }
    .row { padding: 0.28rem 0; }
    .row + .row { border-top: 1px solid var(--line); }
    .name { font-size: 1rem; font-weight: 600; }
    .score {
      font-variant-numeric: tabular-nums;
      font-family: Consolas, "Courier New", monospace;
      font-size: 1.05rem;
      text-align: center;
    }
    .history { color: var(--muted); font-size: 0.8rem; margin-top: 0.45rem; }
    .serve-dot {
      width: 10px; height: 10px; border-radius: 50%;
      background: var(--serve); display: inline-block;
      box-shadow: 0 0 0 3px rgba(245, 197, 66, 0.2);
    }
    .serve-empty { text-align: center; }
    .badge {
      display: inline-block;
      margin-left: 0.4rem;
      font-size: 0.7rem;
      color: var(--accent);
      border: 1px solid rgba(61, 214, 140, 0.35);
      border-radius: 999px;
      padding: 0.1rem 0.45rem;
      vertical-align: middle;
    }
  </style>
</head>
<body>
  <h1>Live tennis scores</h1>
  <p class="meta">Personal scoreboard · auto-refresh every 8s · {{ count }} matches</p>
  <div class="board">
  {% for row in rows %}
    <div class="match">
      <div class="cols">
        <div>Players</div><div>Sets</div><div>Games</div><div>Points</div><div>Serve</div>
      </div>
      <div class="row">
        <div class="name">{{ row.p1 }}{% if row.server == 1 %}<span class="badge">serving</span>{% endif %}</div>
        <div class="score">{{ row.sets_p1 }}</div>
        <div class="score">{{ row.games_p1 }}</div>
        <div class="score">{{ row.points_p1 }}</div>
        <div class="serve-empty">{% if row.server == 1 %}<span class="serve-dot" title="Serving"></span>{% endif %}</div>
      </div>
      <div class="row">
        <div class="name">{{ row.p2 }}{% if row.server == 2 %}<span class="badge">serving</span>{% endif %}</div>
        <div class="score">{{ row.sets_p2 }}</div>
        <div class="score">{{ row.games_p2 }}</div>
        <div class="score">{{ row.points_p2 }}</div>
        <div class="serve-empty">{% if row.server == 2 %}<span class="serve-dot" title="Serving"></span>{% endif %}</div>
      </div>
      {% if row.set_history %}
      <div class="history">Completed / in-progress sets: {{ row.set_history }}</div>
      {% endif %}
    </div>
  {% endfor %}
  </div>
</body>
</html>
"""


def pair_or_dash(values, index):
    """Take one side of a [p1, p2] list; show — if missing."""
    if not isinstance(values, (list, tuple)) or len(values) <= index:
        return "—"
    value = values[index]
    return "—" if value is None else str(value)


def games_by_set(games):
    """
    Turn the API games field into a list of (p1, p2) per set.

    Live Tennis API usually sends either:
      [[7, 2], [5, 2]]  → one [p1, p2] pair per set
      [[3], [2]]        → p1 games list + p2 games list (zip them)
    """
    if not games or not isinstance(games, list):
        return []

    # Case A: list of sets, each set is [p1_games, p2_games]
    if all(isinstance(g, (list, tuple)) and len(g) == 2 for g in games):
        return [(g[0], g[1]) for g in games]

    # Case B: [p1_games_per_set, p2_games_per_set]
    if (
        len(games) >= 2
        and isinstance(games[0], (list, tuple))
        and isinstance(games[1], (list, tuple))
    ):
        p1, p2 = games[0], games[1]
        n = max(len(p1), len(p2))
        out = []
        for i in range(n):
            a = p1[i] if i < len(p1) else 0
            b = p2[i] if i < len(p2) else 0
            out.append((a, b))
        return out

    return []


def format_match_score(score, p1_name, p2_name):
    """Convert raw score JSON into scoreboard fields."""
    sets = score.get("sets") or []
    points = score.get("points") or []
    server = score.get("server")
    pairs = games_by_set(score.get("games"))

    if pairs:
        games_p1, games_p2 = pairs[-1]
        set_history = " · ".join(f"{a}–{b}" for a, b in pairs)
    else:
        games_p1 = games_p2 = "—"
        set_history = ""

    return {
        "p1": p1_name,
        "p2": p2_name,
        "sets_p1": pair_or_dash(sets, 0),
        "sets_p2": pair_or_dash(sets, 1),
        "games_p1": games_p1 if games_p1 == "—" else str(games_p1),
        "games_p2": games_p2 if games_p2 == "—" else str(games_p2),
        "points_p1": pair_or_dash(points, 0),
        "points_p2": pair_or_dash(points, 1),
        "server": server,
        "set_history": set_history,
    }


def score_for_match(m):
    mid = m["id"]
    p1 = (m.get("players") or {}).get("p1", {}).get("name", "?")
    p2 = (m.get("players") or {}).get("p2", {}).get("name", "?")
    try:
        s = requests.get(f"{API}/matches/{mid}/score", headers=HEADERS, timeout=20).json()
    except Exception:
        s = {}
    return format_match_score(s, p1, p2)


def fetch_rows():
    r = requests.get(f"{API}/matches", params={"status": "live"}, headers=HEADERS, timeout=30)
    r.raise_for_status()
    matches = r.json().get("data") or []
    selected = matches[:12]
    rows = [None] * len(selected)
    # Ask for several scores at the same time so the page loads faster
    with ThreadPoolExecutor(max_workers=6) as pool:
        futures = {pool.submit(score_for_match, m): i for i, m in enumerate(selected)}
        for fut in as_completed(futures):
            rows[futures[fut]] = fut.result()
    return rows


@app.get("/")
def home():
    rows = fetch_rows()
    return render_template_string(PAGE, rows=rows, count=len(rows))


if __name__ == "__main__":
    app.run(debug=True, port=5055)

How to start the dashboard

  1. PowerShell in tennis-dashboard with (.venv) active.
  2. Run:
    python app.py
    
  3. Leave this window open. Unlike Step 3, this program keeps running on purpose.
  4. You should see a line like:
     * Running on http://127.0.0.1:5055
    
  5. Open Chrome/Edge/Firefox and click the address bar. Type exactly:
    http://127.0.0.1:5055/
    
    or
    http://localhost:5055/
    
    then press Enter.
  6. First load can take a few seconds while scores are fetched. Then you should see scoreboard cards. The page reloads about every 8 seconds by itself.
Live tennis scoreboard dashboard in the browser with multiple match cards
Finished scoreboard at http://127.0.0.1:5055/ — human-readable sets, games, points, and who is serving.
Full-page live tennis scores scoreboard showing twelve matches
Full page: twelve live matches, each with set history under the card.

If Windows Firewall asks about Python, choose Allow on private networks.

To stop: click the PowerShell window and press Ctrl+C. Then the web page will stop loading until you run python app.py again.

ProblemFix
Browser cannot connectIs PowerShell still showing “Running on…”? Did you use port 5055?
Address already in useAn old Flask is still running — press Ctrl+C in that window, or change port=5055 to port=5056 in app.py and open that URL
Blank / old pageHard refresh: Ctrl+F5
Ugly lists like [1, 0]You are on an older app.py — paste the full scoreboard version again
No module named 'flask'Activate .venv, then pip install flask

You now have a personal live tennis scoreboard on your own computer — not just raw API text. That is the main goal of this guide.

Step 5 — Optional: instant updates (Ultra plan)

Skip this until Steps 1–4 work.

The dashboard above asks for scores every few seconds. Fine for learning. If you want updates the moment a point is played, Live Tennis API’s Ultra plan includes a live stream (called a WebSocket).

Upgrade or subscribe to Ultra (10% off), then:

  1. Create ws_listen.py in the same folder.
  2. Paste this and save:
import json
import os
import websocket
from dotenv import load_dotenv

load_dotenv()
KEY = os.environ["LIVETENNISAPI_KEY"]
URL = f"wss://api.livetennisapi.com/api/public/v1/ws?token={KEY}"

def on_open(ws):
    print("Connected — waiting for live scores…")
    ws.send(json.dumps({"topics": ["live-scores"]}))

def on_message(ws, message):
    msg = json.loads(message)
    if msg.get("type") == "subscribed":
        print("Subscribed OK")
        return
    if msg.get("type") == "score":
        s = msg.get("score") or {}
        print(
            "match", msg.get("match_id"),
            "sets", s.get("sets"),
            "games", s.get("games"),
            "points", s.get("points"),
            "server", s.get("server"),
        )

websocket.WebSocketApp(URL, on_open=on_open, on_message=on_message).run_forever()
  1. With (.venv) active, run:
    python ws_listen.py
    
  2. Leave it running during live matches. New lines should appear when points are played.
  3. Stop with Ctrl+C.

Wiring that stream into the Flask page is a good “next project” once you are comfortable. For trading research with Matchbook prices, see our tennis bots guide.

Everyday use — starting again tomorrow

  1. Open PowerShell in tennis-dashboard
  2. .venv\Scripts\activate
  3. python app.py
  4. Browser → http://127.0.0.1:5055/

That is the whole daily routine.

Ideas to personalise (when you are ready)

  • Watch only matches with a favourite player’s name
  • Change colours in the HTML style section
  • Run it on a second screen while you practise tennis
  • Compare your DIY board with our hosted Tennis Trader Board (alerts + model % already built in)

Keep the board private on your PC. Putting the live feed on a public website may break the vendor’s rules — read their terms first. (The BotBlog trader board is our hosted product under our own Live Tennis API subscription — that is different from republishing your key.)

What this project is (and is not)

  • Is: a beginner-friendly personal tennis scoreboard
  • Is: practice using an API key and Python on your own machine
  • Is not: financial advice or betting tips
  • Is not: a phone app from an app store
  • Is not required if you only need a free scoreboard — use the Tennis Trader Board for that

Hosted board vs this DIY project

Tennis Trader BoardThis DIY guide
Cost to watch scoresFree on BotBlogNeeds your own Live Tennis API key
SetupOpen the page~45–90 minutes first time
Break-point alerts / filtersBuilt in (15–40, surface, ATP/WTA…)You add them yourself later
Best forTrading next to Betfair todayLearning APIs / a private scoreboard you control

Next steps

  1. Try the free Tennis Trader Board so you know what “good” live scores look like
  2. Get your API key (code botblog) if you want your own board
  3. Finish Steps 0–4
  4. Try Step 5 if you want Ultra / instant updates
  5. Later: scores vs exchange prices · BF Bot Manager tennis · 15–40 strategy

Start here — Live Tennis API key (10% off) →

Affiliate link — code botblog. Disclosure

Educational only. Keep your API key private and respect Live Tennis API’s terms. If you also gamble or trade, remember risk of loss — 18+ only. BeGambleAware.org