Skip to main content

Unofficial open-source football match data toolkit using public sources.

Project description

openmatchkit

CI PyPI Release Python License: MIT

Unofficial open-source football match data toolkit for fixtures, results, best-effort live score adapters, standings, exports, and simple prediction models.

This project is unofficial and not affiliated with FIFA, any league, club, broadcaster, federation, or data provider. It does not provide official FIFA data.

Why openmatchkit?

openmatchkit gives Python developers a clean, source-attributed way to work with public football match facts without paid API keys. It starts with open/public datasets, keeps scraping optional and conservative, and returns structured JSON-ready models.

Install

pip install openmatchkit

From GitHub:

pip install git+https://github.com/patilprashan246/openmatchkit.git@v0.3.0

For local development:

python -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
pytest

Quick Start

from openmatchkit import MatchClient

client = MatchClient()
next_match = client.next_match(competition="worldcup", season="2026")

print(next_match.model_dump(mode="json"))
openmatch next-match --competition worldcup --season 2026

Python API

from openmatchkit import MatchClient

client = MatchClient()

fixtures = client.fixtures(competition="worldcup", season="2026")
results = client.results(competition="worldcup", season="2026")
live = client.live_scores()
next_match = client.next_match(competition="worldcup", season="2026")
prediction = client.predict(home="Mexico", away="South Africa", history=results)

client.export_json(fixtures, "fixtures.json")
client.export_csv(fixtures, "fixtures.csv")

League datasets from OpenFootball can be fetched with codes such as:

matches = client.fixtures(competition="en.1", season="2015-16")

Functionality Reference

All public models are Pydantic models. Use .model_dump(mode="json") when you want JSON-ready dictionaries, or use the CLI commands when you want JSON printed directly.

Source Metadata

client.source_capabilities()
client.source_health()

Returns source capability and local health metadata:

[
  {
    "source": "openfootball",
    "fixtures": true,
    "results": true,
    "live_scores": false,
    "scoreboards": true,
    "player_history": false,
    "standings": true,
    "prediction_history": true,
    "notes": [
      "OpenFootball provides fixtures/results; detailed player data is unavailable."
    ]
  }
]

Fixtures, Results, Search, Upcoming, Recent

fixtures = client.fixtures("worldcup", "2026")
results = client.results("worldcup", "2026")
matches = client.search_matches("worldcup", "2026", team="Canada", status="scheduled")
upcoming = client.upcoming_matches("worldcup", "2026", team="Canada", limit=3)
recent = client.recent_results("worldcup", "2026", limit=5)
next_match = client.next_match("worldcup", "2026")
match = client.match_by_id(match_id="...", competition="worldcup", season="2026")

Each item is a Match:

{
  "match_id": "ded80f9a2a529045",
  "competition": "World Cup 2026",
  "season": "2026",
  "round": "Matchday 2",
  "group": "Group B",
  "kickoff": "2026-06-12T15:00:00-04:00",
  "home": {"name": "Canada", "code": null, "country": null},
  "away": {"name": "Bosnia & Herzegovina", "code": null, "country": null},
  "score": {"home": null, "away": null},
  "status": "scheduled",
  "venue": "Toronto",
  "source": "openfootball",
  "source_url": "https://raw.githubusercontent.com/openfootball/worldcup.json/master/2026/worldcup.json",
  "fetched_at": "2026-06-12T10:46:21.427460Z"
}

Scoreboards and Match Summaries

summary = client.match_summary(match_id="detail-1", competition="Demo Cup", season="2026")
scoreboard = client.scoreboard(match_id="detail-1")
scoreboards = client.scoreboards(competition="Demo Cup", season="2026")
live_boards = client.live_scoreboards()

Scoreboard can include match clock, lineups, events, team stats, and player stats when the configured source provides them:

{
  "match": {
    "match_id": "detail-1",
    "competition": "Demo Cup",
    "home": {"name": "Team A"},
    "away": {"name": "Team B"},
    "score": {"home": 1, "away": 0},
    "status": "live"
  },
  "clock": {"minute": 45, "added_time": 2, "period": "first_half", "display": "45+2"},
  "events": [
    {
      "event_type": "goal",
      "team": "Team A",
      "player": "Alex Demo",
      "assist": "Sam Creator",
      "minute": 34,
      "home_score": 1,
      "away_score": 0
    }
  ],
  "team_stats": [
    {"team": "Team A", "possession": 58.4, "shots": 7, "shots_on_target": 3}
  ],
  "player_stats": [
    {"player": {"name": "Alex Demo", "team": "Team A"}, "goals": 1, "minutes_played": 45}
  ],
  "source_notes": ["Demo fixture representing an authorized detailed public JSON feed."]
}

Teams, Standings, Form, Head-to-Head

teams = client.teams("worldcup", "2026")
table = client.standings("worldcup", "2026", group="Group A")
form = client.team_form("Mexico", "worldcup", "2026", last=5)
h2h = client.head_to_head("Mexico", "South Africa", "worldcup", "2026")

TeamForm returns recent results from the team perspective:

{
  "team": "Mexico",
  "competition": "worldcup",
  "season": "2026",
  "requested_last": 5,
  "played": 1,
  "wins": 1,
  "draws": 0,
  "losses": 0,
  "goals_for": 2,
  "goals_against": 0,
  "goal_difference": 2,
  "points": 3,
  "form": ["W"],
  "matches": [
    {
      "opponent": "South Africa",
      "home_away": "home",
      "team_score": 2,
      "opponent_score": 0,
      "result": "W"
    }
  ]
}

HeadToHeadSummary returns aggregate history plus latest matches:

{
  "team_a": "Mexico",
  "team_b": "South Africa",
  "matches": 1,
  "team_a_wins": 1,
  "draws": 0,
  "team_b_wins": 0,
  "team_a_goals": 2,
  "team_b_goals": 0,
  "latest_matches": []
}

Player History

Player history depends on a source that legally provides player-level public match facts. The default OpenFootball adapter does not include player stats, but JsonFileSource supports detailed authorized feeds:

from openmatchkit import MatchClient
from openmatchkit.sources.json_file import JsonFileSource

client = MatchClient(sources=[JsonFileSource("tests/fixtures/sample_detailed_source.json")])
history = client.player_history("Alex Demo")
print(history.model_dump(mode="json"))
{
  "player": {"name": "Alex Demo", "team": "Team A", "position": "FW", "shirt_number": 9},
  "totals": {
    "appearances": 1,
    "starts": 1,
    "minutes_played": 45,
    "goals": 1,
    "assists": 0,
    "yellow_cards": 1,
    "red_cards": 0
  },
  "appearances": [
    {
      "match_id": "detail-1",
      "team": "Team A",
      "opponent": "Team B",
      "home_away": "home",
      "goals": 1,
      "source": "demo_public_feed"
    }
  ]
}

Prediction

history = client.results("worldcup", "2026")
prediction = client.predict(home="Mexico", away="South Africa", history=history)

Returns an educational baseline only:

{
  "home": "Mexico",
  "away": "South Africa",
  "home_win_probability": 0.45,
  "draw_probability": 0.27,
  "away_win_probability": 0.28,
  "expected_home_goals": 1.2,
  "expected_away_goals": 0.9,
  "model": "simple_poisson",
  "training_matches": 2,
  "note": "Educational baseline only. Not betting, financial, or professional advice."
}

Export

client.export_json(fixtures, "fixtures.json")
client.export_csv(fixtures, "fixtures.csv")

JSON export keeps full nested model data. CSV export flattens match-level fields for spreadsheet tools.

CLI

openmatch sources
openmatch health
openmatch fixtures --competition worldcup --season 2026
openmatch search --competition worldcup --season 2026 --team Canada --status scheduled
openmatch results --competition en.1 --season 2015-16 --format csv --output results.csv
openmatch upcoming --competition worldcup --season 2026 --team Canada --limit 3
openmatch recent --competition worldcup --season 2026 --limit 5
openmatch next-match --competition worldcup --season 2026
openmatch match-summary --match-id detail-1 --data-file tests/fixtures/sample_detailed_source.json
openmatch standings --competition worldcup --season 2026
openmatch team-form --team Mexico --competition worldcup --season 2026
openmatch head-to-head --team-a Mexico --team-b "South Africa" --competition worldcup --season 2026
openmatch predict --home Mexico --away "South Africa" --competition worldcup --season 2026

Detailed JSON feeds can expose richer scoreboards and player history:

openmatch scoreboards --data-file tests/fixtures/sample_detailed_source.json
openmatch scoreboard --match-id detail-1 --data-file tests/fixtures/sample_detailed_source.json
openmatch live-scoreboards --data-file tests/fixtures/sample_detailed_source.json
openmatch player-history --player "Alex Demo" --data-file tests/fixtures/sample_detailed_source.json
from openmatchkit import MatchClient
from openmatchkit.sources.json_file import JsonFileSource

client = MatchClient(sources=[JsonFileSource("tests/fixtures/sample_detailed_source.json")])
scoreboard = client.scoreboard(match_id="detail-1")
history = client.player_history("Alex Demo")
print(scoreboard.model_dump(mode="json"))
print(history.model_dump(mode="json"))

Example Output

{
  "competition": "World Cup 2026",
  "home": {"name": "Canada"},
  "away": {"name": "Bosnia & Herzegovina"},
  "status": "scheduled",
  "source": "openfootball"
}

Features

  • Unified match, scoreboard, player history, standings, and prediction models
  • OpenFootball JSON adapter
  • Football-Data.co.uk CSV adapter
  • Local detailed JSON adapter for authorized/public detailed feeds
  • Generic optional public HTML adapter
  • Safe HTTP client with robots.txt checks, caching, user agent, and per-origin delay
  • Fixtures, results, search, upcoming/recent matches, next match, live score adapter interface
  • Source capabilities and health metadata
  • Team info, grouped standings, team form, and head-to-head summaries
  • Detailed scoreboards: clock, events, lineups, team stats, and player match stats when provided
  • Player histories aggregated from player-level source data
  • Simple Poisson prediction baseline and small Elo rating helper
  • JSON and CSV export helpers
  • Offline tests using local fixtures

Current Status

  • Stable enough for demos, research, education, and early open-source feedback
  • Not official live FIFA data
  • True live/player-level data requires a lawful source adapter that provides those facts
  • Public roadmap: ROADMAP.md
  • Release notes: CHANGELOG.md

Source and legal policy

The package code is MIT licensed. Third-party data sources have their own licenses and terms. Optional scraping adapters must respect Terms of Service, robots.txt, caching, and rate limits. Player-level data should only come from public or authorized sources and should contain public sporting facts, not private or sensitive information.

See DATA_SOURCES.md, PRIVACY.md, and CONTRIBUTING.md.

Development

python -m pip install -e ".[dev]"
ruff check .
ruff format .
pytest
python -m build

The prediction output is an educational baseline only. It is not betting, financial, or professional advice.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openmatchkit-0.3.0.tar.gz (29.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openmatchkit-0.3.0-py3-none-any.whl (26.9 kB view details)

Uploaded Python 3

File details

Details for the file openmatchkit-0.3.0.tar.gz.

File metadata

  • Download URL: openmatchkit-0.3.0.tar.gz
  • Upload date:
  • Size: 29.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openmatchkit-0.3.0.tar.gz
Algorithm Hash digest
SHA256 7b6c9fdadc3a83ce81522c2717ae9ecf7fe60630db8bf30ab453a0e092345acb
MD5 5227361614252d274cc0a6d2332f14f2
BLAKE2b-256 7a03e0b7954459b996adc63cc90260303cc044190d669b59141a63dc5fabe1c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for openmatchkit-0.3.0.tar.gz:

Publisher: publish.yml on patilprashan246/openmatchkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openmatchkit-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: openmatchkit-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 26.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openmatchkit-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 175315b5a7c09e08499c00477ce375e5b5a2db163c91402a4b342a3d5abe18d5
MD5 9d9db96d4ad86b8fe18b7d971f1f546e
BLAKE2b-256 49d03a06bed9b9811eac2d55710e4a21c8e7d6e012de0c9ec57b3f13a579c5a5

See more details on using hashes here.

Provenance

The following attestation bundles were made for openmatchkit-0.3.0-py3-none-any.whl:

Publisher: publish.yml on patilprashan246/openmatchkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page