machina-sports/sports-skills

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, World Cup, Championship, Eredivisie, Primeira Liga, Serie A Brazil, Russian Premier League, Scottish/Belgian/Turkish top flights, European Championship, and more (call get_competitions for the live l…

All-time #5925 Trending #8342 First seen Feb 16, 2026
8-week activity · all time api

Installation

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

Also in this package

Other skills from machina-sports/sports-skills · top by installs.

npx skills add machina-sports/sports-skills

Browse all from machina-sports/sports-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 215
License LICENSE
Default branch main
Open issues 0
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Version0.1.0
LicenseMIT
More metadata
author
machina-sports
version
0.1.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 15,859 B
  • docs SUMMARY.md 1,409 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2,115 installs

SKILL.md

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:

which sports-skills || pip install sports-skills

If pip install fails (package not found or Python version error), install from GitHub:

pip install git+https://github.com/machina-sports/sports-skills.git

The 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-skills

No 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-2025

Python SDK (alternative):

from sports_skills import football

standings = football.get_season_standings(season_id="premier-league-2025")
schedule = football.get_daily_schedule()

CRITICAL: Before Any Query

CRITICAL: Before calling any data endpoint, verify:

  • Season ID is derived from getcurrentseason(competition_id="...") — never hardcoded.
  • Team ID is resolved via searchteam(query="...") and passed as the numeric teamid. For getheadtohead, getteamstrength, and getmatch_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.
  • geteventxg and geteventplayers_statistics (with xG) are only called for top-5 leagues (EPL, La Liga, Bundesliga, Serie A, Ligue 1).
  • getseasonleaders and getmissingplayers 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 getcurrentseason(competitionid="...") to get the active seasonid. 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 getcurrentseason(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)
geteventxg, geteventplayers_statistics (xG fields) Understat Top 5 only (EPL, La Liga, Bundesliga, Serie A, Ligue 1). Not RFPL — Understat dropped it.
getseasonleaders, getmissingplayers FPL Premier League only
getplayerprofile, getseasontransfers (market value) Transfermarkt Any player with a tmplayerid
getheadto_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.
getteamstrength, getmatchforecast ClubElo European clubs (incl. Russia).

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)

  • Pass IDs, not ambiguous names. For H2H/strength/forecast, resolve teams with searchteam first and pass the numeric teamid. Names like "Paris Saint-Germain" can collapse onto the wrong club (Paris FC) during name resolution.
  • ClubElo off-season gaps: current-date getteamstrength 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").
  • getmatchforecast 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): searchteam ×2 → getheadtohead (recent record) + getteamstrength(teamid, teamid2) (Elo gap / favorite) + getmatchforecast (if within ~a week: W/D/L + scoreline). For a top-5 fixture add historical getevent_xg context from recent meetings.
  • Match report (post-game): geteventsummary + geteventstatistics + geteventtimeline, and for top-5 leagues geteventxg + geteventplayers_statistics.
  • Team form + context: getteamschedule (recent results) + getteamstrength (current Elo & rank) + getmissingplayers (PL only) + per-match geteventxg (top-5).
  • Rivalry / derby deep dive: getheadtohead (all-time-ish record + goals) + getteam_strength comparison for the current power balance.
  • Odds sanity-check: getmatchforecast 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
getcurrentseason Detect current season for a competition
get_competitions List available competitions with current season info
getcompetitionseasons Available seasons for a competition
getseasonschedule Full season match schedule
getseasonstandings League table for a season
getseasonleaders Top scorers/leaders (Premier League only)
getseasonteams Teams in a season
search_team Search for a team by name
search_player Search for a player by name
getteamprofile Basic team info (no squad/roster)
getdailyschedule All matches for a date across all leagues
geteventsummary Match summary with scores
geteventlineups Match lineups
geteventstatistics Match team statistics
geteventtimeline Match timeline (goals, cards, subs)
getteamschedule Schedule for a specific team
getheadto_head Historical H2H results + stats (European domestic leagues)
getteamstrength ClubElo Elo rating / two-team comparison (European clubs)
getmatchforecast ClubElo win/draw/loss + scoreline forecast (~week ahead)
geteventxg xG data (top 5 leagues only)
geteventplayers_statistics Player-level match stats with optional xG
getmissingplayers Injured/doubtful players (Premier League only)
getseasontransfers Transfer history via Transfermarkt
getplayerseason_stats Player season stats via ESPN
getplayerprofile 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 getcurrentseason(competitionid="premier-league") to get the current seasonid
  2. Call getseasonstandings(seasonid=<seasonid 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 getdailyschedule() or getteamschedule(teamid="359") to find the eventid
  2. Call geteventsummary(event_id="...") for the score
  3. Call geteventstatistics(event_id="...") for possession, shots, etc.
  4. Call geteventxg(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 searchteam(query="Chelsea") → teamid=363, competition=premier-league
  2. Call getteamschedule(teamid="363", competitionid="premier-league") → find recent closed events
  3. For each recent match, call in parallel: geteventxg, geteventstatistics, geteventplayers_statistics
  4. Call getmissingplayers(seasonid=<seasonid>) → 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 getplayerprofile(tmplayerid="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 searchteam(query="Corinthians") → teamid=874, competition=serie-a-brazil
  2. Call getteamschedule(teamid="874", competitionid="serie-a-brazil") for fixtures
  3. Pick a recent match and call geteventtimeline(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 searchteam(query="Arsenal") and searchteam(query="Manchester City") → team_ids 359, 382
  2. In parallel: getheadtohead(teamid="359", teamid2="382") (recent record + goals),

getteamstrength(teamid="359", teamid2="382") (Elo gap + favorite), getmatchforecast(teamid="359", teamid2="382") (W/D/L + likely scoreline, if within ~a week)

  1. 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

  • getstandings — the correct command is getseasonstandings (requires seasonid).
  • getlivescores — not available. Use getdailyschedule() for today's matches.
  • getteamsquad / getteamrostergetteamprofile does NOT return players. Use getseasonleaders for PL player IDs, then getplayerprofile.
  • gettransfers — the correct command is getseasontransfers (requires seasonid + tmplayerids).
  • getmatchresults / getmatch — use geteventsummary with an eventid.
  • getplayerstats — use geteventplayersstatistics for match-level stats, or getplayer_profile for career data.
  • getscores / getresults — use geteventsummary with an event_id.
  • getfixtures — use getdailyschedule for today's matches or getseason_schedule for a full season.
  • getleaguetable — use getseasonstandings with a season_id.

If a command is not in the Commands table above, it does not exist. Do not try commands not listed.

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.
  2. Try alternatives — if an eventid returns no data, call getdailyschedule() or getteam_schedule() to discover the correct ID.
  3. Only report failure after exhausting alternatives — use a clean message (e.g., "I couldn't find that match — can you confirm the teams or date?").

Troubleshooting

Error: sports-skills command not found Cause: Package not installed Solution: Run pip install sports-skills. If not on PyPI, install from GitHub: pip install git+https://github.com/machina-sports/sports-skills.git

Error: ModuleNotFoundError: No module named 'sports_skills' Cause: Package not installed or path issue Solution: Install the package. Prefer the CLI over Python imports to avoid path issues

Error: getseasonleaders or getmissingplayers returns empty for a non-PL league Cause: These commands only work for Premier League; they silently return empty for other leagues Solution: Check the Data Coverage table in references/api-reference.md. For other leagues, use geteventplayers_statistics for player data

Error: getteamprofile returns no players Cause: This command does not return squad rosters — this is expected behavior Solution: For PL teams, use getseasonleaders to find player FPL IDs, then getplayerprofile(fpl_id="...")

Error: Wrong seasonid format Cause: Season ID must follow the {league-slug}-{year} format Solution: Use getcurrentseason(competitionid="...") to discover the correct format. Example: "premier-league-2025", not "2025-2026" or "EPL-2025"

Error: No xG data for a recent match Cause: Understat data may lag 24-48 hours after a match ends Solution: If geteventxg returns empty for a recent top-5 match, retry later. Only available for EPL, La Liga, Bundesliga, Serie A, Ligue 1

Error: Team or event ID unknown Cause: ID was guessed instead of looked up Solution: Use searchteam(query="team name") to find team IDs, or getdailyschedule / getseason_schedule to find event IDs. Never guess IDs.