Understat Football xG Scraper: Expected Goals & Shot Stats avatar

Understat Football xG Scraper: Expected Goals & Shot Stats

Pricing

from $8.32 / 1,000 results

Go to Apify Store
Understat Football xG Scraper: Expected Goals & Shot Stats

Understat Football xG Scraper: Expected Goals & Shot Stats

Scrape Understat Expected Goals (xG) football stats: player, team, league and match xG, xGA, npxG, xGChain, xGBuildup, plus shot-level xG. Top 6 leagues. Optional AI xG insight. Export to JSON, CSV or Excel.

Pricing

from $8.32 / 1,000 results

Rating

0.0

(0)

Developer

Scrapers Lat

Scrapers Lat

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

Understat Football xG Scraper: Expected Goals & Shot Stats

Understat Football xG Scraper: Expected Goals & Shot Stats

Real Expected Goals (xG) analytics for football (soccer): player, team, league, and match xG, plus every shot with its own xG. Here is one real result from a live league run, with every field the actor returns:

{
"mode": "league",
"rowType": "league-player",
"league": "EPL",
"season": "2024",
"playerId": "1250",
"playerName": "Mohamed Salah",
"teamTitle": "Liverpool",
"position": "F M",
"games": 38,
"time": 3392,
"goals": 29,
"xG": 27.706,
"assists": 18,
"xA": 15.858,
"shots": 130,
"keyPasses": 89,
"yellowCards": 1,
"redCards": 0,
"npg": 20,
"npxG": 20.856,
"xGChain": 48.536,
"xGBuildup": 16.207,
"xGDiff": 1.294,
"xADiff": 2.142,
"xGPer90": 0.735,
"xAPer90": 0.421,
"npxGPer90": 0.553,
"xGChainPer90": 1.288,
"aiFinishing": null,
"aiCreativity": null,
"aiStyle": null,
"aiFormNote": null,
"source": "Understat",
"observedAt": "2026-08-16T22:35:54.541Z"
}

The most complete football xG scraper for the top 6 leagues (Premier League, La Liga, Bundesliga, Serie A, Ligue 1, RFPL). It exposes the real advanced metrics generic football scrapers miss: xG, xGA, npxG, xGChain, xGBuildup, xA, and shot-level xG with pitch coordinates, plus derived finishing metrics like goals minus xG and xG per 90. Optional add-ons return every shot and an AI xG performance insight.

📥 Input · 📤 Output · 💰 Pricing · ▶️ Examples

Apify Coverage Metrics Output Billing

Table of contents

What it does

Pick a mode and the actor returns clean, flat, per-entity rows of Expected Goals data with no nested objects, ready for CSV or Excel:

  • League mode returns one row per player or per team for a whole league season, with full xG, npxG, xGChain, xGBuildup, xA, and derived finishing and per-90 metrics. Sort and filter by games.
  • Player mode returns one row per season for a single player, and can optionally add every shot the player has taken (minute, xG, pitch X and Y, result, situation, shot type, who assisted).
  • Team mode returns one row per squad player plus the team's situation splits (open play, set piece, corner, counter) with xG for and against.
  • Match mode returns a per-team xG summary for a single match, and can optionally add every shot from both teams with its xG.

Missing source values are returned as null. Numbers are parsed, not strings. The actor never fabricates values: it only emits what the source actually reports.

Use cases

  • Football analytics and modeling. Build xG models and finishing analysis with real xG, npxG, xGChain, and xGBuildup instead of raw goals.
  • Betting and trading models. Feed team and player xG, xGA, and expected points into value models and over/under markets.
  • Fantasy football and drafting. Rank players by xG per 90, xA per 90, and xGChain to find underlying performers before their price rises.
  • Scouting and recruitment. Compare shot quality, non-penalty xG, and creativity across leagues to shortlist targets.
  • Content and media. Power match previews, xG timelines, and shot maps with pitch coordinates for every shot.
  • Player performance review. Spot over- and under-performance of xG (goals minus xG) season by season.

Quickstart

Open the actor, paste this into the input, and press Run. It returns the top 20 Premier League players of the 2024/2025 season by xG.

{
"mode": "league",
"league": "EPL",
"season": "2024",
"entity": "players",
"sortBy": "xG",
"maxResults": 20
}

season is the starting year, so 2024 means the 2024/2025 season. league accepts codes or names, for example EPL or Premier League, La Liga, Bundesliga, Serie A, Ligue 1, RFPL.

Modes

ModeYou provideYou get
leagueleague, season, entity (players or teams)One row per player or team for the season
playerplayerIdOne row per season for the player; optional shot-level rows
teamteamName, seasonOne row per squad player plus team situation splits
matchmatchIdPer-team xG summary; optional shot-level rows for both teams

Input reference

FieldTypeRequiredDefaultDescription
modeenumnoleagueWhat to scrape: league, player, team, or match.
leaguestringnoEPLLeague for league mode. Codes or names accepted (EPL/Premier League, La Liga, Bundesliga, Serie A, Ligue 1, RFPL).
seasonstringno2024Season starting year. 2024 is the 2024/2025 season. Used by league and team modes.
entityenumnoplayersIn league mode, return one row per players or per teams.
sortByenumnoxGSort player rows by xG, goals, assists, xA, npxG, xGChain, xGBuildup, or shots.
minGamesintegerno0Only include players with at least this many games (league mode).
playerIdstringno1250Understat player ID (player mode).
teamNamestringno(none)Team name (team mode). Spaces are fine, for example Manchester United.
matchIdstringno(none)Understat match ID (match mode).
includeShotsbooleannofalsePlayer and match modes. Also emit every shot with its xG. Paid plans only. Charged once per player or match.
withAiSummarybooleannofalseAdd an AI xG performance insight for a player or team. Paid plans only. Billed only when produced.
maxResultsintegerno50Maximum result rows to return. Free plans are capped at 10.

Output reference

One flat dataset item per entity for the chosen mode. Types: string, number, or null when the source value is absent.

FieldTypeDescription
modestringRequested mode.
rowTypestringRow kind: league-player, team, player-season, team-player, team-situation, match-team, or shot.
leaguestringLeague code.
seasonstringSeason starting year.
playerIdstringUnderstat player ID.
playerNamestringPlayer name.
teamTitlestringTeam name.
positionstringPlaying position(s).
gamesnumberGames or appearances.
timenumberMinutes played.
goalsnumberGoals scored.
xGnumberExpected Goals.
xGAnumberExpected Goals Against (team rows).
assistsnumberAssists.
xAnumberExpected Assists.
shotsnumberShots taken.
keyPassesnumberKey passes.
npgnumberNon-penalty goals.
npxGnumberNon-penalty Expected Goals.
xGChainnumberTotal xG of every possession the player was involved in.
xGBuildupnumberxGChain excluding shots and key passes.
pointsnumberLeague points (team rows).
xPointsnumberExpected points (team rows).
xGDiffnumberGoals minus xG (finishing over- or under-performance).
xADiffnumberAssists minus xA.
xGPer90numberxG per 90 minutes.
xAPer90numberxA per 90 minutes.
npxGPer90numberNon-penalty xG per 90 minutes.
xGChainPer90numberxGChain per 90 minutes.
situationstringPlay situation split (team-situation and shot rows).
shotTypestringBody part or shot type (shot rows).
resultstringShot result: Goal, SavedShot, MissedShots, and so on.
minutenumberMatch minute of the shot.
XnumberShot X location, normalized 0 to 1.
YnumberShot Y location, normalized 0 to 1.
assistedBystringPlayer who assisted the shot.
matchIdstringUnderstat match ID.
aiFinishingstringAI note on finishing versus xG (add-on), or null.
aiCreativitystringAI note on chance creation (add-on), or null.
aiStylestringAI note on playing or scoring style (add-on), or null.
aiFormNotestringAI short performance note (add-on), or null.
sourcestringData source label.
observedAtstringISO 8601 timestamp of when the row was collected.
errorstringnull on success. On a failed run, a single unbilled item with a populated error is written instead.

Run via API and CLI

Start a run and read the dataset. Replace <TOKEN> with your Apify API token.

Run synchronously and get dataset items in one call:

curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~understat-football-xg-scraper/run-sync-get-dataset-items?token=<TOKEN>" \
-H "Content-Type: application/json" \
-d '{"mode":"league","league":"EPL","season":"2024","entity":"players","sortBy":"xG","maxResults":20}'

Scrape a single player with shot-level data:

curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~understat-football-xg-scraper/runs?token=<TOKEN>" \
-H "Content-Type: application/json" \
-d '{"mode":"player","playerId":"1250","includeShots":true}'

Apify CLI:

apify call scrapers_lat/understat-football-xg-scraper \
--input '{"mode":"team","teamName":"Liverpool","season":"2024"}'

Fetch results

Every run writes to a dataset. Fetch items as JSON, CSV, or Excel by changing format:

# JSON
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=json"
# CSV
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=csv"
# Paginate large datasets
curl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&offset=1000&limit=1000"

<DATASET_ID> is returned as defaultDatasetId in the run object. clean=true drops empty and internal fields.

Billing and limits

  • Pay per result. You are charged per result row returned (result event). See the pricing tab for the current per-result price.
  • Shot-level add-on. The shots event returns every shot for a player or match with its own xG and pitch coordinates. It is charged once per player or match, only when the shot data is actually returned.
  • AI xG insight add-on. The ai_summary event adds a finishing, creativity, style, and form read for a player or team. It is charged only when the model returns usable output.
  • No charge on failure. If a run errors or an id is not found, the actor writes a single item with a populated error field and does not charge for it. Runs that return no data cost nothing.
  • Spend cap respected. Set maxTotalChargeUsd on the run; once reached, the actor stops emitting and charging further billable rows.
  • Free Apify plans are capped at 10 result rows per run, and the shots and ai_summary add-ons are disabled.

FAQ and troubleshooting

What does xG mean? Expected Goals (xG) estimates the probability that a given shot becomes a goal, based on factors like location and situation. Summed over shots it measures the quality of chances created or conceded, which is far more predictive than raw goals.

What is xGChain and xGBuildup? xGChain sums the xG of every possession a player was involved in, and xGBuildup is the same but excludes the player's own shots and key passes. Together they credit players who build attacks without taking the final shot.

How do I read xGDiff? xGDiff is goals minus xG. A positive value means the player scored more than their chances suggested (over-performing, clinical finishing or luck); a negative value means under-performance.

Which leagues and seasons are covered? The top 6 leagues: Premier League (EPL), La Liga, Bundesliga, Serie A, Ligue 1, and RFPL, across the seasons the source publishes. Set season to the starting year.

Where do I find a player or match ID? IDs come from the source pages. Player and match modes take the numeric ID; team mode takes the team name directly.

Why are the AI fields null? The AI insight is off by default and requires a paid plan. Enable withAiSummary on a paid plan to populate aiFinishing, aiCreativity, aiStyle, and aiFormNote.

Is this an official tool? No. This actor is independent and has no affiliation with Understat. It reads only data that is publicly available.

More scrapers at scrapers.lat

Built and maintained by scrapers.lat, where we publish scrapers for public platforms: company registries, government data, finance, sports, e-commerce and more. Browse the catalog or request a custom scraper at scrapers.lat.


Independent tool, not affiliated with Understat. Accesses only publicly available data.