
Football Data
- 11 installs
- 82 repo stars
- Updated August 2, 2026
- aaaaqwq/agi-super-skills
football-data is a Claude Code skill that returns football/soccer standings, fixtures, match stats, xG, transfers, and player profiles across 13 leagues with no API keys.
About
football-data is a Claude Code skill that provides football/soccer data across 13 leagues, including standings, schedules, match stats, xG, transfers, and player profiles. A developer uses it via a CLI or Python SDK to answer questions about league tables, fixtures, and player values with no API keys required. Data comes from ESPN, Understat, FPL, and Transfermarkt and updates post-match rather than live.
- Football/soccer data across 13 leagues with zero config and no API keys
- Standings, fixtures, match stats, xG, transfers, and player profiles
- CLI plus Python SDK backed by ESPN, Understat, FPL, and Transfermarkt
Football Data by the numbers
- 11 all-time installs (skills.sh)
- Ranked #1,550 of 2,065 Data Science & ML skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
football-data capabilities & compatibility
Free; no API keys, installed via pip (sports-skills).
- Capabilities
- data analysis · research
- Use cases
- data analysis · research
- Pricing
- Free
What football-data says it does
Football (soccer) data across 13 leagues — standings, schedules, match stats, xG, transfers, player profiles. Zero config, no API keys.
No API keys required.
npx skills add https://github.com/aaaaqwq/agi-super-skills --skill football-dataAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 11 |
|---|---|
| repo stars | ★ 82 |
| Last updated | August 2, 2026 |
| Repository | aaaaqwq/agi-super-skills ↗ |
What it does
Pull football/soccer data (standings, fixtures, match stats, xG, transfers, player profiles) across 13 leagues with no API keys.
Who is it for?
Answering questions on soccer standings, fixtures, match stats, xG, and player values across major leagues.
Skip if: American football, other sports, betting odds, or live real-time scores; data updates post-match.
When should I use this skill?
A user asks about football/soccer standings, fixtures, match stats, xG, transfers, or player profiles.
What you get
League tables, fixtures, match stats, and player data across 13 leagues from one CLI.
- League standings
- Fixtures and schedules
- Match statistics and xG
By the numbers
- 13 leagues covered
- xG for top 5 leagues only
- Python 3.10+ required
Files
Football Data
Setup
Before first use, check if the CLI is available:
which sports-skills || pip install sports-skillsIf pip install fails (package not found or Python version error), install from GitHub:
pip install git+https://github.com/machina-sports/sports-skills.gitThe package requires Python 3.10+. If your default Python is older, use a specific version:
python3 --version # check version
# If < 3.10, try: python3.12 -m pip install sports-skills
# On macOS with Homebrew: /opt/homebrew/bin/python3.12 -m pip install sports-skillsNo API keys required.
Quick Start
Prefer the CLI — it avoids Python import path issues:
sports-skills football get_daily_schedule
sports-skills football get_season_standings --season_id=premier-league-2025Python SDK (alternative):
from sports_skills import football
standings = football.get_season_standings(season_id="premier-league-2025")
schedule = football.get_daily_schedule()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")— don't assume MLS follows European calendar. - Never hardcode a season_id. Always derive it via
get_current_season()or from the system date.
Data Coverage by League
Not all data is available for every league. Use the right command for the right league.
| Command | All 13 leagues | Top 5 only | PL only |
|---|---|---|---|
| get_season_standings | x | ||
| get_daily_schedule | x | ||
| get_season_schedule | x | ||
| get_season_teams | x | ||
| search_team | x | ||
| get_team_schedule | x | ||
| get_team_profile | x | ||
| get_event_summary | x | ||
| get_event_lineups | x | ||
| get_event_statistics | x | ||
| get_event_timeline | x | ||
| get_current_season | x | ||
| get_competitions | x | ||
| get_event_xg | x | ||
| get_event_players_statistics (with xG) | x | ||
| get_season_leaders | x | ||
| get_missing_players | x |
Top 5 leagues (Understat): EPL, La Liga, Bundesliga, Serie A, Ligue 1. PL only (FPL): Premier League — injury news, player stats, ownership, ICT index. All leagues: via ESPN — scores, standings, schedules, match summaries, lineups, team stats. Transfermarkt: Works for any player with a tm_player_id — market values and transfer history.
Note: MLS uses a different season structure (spring-fall calendar). Use get_current_season(competition_id="mls") to detect the right season_id.
ID Conventions
- season_id:
{league-slug}-{year}e.g."premier-league-2025","la-liga-2025" - competition_id: league slug e.g.
"premier-league","serie-a","champions-league" - team_id: ESPN team ID (numeric string) e.g.
"359"(Arsenal),"86"(Real Madrid) - event_id: ESPN event ID (numeric string) e.g.
"740847" - fpl_id: FPL element ID or code (PL players only)
- tm_player_id: Transfermarkt player ID e.g.
"433177"(Saka),"342229"(Mbappe)
Commands
get_current_season
Detect current season for a competition. Works for all leagues.
competition_id(str, required): Competition slug
Returns data.competition and data.season:
{"competition": {"id": "premier-league", "name": "Premier League"}, "season": {"id": "premier-league-2025", "name": "2025-26 English Premier League", "year": "2025"}}get_competitions
List available competitions with current season info. No params. Works for all leagues.
Returns data.competitions[] with id, name, code, current_season.
get_competition_seasons
Get available seasons for a competition. Works for all leagues.
competition_id(str, required): Competition slug
get_season_schedule
Get full season match schedule. Works for all leagues.
season_id(str, required): Season slug (e.g., "premier-league-2025")
Returns data.schedules[] — same shape as events below.
get_season_standings
Get league table for a season. Works for all leagues.
season_id(str, required): Season slug
Returns data.standings[].entries[]:
{
"position": 1,
"team": {"id": "359", "name": "Arsenal", "short_name": "Arsenal", "abbreviation": "ARS", "crest": "https://..."},
"played": 26, "won": 17, "drawn": 6, "lost": 3,
"goals_for": 50, "goals_against": 18, "goal_difference": 32, "points": 57
}get_season_leaders
Get top scorers/leaders for a season. Premier League only (via FPL).
season_id(str, required): Season slug (must bepremier-league-*)
Returns data.leaders[] — note: player name is nested under .player.name:
{
"player": {"id": "223094", "name": "Erling Haaland", "first_name": "Erling", "last_name": "Haaland", "position": "Forward"},
"team": {"id": "43", "name": "Man City"},
"goals": 22, "assists": 6, "penalties": 0, "played_matches": 25
}Returns empty for non-PL leagues.
get_season_teams
Get teams in a season. Works for all leagues.
season_id(str, required): Season slug
search_team
Search for a team by name across all leagues (or a specific one). Uses fuzzy matching.
query(str, required): Team name to search (e.g., "Corinthians", "Barcelona", "Man Utd")competition_id(str, optional): Limit search to one league (e.g., "serie-a-brazil", "premier-league")
Returns data.results[] with team, competition, and season for each match:
{"team": {"id": "874", "name": "Corinthians"}, "competition": {"id": "serie-a-brazil", "name": "Serie A Brazil"}, "season": {"id": "serie-a-brazil-2025", "year": "2025"}}get_team_profile
Get basic team info (name, crest, venue). Does not return squad/roster — use get_season_leaders to find PL player IDs, then get_player_profile for individual player data.
team_id(str, required): ESPN team IDleague_slug(str, optional): League hint (faster resolution)
Returns data.team and data.venue. data.players[] is empty — see "Deep dive on a PL team" example below for the recommended workflow.
get_daily_schedule
Get all matches for a specific date across all leagues.
date(str, optional): Date in YYYY-MM-DD format. Defaults to today.
Returns data.date and data.events[]:
{
"id": "748381", "status": "not_started", "start_time": "2026-02-16T20:00Z",
"competition": {"id": "la-liga", "name": "La Liga"},
"season": {"id": "la-liga-2025", "year": "2025"},
"venue": {"name": "Estadi Montilivi", "city": "Girona"},
"competitors": [
{"team": {"id": "9812", "name": "Girona", "abbreviation": "GIR"}, "qualifier": "home", "score": 0},
{"team": {"id": "83", "name": "Barcelona", "abbreviation": "BAR"}, "qualifier": "away", "score": 0}
],
"scores": {"home": 0, "away": 0}
}Status values: "not_started", "live", "halftime", "closed", "postponed".
get_event_summary
Get match summary with scores. Works for all leagues.
event_id(str, required): Match/event ID
Returns data.event (same shape as daily schedule events).
get_event_lineups
Get match lineups. Works for all leagues (when available from ESPN).
event_id(str, required): Match/event ID
Returns data.lineups[]:
{
"team": {"id": "364", "name": "Liverpool", "abbreviation": "LIV"},
"qualifier": "home",
"formation": "4-3-3",
"starting": [{"id": "275599", "name": "Caoimhín Kelleher", "position": "Goalkeeper", "shirt_number": 1}],
"bench": [{"id": "...", "name": "...", "position": "...", "shirt_number": 62}]
}get_event_statistics
Get match team statistics. Works for all leagues.
event_id(str, required): Match/event ID
Returns data.teams[]:
{
"team": {"id": "244", "name": "Brentford"},
"qualifier": "home",
"statistics": {"ball_possession": "40.8", "shots_total": "10", "shots_on_target": "3", "fouls": "12", "corners": "4"}
}get_event_timeline
Get match timeline/key events (goals, cards, substitutions). Works for all leagues.
event_id(str, required): Match/event ID
Returns data.timeline[] with goal, card, and substitution events.
get_team_schedule
Get schedule for a specific team — includes both past results and upcoming fixtures. Works for all leagues.
team_id(str, required): ESPN team IDleague_slug(str, optional): League hint (faster resolution)season_year(str, optional): Season year filtercompetition_id(str, optional): Filter results to a single competition (e.g., "serie-a-brazil", "premier-league")
get_head_to_head
UNAVAILABLE — requires licensed data. Do not call this command; it will return empty results. Instead, use get_team_schedule for both teams and filter overlapping matches manually.
team_id(str, required): First team IDteam_id_2(str, required): Second team ID
get_event_xg
Get expected goals (xG) data from Understat. Top 5 leagues only: EPL, La Liga, Bundesliga, Serie A, Ligue 1. Returns empty for other leagues.
event_id(str, required): Match/event ID
Returns data.teams[] and data.shots[]:
{"team": {"id": "244", "name": "Brentford"}, "qualifier": "home", "xg": 1.812}data.shots[] contains individual shot data with xG per shot. Note: very recent matches (last 24-48h) may not be indexed on Understat yet.
get_event_players_statistics
Get player-level match statistics with xG enrichment. Works for all leagues (basic stats from ESPN). xG/xA enrichment only for top 5 leagues (Understat).
event_id(str, required): Match/event ID
Returns data.teams[].players[]:
{
"id": "...", "name": "Bukayo Saka", "position": "Midfielder", "shirt_number": 7, "starter": true,
"statistics": {"appearances": "1", "shotsTotal": "3", "shotsOnTarget": "1", "foulsCommitted": "1", "xg": "0.45", "xa": "0.12"}
}xg and xa fields only present for top 5 leagues.
get_missing_players
Get injured/missing/doubtful players. Premier League only (via FPL). Returns empty for other leagues.
season_id(str, required): Season slug (must bepremier-league-*)
Returns data.teams[].players[]:
{
"id": "463748", "name": "Mikel Merino Zazón", "web_name": "Merino",
"position": "Midfielder", "status": "injured",
"news": "Foot injury - Unknown return date",
"chance_of_playing_this_round": 0, "chance_of_playing_next_round": 0
}Status values: "injured", "unavailable", "doubtful", "suspended".
get_season_transfers
Get transfer history for specific players via Transfermarkt. Works for any league.
season_id(str, required): Season slug (used to filter transfers by year)tm_player_ids(list, required): Transfermarkt player IDs
Returns data.transfers[]:
{
"player_tm_id": "433177", "date": "2019-07-01", "season": "19/20",
"from_team": {"name": "Arsenal U23", "image": "https://..."},
"to_team": {"name": "Arsenal", "image": "https://..."},
"fee": "-", "market_value": "-"
}get_player_season_stats
Get player season stats via ESPN overview endpoint. Works for any league with ESPN athlete IDs.
player_id(str, required): ESPN athlete IDleague_slug(str, optional): League slug hint (e.g., "eng.1", "esp.1"). Defaults to auto-detect.
Returns season stats (goals, assists, appearances, etc.) and game log when available.
get_player_profile
Get player profile. Works for any player if you have their Transfermarkt or FPL ID. At least one ID required.
fpl_id(str, optional): FPL player ID (PL players only)tm_player_id(str, optional): Transfermarkt player ID (any league)
With tm_player_id, returns data.player with:
{
"market_value": {"value": 130000000, "currency": "EUR", "formatted": "€130.00m", "date": "09/12/2025", "age": "24", "club": "Arsenal FC"},
"market_value_history": [{"value": 7000000, "formatted": "€7.00m", "date": "23/09/2019", "club": "Arsenal FC"}],
"transfer_history": [
{"player_tm_id": "433177", "date": "2019-07-01", "season": "19/20", "from_team": {"name": "Arsenal U23"}, "to_team": {"name": "Arsenal"}, "fee": "-"}
]
}With fpl_id, also includes data.player.fpl_data with FPL stats (points, form, ICT index, ownership, etc.).
Supported Leagues
Premier League, La Liga, Bundesliga, Serie A, Ligue 1, MLS, Championship, Eredivisie, Primeira Liga, Serie A Brazil, Champions League, European Championship, World Cup.
Data Sources
| Source | What it provides | League coverage |
|---|---|---|
| ESPN | Scores, standings, schedules, lineups, match stats, timelines | All 13 leagues |
| openfootball | Schedules, standings, team lists (fallback when ESPN is down) | 10 leagues (all except CL, Euros, World Cup) |
| Understat | xG per match, xG per shot, player xG/xA | Top 5 (EPL, La Liga, Bundesliga, Serie A, Ligue 1) |
| FPL | Top scorers, injuries, player stats, ownership | Premier League only |
| Transfermarkt | Market values, transfer history | Any player (requires tm_player_id) |
For licensed data with full coverage across all sports (Sportradar, Opta, Genius Sports), see Machina Sports.
Examples
User: "Show me the Premier League table" 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>) 3. Present standings table with position, team, played, won, drawn, lost, GD, points
User: "How did Arsenal vs Liverpool go?" 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) 5. Present match report with scores, key stats, and xG
User: "Deep dive on Chelsea's recent form" 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(event_id="...")for xG comparison and shot mapget_event_statistics(event_id="...")for possession, shots, passesget_event_players_statistics(event_id="...")for individual player xG/xA
4. Call get_missing_players(season_id=<season_id>) → filter Chelsea's injured/doubtful players 5. Call get_season_leaders(season_id=<season_id>) → filter Chelsea players, get their FPL IDs 6. Call get_player_profile(fpl_id="...", tm_player_id="...") for key players — combine FPL stats (form, ownership, ICT) with Transfermarkt data (market value, transfer history) 7. Present: xG trend across matches, key player stats, injury report, market values
User: "What's Saka's market value?" 1. Call get_player_profile(tm_player_id="433177") for Transfermarkt data 2. Optionally add fpl_id for FPL stats if Premier League player 3. Present market value, value history, and transfer history
User: "Tell me about Corinthians" 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 4. Note: xG, FPL stats, and season leaders are NOT available for Brazilian Serie A
Error Handling
When a command fails (wrong event_id, missing data, network error, etc.), do not surface the raw error to the user. Instead:
1. Catch it silently — treat the failure as an exploratory miss, not a fatal error. 2. Try alternatives — e.g., if an event_id returns no data, call get_daily_schedule() or get_team_schedule() to discover the correct ID. If ESPN is down, openfootball data may still be available via get_season_standings or get_season_schedule. 3. Only report failure after exhausting alternatives — and when you do, give a clean human-readable message (e.g., "I couldn't find that match — can you confirm the teams or date?"), not a traceback or raw CLI output.
This is especially important when the agent is responding through messaging platforms (Telegram, Slack, etc.) where raw exec failures look broken.
Common Mistakes
These are the ONLY valid commands. Do not invent or guess command names:
get_current_seasonget_competitionsget_competition_seasonsget_season_scheduleget_season_standingsget_season_leadersget_season_teamssearch_teamget_team_profileget_daily_scheduleget_event_summaryget_event_lineupsget_event_statisticsget_event_timelineget_team_scheduleget_head_to_headget_event_xgget_event_players_statisticsget_missing_playersget_season_transfersget_player_profileget_player_season_stats
Commands that DO NOT exist (commonly hallucinated):
- ~~
get_standings~~ — the correct command isget_season_standings(requiresseason_id). - ~~
get_live_scores~~ — not available. Useget_daily_schedule()for today's matches; status field shows "live" for in-progress games. - ~~
get_team_squad~~ / ~~get_team_roster~~ —get_team_profiledoes NOT return players. Useget_season_leadersfor PL player IDs, thenget_player_profilefor individual data. - ~~
get_transfers~~ — the correct command isget_season_transfers(requiresseason_id+tm_player_ids). - ~~
get_match_results~~ / ~~get_match~~ — useget_event_summarywith anevent_id. - ~~
get_player_stats~~ — useget_event_players_statisticsfor match-level stats, orget_player_profilefor career data.
Other common mistakes:
- Using
get_season_leadersorget_missing_playerson non-PL leagues — they return empty. Check the Data Coverage table. - Using
get_event_xgon leagues outside the top 5 — returns empty. Only works for EPL, La Liga, Bundesliga, Serie A, Ligue 1. - Guessing
team_idorevent_idinstead of discovering them viasearch_team,get_daily_schedule, orget_season_schedule.
If you're unsure whether a command exists, check this list. Do not try commands that aren't listed above.
Troubleshooting
- `sports-skills` command not found: Package not installed. Run
pip install sports-skills. If the package is not found on PyPI, install from GitHub:pip install git+https://github.com/machina-sports/sports-skills.git. Requires Python 3.10+ — see Setup section. - `ModuleNotFoundError: No module named 'sports_skills'`: Same as above — install the package. Prefer the CLI over Python imports to avoid path issues.
- Empty results for PL-only commands on other leagues:
get_season_leadersandget_missing_playersonly return data for Premier League. They silently return empty for other leagues — check the Data Coverage table. - `get_team_profile` returns empty players: This is expected — squad rosters are not available. To get player data for a PL team, use
get_season_leadersto find players and their FPL IDs, thenget_player_profile(fpl_id="...")for detailed stats. For Transfermarkt data, you need the player'stm_player_id. - Finding FPL IDs and Transfermarkt IDs: Use
get_season_leaders(season_id="premier-league-2025")to discover FPL IDs for PL players. Transfermarkt IDs must be looked up on transfermarkt.com — the ID is the number at the end of the player's URL. Well-known examples: Cole Palmer =568177, Bukayo Saka =433177, Mbappe =342229. - No xG for recent matches: Understat data may lag 24-48 hours after a match ends. If
get_event_xgreturns empty for a recent top-5 match, try again later. - Wrong season_id format: Must be
{league-slug}-{year}e.g."premier-league-2025". Not"2025-2026", not"EPL-2025". Useget_current_season()to discover the correct format. - Team/event IDs unknown: Use
search_team(query="team name")to find team IDs by name, orget_season_teamsto list all teams in a season. Useget_daily_scheduleorget_season_scheduleto find event IDs. IDs are ESPN numeric strings.
Football Data — Valid Commands & Common Mistakes
Valid Commands
These are the ONLY valid commands. Do not invent or guess command names:
get_current_seasonget_competitionsget_competition_seasonsget_season_scheduleget_season_standingsget_season_leadersget_season_teamssearch_teamget_team_profileget_daily_scheduleget_event_summaryget_event_lineupsget_event_statisticsget_event_timelineget_team_scheduleget_head_to_headget_event_xgget_event_players_statisticsget_missing_playersget_season_transfersget_player_profile
Commands That DO NOT Exist (Commonly Hallucinated)
- ~~
get_standings~~ — the correct command isget_season_standings(requiresseason_id). - ~~
get_live_scores~~ — not available. Useget_daily_schedule()for today's matches; status field shows "live" for in-progress games. - ~~
get_team_squad~~ / ~~get_team_roster~~ —get_team_profiledoes NOT return players. Useget_season_leadersfor PL player IDs, thenget_player_profilefor individual data. - ~~
get_transfers~~ — the correct command isget_season_transfers(requiresseason_id+tm_player_ids). - ~~
get_match_results~~ / ~~get_match~~ — useget_event_summarywith anevent_id. - ~~
get_player_stats~~ — useget_event_players_statisticsfor match-level stats, orget_player_profilefor career data.
Other Common Mistakes
- Using
get_season_leadersorget_missing_playerson non-PL leagues — they return empty. Check the Data Coverage table. - Using
get_event_xgon leagues outside the top 5 — returns empty. Only works for EPL, La Liga, Bundesliga, Serie A, Ligue 1. - Guessing
team_idorevent_idinstead of discovering them viasearch_team,get_daily_schedule, orget_season_schedule.
If you're unsure whether a command exists, check this list. Do not try commands that aren't listed above.
Command Parameter Reference
get_current_season
competition_id(str, required): Competition slug
get_competitions
No parameters.
get_competition_seasons
competition_id(str, required): Competition slug
get_season_schedule
season_id(str, required): Season slug (e.g., "premier-league-2025")
get_season_standings
season_id(str, required): Season slug
get_season_leaders
season_id(str, required): Season slug (must bepremier-league-*)
get_season_teams
season_id(str, required): Season slug
search_team
query(str, required): Team name to searchcompetition_id(str, optional): Limit search to one league
get_team_profile
team_id(str, required): ESPN team IDleague_slug(str, optional): League hint
get_daily_schedule
date(str, optional): Date in YYYY-MM-DD format. Defaults to today.
get_event_summary
event_id(str, required): Match/event ID
get_event_lineups
event_id(str, required): Match/event ID
get_event_statistics
event_id(str, required): Match/event ID
get_event_timeline
event_id(str, required): Match/event ID
get_team_schedule
team_id(str, required): ESPN team IDleague_slug(str, optional): League hintseason_year(str, optional): Season year filtercompetition_id(str, optional): Filter to a single competition
get_head_to_head
UNAVAILABLE — requires licensed data. Do not call this command.
team_id(str, required): First team IDteam_id_2(str, required): Second team ID
get_event_xg
event_id(str, required): Match/event ID. Top 5 leagues only.
get_event_players_statistics
event_id(str, required): Match/event ID
get_missing_players
season_id(str, required): Season slug (must bepremier-league-*)
get_season_transfers
season_id(str, required): Season slugtm_player_ids(list, required): Transfermarkt player IDs
get_player_profile
fpl_id(str, optional): FPL player ID (PL players only)tm_player_id(str, optional): Transfermarkt player ID (any league)
At least one ID required.
Football Data — Data Coverage by League
Coverage Table
Not all data is available for every league. Use the right command for the right league.
| Command | All 13 leagues | Top 5 only | PL only |
|---|---|---|---|
| get_season_standings | x | ||
| get_daily_schedule | x | ||
| get_season_schedule | x | ||
| get_season_teams | x | ||
| search_team | x | ||
| get_team_schedule | x | ||
| get_team_profile | x | ||
| get_event_summary | x | ||
| get_event_lineups | x | ||
| get_event_statistics | x | ||
| get_event_timeline | x | ||
| get_current_season | x | ||
| get_competitions | x | ||
| get_event_xg | x | ||
| get_event_players_statistics (with xG) | x | ||
| get_season_leaders | x | ||
| get_missing_players | x |
Top 5 leagues (Understat): EPL, La Liga, Bundesliga, Serie A, Ligue 1. PL only (FPL): Premier League — injury news, player stats, ownership, ICT index. All leagues: via ESPN — scores, standings, schedules, match summaries, lineups, team stats. Transfermarkt: Works for any player with a tm_player_id — market values and transfer history.
Note: MLS uses a different season structure (spring-fall calendar). Use get_current_season(competition_id="mls") to detect the right season_id.
Data Sources
| Source | What it provides | League coverage |
|---|---|---|
| ESPN | Scores, standings, schedules, lineups, match stats, timelines | All 13 leagues |
| openfootball | Schedules, standings, team lists (fallback when ESPN is down) | 10 leagues (all except CL, Euros, World Cup) |
| Understat | xG per match, xG per shot, player xG/xA | Top 5 (EPL, La Liga, Bundesliga, Serie A, Ligue 1) |
| FPL | Top scorers, injuries, player stats, ownership | Premier League only |
| Transfermarkt | Market values, transfer history | Any player (requires tm_player_id) |
For licensed data with full coverage across all sports (Sportradar, Opta, Genius Sports), see Machina Sports.
Football Data — JSON Schemas
get_current_season
Returns data.competition and data.season:
{"competition": {"id": "premier-league", "name": "Premier League"}, "season": {"id": "premier-league-2025", "name": "2025-26 English Premier League", "year": "2025"}}get_season_standings
Returns data.standings[].entries[]:
{
"position": 1,
"team": {"id": "359", "name": "Arsenal", "short_name": "Arsenal", "abbreviation": "ARS", "crest": "https://..."},
"played": 26, "won": 17, "drawn": 6, "lost": 3,
"goals_for": 50, "goals_against": 18, "goal_difference": 32, "points": 57
}get_season_leaders
Returns data.leaders[] — note: player name is nested under .player.name:
{
"player": {"id": "223094", "name": "Erling Haaland", "first_name": "Erling", "last_name": "Haaland", "position": "Forward"},
"team": {"id": "43", "name": "Man City"},
"goals": 22, "assists": 6, "penalties": 0, "played_matches": 25
}Returns empty for non-PL leagues.
get_daily_schedule
Returns data.date and data.events[]:
{
"id": "748381", "status": "not_started", "start_time": "2026-02-16T20:00Z",
"competition": {"id": "la-liga", "name": "La Liga"},
"season": {"id": "la-liga-2025", "year": "2025"},
"venue": {"name": "Estadi Montilivi", "city": "Girona"},
"competitors": [
{"team": {"id": "9812", "name": "Girona", "abbreviation": "GIR"}, "qualifier": "home", "score": 0},
{"team": {"id": "83", "name": "Barcelona", "abbreviation": "BAR"}, "qualifier": "away", "score": 0}
],
"scores": {"home": 0, "away": 0}
}Status values: "not_started", "live", "halftime", "closed", "postponed".
get_event_lineups
Returns data.lineups[]:
{
"team": {"id": "364", "name": "Liverpool", "abbreviation": "LIV"},
"qualifier": "home",
"formation": "4-3-3",
"starting": [{"id": "275599", "name": "Caoimhin Kelleher", "position": "Goalkeeper", "shirt_number": 1}],
"bench": [{"id": "...", "name": "...", "position": "...", "shirt_number": 62}]
}get_event_statistics
Returns data.teams[]:
{
"team": {"id": "244", "name": "Brentford"},
"qualifier": "home",
"statistics": {"ball_possession": "40.8", "shots_total": "10", "shots_on_target": "3", "fouls": "12", "corners": "4"}
}get_event_xg
Returns data.teams[] and data.shots[]:
{"team": {"id": "244", "name": "Brentford"}, "qualifier": "home", "xg": 1.812}data.shots[] contains individual shot data with xG per shot. Note: very recent matches (last 24-48h) may not be indexed on Understat yet.
get_event_players_statistics
Returns data.teams[].players[]:
{
"id": "...", "name": "Bukayo Saka", "position": "Midfielder", "shirt_number": 7, "starter": true,
"statistics": {"appearances": "1", "shotsTotal": "3", "shotsOnTarget": "1", "foulsCommitted": "1", "xg": "0.45", "xa": "0.12"}
}xg and xa fields only present for top 5 leagues.
get_missing_players
Returns data.teams[].players[]:
{
"id": "463748", "name": "Mikel Merino Zazon", "web_name": "Merino",
"position": "Midfielder", "status": "injured",
"news": "Foot injury - Unknown return date",
"chance_of_playing_this_round": 0, "chance_of_playing_next_round": 0
}Status values: "injured", "unavailable", "doubtful", "suspended".
get_season_transfers
Returns data.transfers[]:
{
"player_tm_id": "433177", "date": "2019-07-01", "season": "19/20",
"from_team": {"name": "Arsenal U23", "image": "https://..."},
"to_team": {"name": "Arsenal", "image": "https://..."},
"fee": "-", "market_value": "-"
}get_player_profile
With tm_player_id, returns data.player with:
{
"market_value": {"value": 130000000, "currency": "EUR", "formatted": "EUR130.00m", "date": "09/12/2025", "age": "24", "club": "Arsenal FC"},
"market_value_history": [{"value": 7000000, "formatted": "EUR7.00m", "date": "23/09/2019", "club": "Arsenal FC"}],
"transfer_history": [
{"player_tm_id": "433177", "date": "2019-07-01", "season": "19/20", "from_team": {"name": "Arsenal U23"}, "to_team": {"name": "Arsenal"}, "fee": "-"}
]
}With fpl_id, also includes data.player.fpl_data with FPL stats (points, form, ICT index, ownership, etc.).
search_team
Returns data.results[] with team, competition, and season for each match:
{"team": {"id": "874", "name": "Corinthians"}, "competition": {"id": "serie-a-brazil", "name": "Serie A Brazil"}, "season": {"id": "serie-a-brazil-2025", "year": "2025"}}#!/bin/bash
# Validates football-data parameters
COMMAND="${1:-}"
# Season ID format check
if [[ "$*" == *"--season_id="* ]]; then
SID=$(echo "$*" | grep -o '\-\-season_id=[^ ]*' | cut -d= -f2)
if [[ ! "$SID" =~ ^[a-z-]+-[0-9]{4}$ ]]; then
echo "ERROR: season_id must be {league-slug}-{year} format (e.g., premier-league-2025). Got: $SID"
exit 1
fi
fi
# League coverage warnings
case "$COMMAND" in
get_season_leaders|get_missing_players)
if [[ "$*" != *"premier-league"* ]]; then
echo "WARNING: $COMMAND only works for Premier League. Will return empty for other leagues."
fi
;;
get_event_xg)
echo "INFO: xG data only available for top 5 leagues (EPL, La Liga, Bundesliga, Serie A, Ligue 1)."
;;
esac
echo "OK"
Related skills
FAQ
Does it need an API key?
No, the docs state zero config and no API keys required.
Which leagues are covered?
13 leagues including Premier League, La Liga, Bundesliga, Serie A, Ligue 1, MLS, Champions League, and the World Cup.