Soccer API in Python: Premier League, LaLiga and MLS scores
A single Python script that prints a league's fixtures and scores for today or any day. Change one league code to switch from the Premier League to LaLiga, MLS or the Champions League.
- Stack
- Python, requests
- Plan
- Free (one call per command)
- Code
- python-soccer/ (MIT)
Updated 2026-11-05. Tested against the live API on that date. Data is aggregated from public sources and is typically 20-30 seconds behind live play (about 1 second after our source). There is no SLA.
1. Get a free API key
Sign up (no card) and copy the key from the dashboard. The Free plan gives you 1,000 calls in the first 30 days, then 125 a month, at 1 request per second. Every successful REST call counts as one call.
Check the key works with one call to the live-scores endpoint:
Terminal
export REALTIME_SPORTS_API_KEY=your_key
curl -H "Authorization: Bearer $REALTIME_SPORTS_API_KEY" \
"https://www.realtimesportsapi.com/api/v1/sports/football/leagues/nfl/events/live"2. Get the code
Everything below is in the python-soccer/ folder of the examples repo (MIT). Clone it and work from that folder.
Terminal
git clone https://github.com/ElcoDevRepos/realtime-sports-api-examples
cd realtime-sports-api-examples/python-soccer3. Install
Python 3.10+ and requests. Nothing else.
Terminal
python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # REALTIME_SPORTS_API_KEY4. The script
scores reads a league's scoreboard: today by default, or any day with --date. The league is a code: eng.1 (Premier League), esp.1 (LaLiga), ita.1 (Serie A), ger.1 (Bundesliga), fra.1 (Ligue 1), usa.1 (MLS), mex.1 (Liga MX), uefa.champions. leagues prints them.
python-soccer/soccer.py
#!/usr/bin/env python3
"""Soccer (football) data in Python with the Realtime Sports API: fixtures and scores for many leagues.
Usage:
python soccer.py scores # Premier League scoreboard
python soccer.py scores --league esp.1 # LaLiga (usa.1 = MLS, eng.1 = Premier League ...)
python soccer.py scores --league usa.1 --date 2026-11-01
python soccer.py leagues # the league codes
One key covers every league. Needs REALTIME_SPORTS_API_KEY (env or .env).
"""
from __future__ import annotations
import argparse
import os
import sys
from pathlib import Path
from typing import Any, Dict
import requests
API_BASE = os.environ.get("RSA_API_BASE", "https://www.realtimesportsapi.com/api/v1")
def load_dotenv(path: Path) -> None:
"""Tiny .env loader (KEY=value). Existing environment variables win."""
if not path.exists():
return
for line in path.read_text().splitlines():
line = line.strip()
if line and not line.startswith("#") and "=" in line:
k, v = line.split("=", 1)
os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'"))
def api_get(path: str, **params: Any) -> Dict[str, Any]:
key = os.environ.get("REALTIME_SPORTS_API_KEY")
if not key:
sys.exit("Set REALTIME_SPORTS_API_KEY (get a free key at https://www.realtimesportsapi.com/signup)")
r = requests.get(f"{API_BASE}{path}", params=params, headers={"Authorization": f"Bearer {key}"}, timeout=20)
body = r.json()
if r.status_code != 200 or not body.get("success", False):
err = body.get("error") or {}
sys.exit(f"HTTP {r.status_code}: {err.get('message') or body}")
return body
def team_line(t: Dict[str, Any]) -> str:
score = t.get("score")
return f"{t.get('abbreviation') or t.get('name')}{'' if score is None else f' {score}'}"
def print_games(games) -> None:
for g in sorted(games, key=lambda e: e.get("date") or ""):
st = g.get("status") or {}
print(f"[{g['id']}] {g.get('date', '')[:16]} {team_line(g['awayTeam'])} @ {team_line(g['homeTeam'])} {st.get('detail') or st.get('state')}")
LEAGUES = {
"eng.1": "Premier League", "esp.1": "LaLiga", "ita.1": "Serie A", "ger.1": "Bundesliga",
"fra.1": "Ligue 1", "usa.1": "MLS", "mex.1": "Liga MX", "uefa.champions": "Champions League",
}
def cmd_scores(args: argparse.Namespace) -> None:
params = {"date": args.date} if args.date else {}
print_games(api_get(f"/sports/soccer/leagues/{args.league}/events", **params)["data"])
def cmd_leagues(args: argparse.Namespace) -> None:
for code, name in LEAGUES.items():
print(f"{code:<16} {name}")
def main() -> None:
load_dotenv(Path(__file__).with_name(".env"))
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
sub = ap.add_subparsers(dest="cmd", required=True)
s = sub.add_parser("scores"); s.add_argument("--league", default="eng.1"); s.add_argument("--date"); s.set_defaults(fn=cmd_scores)
l = sub.add_parser("leagues"); l.set_defaults(fn=cmd_leagues)
args = ap.parse_args()
args.fn(args)
if __name__ == "__main__":
main()
5. Run it
On 5 November 2026, scores --league usa.1 --date 2026-11-01 listed [761927] SEA 1 @ VAN 5 FT, and the Premier League scoreboard showed the next fixture, COV @ EVE on 6 November.
Terminal
python soccer.py scores # Premier League
python soccer.py scores --league usa.1 --date 2026-11-01 # MLS on a day
python soccer.py leagues # league codes6. Going further
Each league has its own page with teams and endpoints: Premier League, LaLiga, MLS. Soccer box scores carry team totals and period scores only, not player stats. Data typically runs 20-30 seconds behind live play.
Endpoints used
GET /sports/soccer/leagues/{league}/events
Full reference: docs · OpenAPI · what each endpoint returns, by league
FAQ
- Is there a free soccer API for Python?
- A free key (no card) gives 1,000 calls in the first 30 days, then 125 a month, and includes every endpoint. The same key covers every soccer league here, plus the US sports.
- Which soccer leagues are covered?
- Run `python soccer.py leagues` for the codes this script knows. The full list of monitored leagues is on the API pages.
- Does it include player stats for soccer?
- Not currently. Soccer box scores return team totals and period scores; player stats are not returned.