Understat Scraper: Football xG & Player Stats avatar

Understat Scraper: Football xG & Player Stats

Pricing

Pay per event

Go to Apify Store
Understat Scraper: Football xG & Player Stats

Understat Scraper: Football xG & Player Stats

Scrape Understat expected goals (xG), xA, npxG, shots and key passes per player for the Premier League, La Liga, Bundesliga, Serie A, Ligue 1 and RFPL since 2014. Computed per-90 rates. Export CSV, Excel, JSON. No login or API key. La Liga 2025/26 returns 600 players.

Pricing

Pay per event

Rating

0.0

(0)

Developer

RecordsData

RecordsData

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Share

RecordsData

โšฝ Understat Scraper: Football xG, Team Tables, Matches & Shots

The Understat xG Scraper exports expected goals data from understat.com as CSV, Excel or JSON. For any season since 2014/15 it returns player rows, team season tables with xG, xGA and xPoints, match results with match xG, shot-level data with pitch X/Y, and full player careers for the Premier League, La Liga, Bundesliga, Serie A, Ligue 1 and RFPL. No login or API key.

This Understat scraper pulls a full league player table (La Liga 2025/26 returns 600 player rows), a team season table (Arsenal 2025/26: 85 points, xG 77.49, xGA 33.13), the matches of a season, or every shot of a match. It adds columns Understat does not show: xG/90, xA/90, shots/90 and goals minus xG. An optional only-new mode delivers just the rows that changed since your last run.

โšฝ What does the Understat xG Scraper do?

Pick what to export with the entity input:

  • players: league player tables and club squad tables, with a minimum-minutes filter and seven sort keys.
  • teams: one row per team and season with rank, W/D/L, points, goals, xG, xGA, xGD, npxG, xPoints, PPDA and deep passes. Optional situation splits per club.
  • matches: results and upcoming fixtures with match xG, xPoints, PPDA and Understat win probabilities. Filter by dates, clubs or match IDs.
  • playerCareer: one row per season and club for a player, found by Understat ID, player URL or exact name.
  • Shots (includeShots): one row per shot with minute, X, Y, xG, result, situation, shot type, last action and assisting player.
  • Only-new mode (onlyNew): skips rows already delivered, so repeat runs cost less.
  • Covers six leagues and every season from 2014/15. Invalid input, unknown teams and empty results cost nothing.

๐Ÿ“Š What data can you extract from Understat?

The dataset schema has 96 columns in one fixed order. A row carries only the keys that have a value, and the recordType column tells you which kind of row it is (league-player, team-player, player-season, team-season, match, shot or team-split).

GroupFields
Player identityname, playerId, team, position, season, games, minutes
Player metricsgoals, nonPenaltyGoals, xG, npxG, xGDiff, assists, xA, xADiff, shots, keyPasses, yellowCards, redCards, xGChain, xGBuildup
Per-90 ratesxGPer90, xAPer90, npxGPer90, xGChainPer90, shotsPer90
Team tablerank, wins, draws, losses, points, goalsAgainst, goalDiff, xGA, xGD, npxGA, npxGD, xPoints, xPointsDiff, ppda, oppda, deep, deepAllowed
Team splitssplitGroup, split (situation, formation, game state, timing, shot zone, attack speed, result)
MatchmatchId, date, kickoff, homeTeam, awayTeam, goals, homeXG, awayXG, xPoints, PPDA, deep, shots on target, win, draw and loss probabilities
ShotshotId, minute, X, Y, xG, result, situation, shotType, lastAction, assistedBy
MetarecordType, scope, scopeValue, league, changeType, url, scrapedAt

๐Ÿงพ Understat scraper sample output

A real player row from a cloud run (La Liga, season 2025, 10 rows requested, 10 delivered):

{
"recordType": "league-player",
"scope": "league",
"scopeValue": "La_liga",
"season": "2025/2026",
"playerId": "3423",
"name": "Kylian Mbappe-Lottin",
"team": "Real Madrid",
"position": "F S",
"games": 31,
"minutes": 2623,
"goals": 25,
"xG": 25.8,
"xGDiff": -0.8,
"assists": 5,
"xA": 7.24,
"shots": 146,
"keyPasses": 65,
"xGPer90": 0.89,
"shotsPer90": 5.01,
"url": "https://understat.com/player/3423",
"scrapedAt": "2026-10-04T04:15:31.634Z"
}

A trimmed team row (EPL, season 2025). Only values read from the cloud run are shown, other columns are left out:

{
"recordType": "team-season",
"league": "EPL",
"team": "Arsenal",
"points": 85,
"xG": 77.49,
"xGA": 33.13
}

Rows are never padded with empty columns. The player row comes from an earlier version without the newer columns.

๐Ÿ’ฐ How much does it cost to scrape Understat?

Pricing is pay per event. Six events are live, at the Free plan rate shown below. Paid Apify plans get a lower per-row price on the player events, and the other four events keep the same price on every plan.

EventWhen it is chargedPrice per row (Free plan)
League player rowOne player-season from a league request or a player career$0.015
Team player rowOne player-season from a club request$0.015
Team season rowOne team-season table row$0.004
Match rowOne match with result, xG and win probabilities$0.002
Team split rowOne situation, formation, timing or zone split row$0.001
Shot rowOne shot with position, xG, minute and result$0.0001

On the Gold plan a player row costs $0.01275. Paid plans pay less per player row than the Free plan.

Examples at the Free plan rate: 10 player rows cost $0.15, a full 600-row La Liga season costs $9.00, and 1,000 rows cost 1,000 x $0.015 = $15.00. A 20-team EPL table costs 20 x $0.004 = $0.08. A match with its shots costs $0.002 plus $0.0001 per shot, so 3 matches and 57 shots cost $0.0117. You are not charged for failed, empty or "not found" lookups, and the actor stops when your maximum cost per run is reached. Use maxItems to cap the rows and the spend.

๐Ÿš€ How to scrape Understat in 3 steps

  1. Open the actor on Apify and click Try for free.
  2. Choose what to export, then one or more leagues, or club names such as Arsenal, and set the season (2025 means 2025/26).
  3. Click Start, then download the dataset as CSV, Excel, JSON or XML.

โš™๏ธ Understat scraper input

FieldTypeDefaultWhat it does
entitystringplayersplayers, teams, matches or playerCareer
leaguesarray["EPL"]EPL, La_liga, Bundesliga, Serie_A, Ligue_1, RFPL (max 6)
teamsarray[]Club names; squad tables for players, club filter for teams and matches
seasonstring2025Season start year, 2014 or later
matchStatus, dateFrom, dateTostringplayedMatches only: played, scheduled or all, and a date range
matchIdsarray[]Matches only: Understat match IDs or URLs (up to 200)
playerIdsarray[]Careers only: player IDs, URLs or exact names (up to 200)
includeShotsbooleanfalseMatches and careers: one extra row per shot
includeSplitsbooleanfalseTeams: situation, formation and timing splits per club
minMinutes, sortByinteger, string0, xGPlayers only: minutes filter and sort (xG, goals, xA, assists, shots, time, xGChain)
onlyNew, stateKey, resetSeenboolean, stringoffDeliver only new or changed rows; name or clear the memory
maxItemsintegernoneMaximum rows to export and be charged for

Example input:

{
"entity": "matches",
"leagues": ["EPL"],
"season": "2025",
"teams": ["Arsenal"],
"dateFrom": "2026-05-01",
"includeShots": true,
"maxItems": 60
}

Free users get a 10-row preview; paid users export up to 1,000,000 rows. Lists take up to 200 entries, and a season below 2014 fails at once with a clear message.

๐Ÿ“ฆ Understat scraper output

Each row is one player, team, match, shot or split, as set by recordType. Views are ready for players, teams, matches, shots and team splits. If a league, team or season returns no rows, the run still succeeds with a clear status message and charges nothing. If Understat cannot be read at all, the run fails with an explicit message instead of reporting an empty success. Understat's split figures do not sum to the table xG (Arsenal 2025: 83.98 against 77.49), so use each as published.

๐Ÿ†š Understat scraper vs alternatives

Read on 2026-10-10 from the public Store pages.

This actorscrapers_latjungle_synthesizer
DataPlayers, teams, matches, shots, careersLeague, player, team, match, shotsTeam season tables only
Only-new modeYesNot shownNot shown
Situation splitsTeam splitsSquad splitsNo
Price per 1,000$15 players, $4 teams, $2 matches, $0.10 shotsFrom $8.32From $0.90

parseforge ($5 per 1,000) sells player tables only, with no team, match or shot data. scrapers_lat covers similar modes and adds an optional AI summary, which we do not have. For player rows we cost about 1.7 times scrapers_lat and 3 times parseforge. Our team rows cost $4 per 1,000, so a team table costs more than at jungle_synthesizer, but ours adds players, matches and shots in one actor. Check current prices before choosing.

๐Ÿ’ผ Understat xG use cases

  • Recruitment and scouting: shortlist players by xG/90 and xA/90 across six leagues.
  • Betting models: build features from goals minus xG, team xGA and match xG.
  • Fantasy football and media: refresh xG and xA each matchday with only-new mode; source xPoints tables and shot maps.

๐Ÿ”Œ Run the Understat scraper via API and integrations

Call it from any language with the Apify API, or schedule it after each matchday.

curl -X POST "https://api.apify.com/v2/acts/recordsdata~understat-xg-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"entity":"teams","leagues":["EPL"],"season":"2025","maxItems":20}'

Results flow to Google Sheets, Zapier, Make, n8n or Airbyte through the Apify integrations.

๐Ÿค– Understat Scraper MCP server for AI agents

AI agents can call this Actor through the Apify MCP server at https://mcp.apify.com?tools=RecordsData/understat-xg-scraper. The URL loads only this Actor as a tool.

Add this to your MCP client configuration (Claude Desktop, Cursor, VS Code):

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=RecordsData/understat-xg-scraper"
}
}
}

Example agent prompt:

Use the Understat Scraper with entity teams for the EPL 2025 season, then list the three teams whose points are furthest above their xPoints and say who is over-performing.

Tool description: use it when an agent needs football xG, xA, team xGA and xPoints, match xG or shot coordinates for the top six leagues. It takes the same fields as the Input table.

The actor reads only public aggregate football statistics at a polite request rate, with no login and no personal data beyond public player names. Check Understat's terms for your use case and credit Understat when you republish its numbers.

โ“ Frequently asked questions

What is xG in football and how does Understat Scraper use it?

Expected goals (xG) is the probability-weighted value of the chances a player took. Understat Scraper exports xG from understat.com for every player, team, match and shot and computes xGDiff, which is goals minus xG. A positive value means a player scores more than their chances suggest.

How do I spell team names in Understat Scraper?

Use Understat's own spelling with underscores in the teams field, for example Manchester_City, Real_Madrid or Bayern_Munich. A spelling that Understat does not know returns no rows from Understat Scraper and no charge. If a club returns nothing, check the underscore spelling against the club name on understat.com.

Which seasons and leagues does Understat Scraper cover?

Understat Scraper covers the Premier League (EPL), La Liga, Bundesliga, Serie A, Ligue 1 and the Russian Premier League, from the 2014/15 season to the current one. Enter the start year of the season in the season field, for example 2025 for 2025/26, and pick one or more leagues in leagues.

Why did my Understat Scraper run return 0 results?

Usually the team spelling is wrong, the season is outside 2014 to the current year, or minMinutes is higher than any player reached. Understat Scraper then succeeds with a status message and costs nothing. An invalid season such as 1999 fails immediately with a clear message instead of an empty success.

How many player rows does an Understat league return?

When checked in October 2026, Understat Scraper returned these player rows for the 2025/26 season: 537 for the Premier League, 600 for La Liga, 499 for Bundesliga, 586 for Serie A, 553 for Ligue 1 and 470 for the Russian Premier League. A full season is one league request and costs one row price per player.

Am I charged for errors in Understat Scraper?

No. Understat Scraper charges only for valid priced rows, never for failed lookups. Error rows, empty results, unknown team lookups and duplicate rows are never billed, and the run stops cleanly when your maximum cost per run is reached. Use maxItems to cap spend.

Can I try Understat Scraper for free?

Yes. Free Apify users get a 10-row preview of Understat Scraper, which costs $0.15 at the Free-plan rate of $0.015 per player row. That is enough to check the columns before a full league export. Paid Apify plans unlock exports of up to 1,000,000 rows.

Can I scrape single matches or shots with Understat Scraper?

Yes. Set entity to matches and add includeShots to get one row per shot, with minute, X, Y, xG, result, situation, shot type and assisting player. Understat Scraper accepts match IDs or URLs, or a date range and clubs. For one player's shots over a whole career, use playerCareer with includeShots. Shots are off by default and cost $0.0001 per shot row.

Can I get team tables and xPoints with Understat Scraper?

Yes. Set entity to teams to get one row per team and season with rank, points, xG, xGA, xGD, npxG, xPoints and PPDA, computed from Understat's per-match history in the site's own order. Add includeSplits for situation, formation and timing splits. Team rows cost $0.004 each and split rows $0.001 each.

Can Understat Scraper return only new results?

Yes. Turn on onlyNew and Understat Scraper delivers only rows that are new or changed since the last run with the same filters, such as new match results, new shots and updated totals. Skipped rows are not charged. A second run on the same match returned 0 rows and charged 0. Use stateKey to name the memory and resetSeen to clear it.

Can I look up one player by ID or name in Understat Scraper?

Yes. Set entity to playerCareer and enter Understat player IDs, player URLs such as understat.com/player/8260, or a full name in playerIds. Understat Scraper returns one row per season and club, billed as player rows. An ambiguous name is rejected with the candidate IDs listed, so use the ID when two players share a name.

๐Ÿ”— Want more football and sports data?

๐Ÿ›Ÿ Support

Found a bug or a missing field? Open the Issues tab on this actor's page or write to contact.punkrecordsdata@gmail.com. Custom solutions available on request.

Last updated: 2026-10-11