Understat Football xG Scraper: Expected Goals & Shot Stats
Pricing
from $8.32 / 1,000 results
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
Maintained by CommunityActor 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
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
Table of contents
- What it does
- Use cases
- Quickstart
- Modes
- Input reference
- Output reference
- Run via API and CLI
- Fetch results
- Billing and limits
- FAQ and troubleshooting
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
| Mode | You provide | You get |
|---|---|---|
league | league, season, entity (players or teams) | One row per player or team for the season |
player | playerId | One row per season for the player; optional shot-level rows |
team | teamName, season | One row per squad player plus team situation splits |
match | matchId | Per-team xG summary; optional shot-level rows for both teams |
Input reference
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
mode | enum | no | league | What to scrape: league, player, team, or match. |
league | string | no | EPL | League for league mode. Codes or names accepted (EPL/Premier League, La Liga, Bundesliga, Serie A, Ligue 1, RFPL). |
season | string | no | 2024 | Season starting year. 2024 is the 2024/2025 season. Used by league and team modes. |
entity | enum | no | players | In league mode, return one row per players or per teams. |
sortBy | enum | no | xG | Sort player rows by xG, goals, assists, xA, npxG, xGChain, xGBuildup, or shots. |
minGames | integer | no | 0 | Only include players with at least this many games (league mode). |
playerId | string | no | 1250 | Understat player ID (player mode). |
teamName | string | no | (none) | Team name (team mode). Spaces are fine, for example Manchester United. |
matchId | string | no | (none) | Understat match ID (match mode). |
includeShots | boolean | no | false | Player and match modes. Also emit every shot with its xG. Paid plans only. Charged once per player or match. |
withAiSummary | boolean | no | false | Add an AI xG performance insight for a player or team. Paid plans only. Billed only when produced. |
maxResults | integer | no | 50 | Maximum 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.
| Field | Type | Description |
|---|---|---|
mode | string | Requested mode. |
rowType | string | Row kind: league-player, team, player-season, team-player, team-situation, match-team, or shot. |
league | string | League code. |
season | string | Season starting year. |
playerId | string | Understat player ID. |
playerName | string | Player name. |
teamTitle | string | Team name. |
position | string | Playing position(s). |
games | number | Games or appearances. |
time | number | Minutes played. |
goals | number | Goals scored. |
xG | number | Expected Goals. |
xGA | number | Expected Goals Against (team rows). |
assists | number | Assists. |
xA | number | Expected Assists. |
shots | number | Shots taken. |
keyPasses | number | Key passes. |
npg | number | Non-penalty goals. |
npxG | number | Non-penalty Expected Goals. |
xGChain | number | Total xG of every possession the player was involved in. |
xGBuildup | number | xGChain excluding shots and key passes. |
points | number | League points (team rows). |
xPoints | number | Expected points (team rows). |
xGDiff | number | Goals minus xG (finishing over- or under-performance). |
xADiff | number | Assists minus xA. |
xGPer90 | number | xG per 90 minutes. |
xAPer90 | number | xA per 90 minutes. |
npxGPer90 | number | Non-penalty xG per 90 minutes. |
xGChainPer90 | number | xGChain per 90 minutes. |
situation | string | Play situation split (team-situation and shot rows). |
shotType | string | Body part or shot type (shot rows). |
result | string | Shot result: Goal, SavedShot, MissedShots, and so on. |
minute | number | Match minute of the shot. |
X | number | Shot X location, normalized 0 to 1. |
Y | number | Shot Y location, normalized 0 to 1. |
assistedBy | string | Player who assisted the shot. |
matchId | string | Understat match ID. |
aiFinishing | string | AI note on finishing versus xG (add-on), or null. |
aiCreativity | string | AI note on chance creation (add-on), or null. |
aiStyle | string | AI note on playing or scoring style (add-on), or null. |
aiFormNote | string | AI short performance note (add-on), or null. |
source | string | Data source label. |
observedAt | string | ISO 8601 timestamp of when the row was collected. |
error | string | null 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:
# JSONcurl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=json"# CSVcurl "https://api.apify.com/v2/datasets/<DATASET_ID>/items?token=<TOKEN>&clean=true&format=csv"# Paginate large datasetscurl "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 (
resultevent). See the pricing tab for the current per-result price. - Shot-level add-on. The
shotsevent 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_summaryevent 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
errorfield and does not charge for it. Runs that return no data cost nothing. - Spend cap respected. Set
maxTotalChargeUsdon 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
shotsandai_summaryadd-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.
Related scrapers
- ESPN Soccer Scraper: soccer fixtures, results, and standings.
- Polymarket Prediction Markets Scraper: live odds, volume, and liquidity.
- Sofascore Scraper: live scores and match statistics.
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.
