OrbTop

Understat xG League & Team Stats Scraper

SPORTSDEVELOPER TOOLS

Understat xG League & Team Stats Scraper

Scrape expected goals (xG), non-penalty xG (NPxG), xGA, PPDA, deep completions, and full W/D/L standings from understat.com — the canonical open xG data source for European football.

Covers all 6 understat leagues (EPL, La Liga, Bundesliga, Serie A, Ligue 1, RFPL) across every available season (2014–present). One aggregated row per team per season.

Features

  • 6 leagues in a single run: EPL, La Liga, Bundesliga, Serie A, Ligue 1, RFPL
  • All seasons from 2014/2015 onwards — back-fill historical data or track the current season
  • Match-level aggregation — sums each team's per-match xG, xGA, NPxG, PPDA, deep completions into a clean season total
  • PPDA ratio computed correctly as passes_attempted / defensive_actions (lower = more pressing)
  • No proxy required — understat.com is open and datacenter-friendly

Use Cases

  • Build football analytics dashboards (xG vs actual goals by team)
  • Feed betting or fantasy football models with expected-goals standings
  • Compare xG performance across leagues or seasons for research / Substack writing
  • Backtest xG-based table predictions

Input

Field Type Default Description
leagues array (all 6) Which leagues to scrape. Valid values: EPL, La_liga, Bundesliga, Serie_A, Ligue_1, RFPL
seasons array ["2024"] Season start years to scrape. E.g. ["2024"] = 2024/2025, ["2023","2024"] = two seasons
maxItems integer 10 Maximum records to return (0 = unlimited)

Example input — EPL last 3 seasons

{
  "leagues": ["EPL"],
  "seasons": ["2022", "2023", "2024"],
  "maxItems": 0
}

Example input — All leagues, current season

{
  "leagues": ["EPL", "La_liga", "Bundesliga", "Serie_A", "Ligue_1", "RFPL"],
  "seasons": ["2024"],
  "maxItems": 0
}

Output

One record per team per season:

{
  "season": "2024/2025",
  "league": "EPL",
  "team_name": "Aston Villa",
  "team_id": "71",
  "games_played": 38,
  "wins": 19,
  "draws": 9,
  "losses": 10,
  "goals_for": 58,
  "goals_against": 51,
  "xg_for": 66.39,
  "xg_against": 55.0,
  "npxg": 61.71,
  "deep": 285,
  "ppda": 12.39,
  "oppda": 9.96,
  "points": 66,
  "source": "https://understat.com/league/EPL"
}

Field reference

Field Description
season Season label (e.g. 2024/2025)
league League name
team_name Team name as shown on understat.com
team_id Understat internal team ID
games_played Total matches played
wins / draws / losses Season record
goals_for / goals_against Goals scored / conceded
xg_for Total expected goals (xG)
xg_against Total expected goals against (xGA)
npxg Non-penalty xG (excludes spot-kick quality)
deep Deep completions — passes into the opposition's danger zone
ppda Passes per defensive action by opponent (lower = team presses more aggressively)
oppda Opponent PPDA — how much the team is pressed
points Total league points
source Source URL

Notes

  • Data is sourced from understat.com's internal XHR API (/getLeagueData/{league}/{season}), which returns gzip-compressed JSON. All values are aggregated from per-match history.
  • PPDA and OPPDA are null if a team played 0 defensive actions (extremely rare, data gap seasons only).
  • The RFPL (Russian Premier League) data coverage may be incomplete for recent seasons.
  • maxItems counts across all requested league × season combinations. Set to 0 to scrape everything.