football-data

Football (soccer) data across the world's major leagues — standings, schedules, match stats, xG, transfers, player profiles, head-to-head history, team strength (Elo), and match forecasts. Zero config, no API keys. Covers Premier League, La Liga, Bundesliga, Serie A, Ligue 1, MLS, Champions League,

By machina-sports · 2,133 installs

npx skills add machina-sports/sports-skills --skill football-data

Source repository · Upstream listing

Football Data Before writing queries, consult references/api reference.md for endpoints, ID conventions, and data shapes. Setup Before first use, check if the CLI is available: If pip install fails (package not found or Python version error), install from GitHub: The package requires Python 3.10+. If your default Python is older, use a specific version: No API keys required. Quick Start Prefer the CLI — it avoids Python import path issues: Python SDK (alternative): CRITICAL: Before Any Query CRITICAL: Before calling any data endpoint, verify: Season ID is derived from get current season(competition id="...") — never hardcoded. Team ID is resolved via search team(query="...") and passed as the numeric team id . For get head to head , get team strength , and get match forecast , always pass IDs — ambiguous names (e.g. two "Paris" clubs) can resolve to the wrong team. The endpoint actually covers the league in question — see the Coverage & Source Map below. Coverage is uneven across sources; an uncovered call returns an empty payload with a message , not data. get event xg and get event players statistics (with xG) are only called for top 5 leagues (EPL, La Liga, Bundesliga, Serie A, Ligue 1). get season leaders and get missing players are only called for Premier League seasons (season id must start with premier league ). Choosing the Season Derive the current year from the system prompt's date (e.g., currentDate: 2026 02 16 → current year is 2026). If the user specifies a season , use it as is. If the user says "current", "latest", or doesn't specify : Call get current season(competition id="...") to get the active season id. Do NOT guess or hardcode the year. Season format : Always {league slug} {year} (e.g., "premier league 2025" for the 2025 26 season). The year is the start year of the season, not the end year. MLS exception : MLS runs spring fall within a single calendar year. Use get current season(competition id="mls") . Coverage & Source Map This skill stitches several free sources together. Coverage is not uniform — each endpoint works only where its underlying source has data. Check this before promising an answer; when an endpoint isn't covered, it returns an empty payload with an explanatory message (never an error) — read that message and fall back. Endpoint(s) Source Coverage standings, schedules, teams, event summary/lineups/stats/timeline ESPN All leagues (broadest — the backbone) get event xg , get event players statistics (xG fields) Understat Top 5 only (EPL, La Liga, Bundesliga, Serie A, Ligue 1). Not RFPL — Understat dropped it. get season leaders , get missing players FPL Premier League only get player profile , get season transfers (market value) Transfermarkt Any player with a tm player id get head to head football data.co.uk 11 European domestic leagues (EPL, Championship, La Liga, Serie A, Bundesliga, Ligue 1, Eredivisie, Primeira Liga, Scottish, Belgian, Turkish). Same division meetings only. get team strength ClubElo, falling back to local Elo European clubs (incl. Russia). Falls back to ratings computed from football data.co.uk when ClubElo is down. get match forecast ClubElo European clubs (incl. Russia). No fallback — needs ClubElo's fixture feed. Rule of thumb: ESPN answers "what happened" everywhere; the enrichment sources ( Understat/FPL/ClubElo/football data.co.uk ) add depth only in their coverage zone. ESPN is always the fixture/score authority — never let an enrichment source override an ESPN score. Gotchas (from live testing) get team profile returns the squad. data.players[] carries the current roster with ESPN athlete ids, shirt numbers and ages — use it instead of collecting names match by match. get player season stats takes the same league slug as everything else ( serie a brazil , not only ESPN's bra.1 ), and its gamelog is the last ~5 matches across competitions, not a season total. Scored penalties are penalty goal in the timeline. Count goal + penalty goal + own goal when reconciling with the score. Pass IDs, not ambiguous names. For H2H/strength/forecast, resolve teams with search team first and pass the numeric team id . Names like "Paris Saint Germain" can collapse onto the wrong club (Paris FC) during name resolution. ClubElo off season gaps : current date get team strength can miss clubs in the summer break (a club's weekly Elo period may not span today). If a well known club returns unresolved, pass an in season date (e.g. date="2026 03 01" ). ClubElo outages : get team strength falls back to locally computed Elo and sets source: "local elo" . Check that field before comparing numbers across calls — the local scale is division local, so a rating means nothing outside its own division and cross division comparisons are refused. The fallback honours date (it rates the division as of that date, and each entry's as of is the last match counted). get match forecast has no fallback and stays empty. get match forecast is short horizon : ClubElo only forecasts ~a week ahead — empty between matchdays / off season. That's expected, not a failure. H2H is same division only : two clubs that met in a cup or across tiers won't show; it counts league meetings in the resolved division. H2H tells "unresolved" apart from "never met" : football data.co.uk uses short exonyms/abbreviations ("FC Koln", "M'gladbach", "Sp Lisbon"). Each club in teams[] reports resolved + matched as ; if a club is resolved: false , zero meetings means the lookup failed, not that the clubs never played. Combining Endpoints (mix and match) Compose sources for richer answers. Run independent calls in parallel. Match preview ( X vs Y ): search team ×2 → get head to head (recent record) + get team strength(team id, team id 2) (Elo gap / favorite) + get match forecast (if within ~a week: W/D/L + scoreline). For a top 5 fixture add historical get event xg context from recent meetings. Match report (post game): get event summary + get event statistics + get event timeline , and for top 5 leagues get event xg + get event players statistics . Team form + context : get team schedule (recent results) + get team strength (current Elo & rank) + get missing players (PL only) + per match get event xg (top 5). Rivalry / derby deep dive : get head to head (all time ish record + goals) + get team strength comparison for the current power balance. Odds sanity check : get match forecast gives a free model baseline (W/D/L) to compare against the kalshi / polymarket betting skills. When a piece of the composition isn't covered (e.g. xG outside the top 5, H2H for MLS), skip it silently and deliver the parts that are covered — don't block the whole answer on one missing source. Commands Command Description get current season Detect current season for a competition get competitions List available competitions with current season info get competition seasons Available seasons for a competition get season schedule Full season match schedule get season standings League table for a season get season leaders Top scorers/leaders (Premier League only) get season teams Teams in a season search team Search for a team by name search player Search for a player by name get team profile Team info + current squad (roster) get daily schedule All matches for a date across all leagues get event summary Match summary with scores get event lineups Match lineups get event statistics Match team statistics get event timeline Match timeline (goals, cards, subs) get team schedule Schedule for a specific team get head to head Historical H2H results + stats (European domestic leagues) get team strength Elo rating / two team comparison (European clubs); local Elo fallback if ClubElo is down get match forecast ClubElo win/draw/loss + scoreline forecast (~week ahead) get event xg xG data (top 5 leagues only) get event players statistics Player level match stats with optional xG get missing players Injured/doubtful players (Premier League only) get season transfers Transfer history via Transfermarkt get player season stats Player season stats via ESPN get player profile Player profile (FPL and/or Transfermarkt) See references/api reference.md for full parameter lists, return shapes, and data coverage table. Examples Example 1: Premier League table User says: "Show me the Premier League table" Actions: 1. Call get current season(competition id="premier league") to get the current season id 2. Call get season standings(season id=<season id from step 1 ) Result: Standings table with position, team, played, won, drawn, lost, GD, points Example 2: Match report User says: "How did Arsenal vs Liverpool go?" Actions: 1. Call get daily schedule() or get team schedule(team id="359") to find the event id 2. Call get event summary(event id="...") for the score 3. Call get event statistics(event id="...") for possession, shots, etc. 4. Call get event xg(event id="...") for xG comparison (EPL — top 5 only) Result: Match report with scores, key stats, and xG Example 3: Team deep dive User says: "Deep dive on Chelsea's recent form" Actions: 1. Call search team(query="Chelsea") → team id=363, competition=premier league 2. Call get team schedule(team id="363", competition id="premier league") → find recent closed events 3. For each recent match, call in parallel: get event xg , get event statistics , get event players statistics 4. Call get missing players(season id=<season id ) → filter Chelsea's injured/doubtful players Result: xG trend across matches, key player stats, and injury report Example 4: Player market value User says: "What's Saka's market value?" Actions: 1. Call get player profile(tm player id="433177") for Transfermarkt data 2. Optionally add fpl id for FPL stats Result: Market value, value history, and transfer history Example 5: Non PL club User says: "Tell me about Corinthians" Actions: 1. Call search team(query="Corinthians") → team id=874, competition=serie a brazil 2. Call get team schedule(team id="874", competition id="serie a brazil") for fixtures 3. Pick a recent match and call get event timeline(event id="...") for goals, cards, subs Result: Fixtures, timeline events (note: xG, FPL stats, and season leaders NOT available for Brazilian Serie A) Example 6: Match preview (mix and match) User says: "Preview Arsenal vs Man City this weekend" Actions: 1. Call search team(query="Arsenal") and search team(query="Manchester City") → team ids 359, 382 2. In parallel: get head to head(team id="359", team id 2="382") (recent record + goals), get team strength(team id="359", team id 2="382") (Elo gap + favorite), get match forecast(team id="359", team id 2="382") (W/D/L + likely scoreline, if within ~a week) 3. Synthesize: form/record + power balance + model odds. Skip any piece that returns empty (e.g. forecast if the match is 1 week out). Result: A preview blending head to head history, current strength, and a free model forecast Commands that DO NOT exist — never call these ~~ get standings ~~ — the correct command is get season standings (requires season id ). ~~ get live scores ~~ — not available. Use get daily schedule() for today's matches. ~~ get team squad ~~ / ~~ get team roster ~~ — use get team profile : data.players[] is the current roster with ESPN athlete ids (see Gotchas). get season leaders + get player profile remain the path for career data. ~~ get transfers ~~ — the correct command is