Scrape SofaScore sports data into clean JSON or CSV: live
scores, fixtures and results, match statistics, lineups with player ratings, xG shot maps,
league tables, season player stats, player and team profiles, and rankings.
Get every match in play right now for football, basketball, tennis or any other sport
SofaScore covers, or leave watch running to get kick-offs, goals, period changes and final
results as they happen. List fixtures and results by date, round, team or season. For a
single match you get the score by period, venue, attendance, referee and managers, plus
SofaScore's team statistics (possession, xG, shots, passes, duels...), both lineups with
formations, ratings and per-player match stats, every incident (goals with assists, cards,
substitutions) and the shot map with xG, xGOT and pitch coordinates. Pull league tables
(total, home or away), season leaderboards with any statistic, per-game or per-90 values and
position, team or appearance filters, player profiles with market value and season stats,
squads, and FIFA, UEFA, ATP and WTA rankings.
Powered by ScrapeUnblocker:
the getPageSource API fetches the same JSON endpoints the sofascore.com site loads, and
this package turns their responses into typed records. You don't need a SofaScore account,
cookies, proxies, a headless browser or retry logic of your own.
- Live scores. Every match in play for a sport, with the score, the score by period and the match minute (football). Filter by tournament or team.
- Live watcher.
watchpolls the live feed and prints one JSON line per change:kickoff,score,status(half-time, second half, ...) andfinal(the match left the live feed; it is fetched once to report the final score). - Fixtures and results. By UTC date for a tournament or a country, by round (matchday), or as a team's or a season's latest results / upcoming fixtures (30 per page, as many pages as you ask for, de-duplicated).
- Match details. Score, score by period, extra time, penalty shoot-out and aggregate, winner, venue and capacity, attendance, referee, managers and the sofascore.com URL.
- Team statistics. Every statistic SofaScore shows (possession, expected goals, big chances, shots inside/outside the box, passes, long balls, duels, tackles, saves, ...) for the full match and each half, as display text and as numbers.
- Lineups. Formations, starters and substitutes, captain, shirt numbers, rating, minutes, goals, assists, xG, xA and every per-player match statistic SofaScore records, plus injured and suspended players with the reason and expected return date.
- Incidents. Goals with assists and the running score, yellow and red cards (manager cards included), substitutions (injury subs flagged), added time and period ends, in match order.
- Shot maps. Every shot with minute, outcome (goal, save, miss, block, post), situation, body part, xG, xGOT, shooter coordinates, goal-mouth location and goalkeeper.
- Head-to-head. Previous results between the two teams and the two managers.
- League tables. Total, home or away; position, played, won, drawn, lost, goals, goal
difference, points and the promotion / relegation zone. Group stages (World Cup, ...)
return every group's table, named in
group. - Season leaderboards. SofaScore's player statistics for a season: the five stat groups (summary, attack, defence, passing, goalkeeper) or any statistics you name, sorted by any of them, as totals, per game or per 90 minutes, filtered by position, team and minimum appearances, 100 players per request.
- Players. Profile (position, detailed positions, shirt number, height, preferred foot, date of birth, age, nationality, team, contract end, SofaScore's market value estimate), every season with statistics, and the full statistics for any tournament season.
- Teams and squads. Team profile (country, league, manager, venue, founding date) and the squad with positions, ages, nationalities and market values.
- Rankings. FIFA, UEFA country coefficients, ATP and WTA.
- Discovery. Search teams, players and tournaments; list a sport's countries and their
competitions; built-in aliases for popular competitions (
premier-league,laliga,champions-league,nba, ...). - IDs or URLs. Every command takes SofaScore IDs or the sofascore.com page URL.
- Output as JSON, JSON Lines, CSV (Excel-friendly) or a terminal table.
- Robust: retries throttled, blocked or timed-out requests with backoff, refetches a response that is not JSON, and returns empty sections when a match has no data for them.
git clone https://github.com/ScrapeUnblocker/sofascore-scraper.git
cd sofascore-scraper
pip install .Get an API key at scrapeunblocker.com
and put it in the environment (or in a .env file, see .env.example):
export SCRAPEUNBLOCKER_KEY=your_key_herePython 3.9 or newer. The only dependency is the official
scrapeunblocker SDK.
# Every football match in play right now (or basketball, tennis, ice-hockey, ...)
sofascore-scraper live
sofascore-scraper live --sport basketball -f json
# Stream kick-offs, goals, period changes and final scores (JSON Lines)
sofascore-scraper watch -t premier-league -t champions-league --interval 60
# Fixtures and results
sofascore-scraper matches -t premier-league --date today
sofascore-scraper matches -t premier-league --round 9
sofascore-scraper matches --team 42 --results --pages 2
sofascore-scraper matches -t laliga --fixtures -f csv -o laliga-fixtures.csv
# One match: details + statistics, lineups and incidents (JSON), or every section
sofascore-scraper match 16363891
sofascore-scraper match 16363891 -i all
sofascore-scraper match 16363891 16363902 -f csv -o matches.csv # one row per match
# The parts of a match as tables or CSV
sofascore-scraper stats 16363891
sofascore-scraper lineups 16363891 -f csv -o player-stats.csv
sofascore-scraper lineups 16363891 --missing
sofascore-scraper incidents 16363891 --type goal
sofascore-scraper shotmap 16363891 -f csv -o shots.csv
# League table (total / home / away), current or any season
sofascore-scraper standings premier-league
sofascore-scraper standings serie-a --table home --season 25/26
sofascore-scraper seasons premier-league
# Season leaderboards
sofascore-scraper leaderboard premier-league
sofascore-scraper leaderboard premier-league -g attack --per per-90 --min-apps 5
sofascore-scraper leaderboard bundesliga --fields goals,expectedGoals,assists --order goals \
--position F -n 20 -f csv -o strikers.csv
# Players and teams
sofascore-scraper player 934235 -t premier-league
sofascore-scraper player https://www.sofascore.com/football/player/declan-rice/856714 --seasons
sofascore-scraper team 42 --squad
sofascore-scraper squad 42 --position F
# Rankings, search and discovery
sofascore-scraper rankings fifa -n 20
sofascore-scraper rankings atp
sofascore-scraper search "bukayo saka" --type players
sofascore-scraper tournaments --country Spain
sofascore-scraper aliasesCommon options: -f json|jsonl|csv|table, -o FILE, --proxy-country, --retries N and
-v (log each request to stderr). --season takes a season year as SofaScore writes it
(25/26, 2025/26, 2026) or a season ID; the default is the current season. Run
sofascore-scraper <command> --help for every option.
from sofascore_scraper import SofascoreScraper
sofa = SofascoreScraper() # reads SCRAPEUNBLOCKER_KEY
# Live scores
for m in sofa.live("football"):
print(m.tournament, m.home_team, m.score, m.away_team, m.minute)
# League table and recent results
table = sofa.standings("premier-league")
results = sofa.team_matches(42, "last", pages=2) # Arsenal, newest first
round_9 = sofa.round("premier-league", 9)
today = sofa.scheduled("today", tournament="laliga")
# A full match
game = sofa.match(16363891, ["statistics", "lineups", "incidents", "shotmap", "h2h"])
game.stat("expectedGoals") # (1.96, 0.63)
best = max(game.players(), key=lambda p: p.rating or 0)
goals = [i for i in game.incidents if i.type == "goal"]
big_chances = [s for s in game.shots if (s.xg or 0) > 0.3]
# Season leaderboard: forwards with 5+ appearances, goals per 90
top = sofa.leaderboard(
"premier-league",
fields=["goals", "expectedGoals", "minutesPlayed"],
order="-goals",
accumulation="per-90",
positions=["F"],
min_appearances=5,
limit=20,
)
# Player profile with this season's league statistics
saka = sofa.player(934235, tournament="premier-league")
saka.market_value, saka.season_stats.statistics["rating"]
# Live watcher (runs until interrupted, or until max_polls)
for update in sofa.watch(tournaments=["premier-league"], interval=60):
print(update.kind, update.match.home_team, update.match.score, update.match.away_team)Every record is a dataclass with to_dict(); sofascore_scraper.write(records, "csv", path)
and to_csv_file(records, path) save any list of them.
examples/league_table_to_csv.py: total, home and away tables to CSV.examples/match_report.py: score, xG, possession, goals and the best-rated players of a match.examples/team_shots_dataset.py: a shot-level xG dataset from a team's latest matches.examples/live_goal_alerts.py: print goals and full-time scores in the competitions you follow.
sofascore-scraper live -n 5:
id start (UTC) status tournament home score away
16318018 2026-11-01 03:10 1st half 18' Liga MX, Apertura Club América 0-0 CD Toluca
15171751 2026-11-01 01:30 2nd half 90+4' MLS Colorado Rapids 2-4 Chicago Fire
17200581 2026-11-01 03:00 Started Fraser Valley Soccer League Championship - A Akal Pacific United 0-0 Mission SC
17200617 2026-11-01 03:15 Started Fraser Valley Soccer League Championship - A GVU Punjab 0-0 RHO FC B
17438693 2026-11-01 02:20 Started Knockout Cup Avatiu FC 1-0 Matavera-Ngatangiia FC
sofascore-scraper live --sport tennis -n 3:
id start (UTC) status tournament home score away
17377213 2026-11-01 03:00 1st set Tokyo Leylah Fernandez 0-0 Diana Shnaider
17452141 2026-11-01 03:25 1st set Hong Kong Himeno Sakatsume 0-0 Elena Pridankina
17377176 2026-11-01 02:25 2nd set Queretaro, Mexico Bianca Andreescu 1-0 Carole Monnet
sofascore-scraper standings premier-league:
# team P W D L GF GA GD Pts zone
1 Manchester City 9 7 0 2 20 10 +10 21 Champions League
2 Arsenal 8 7 0 1 13 5 +8 21 Champions League
3 Brighton & Hove Albion 9 6 1 2 24 7 +17 19 Champions League
4 Chelsea 9 5 1 3 19 15 +4 16 Champions League
5 Liverpool FC 8 4 3 1 11 8 +3 15 Europa League
6 Brentford 9 3 5 1 16 9 +7 14
sofascore-scraper matches --team 42 --results -n 3:
id start (UTC) status tournament home score away
17118366 2026-10-27 20:00 AP EFL Cup Fleetwood Town 1-1 (pens 5-3) Arsenal
16363891 2026-10-24 14:00 Ended Premier League Arsenal 2-0 Everton
16938859 2026-10-21 19:00 Ended UEFA Champions League FC Bayern München 2-2 Arsenal
sofascore-scraper leaderboard premier-league --fields goals,expectedGoals,assists,minutesPlayed --order goals --position F --min-apps 5 -n 5:
# player team statistics
1 Erling Haaland Manchester City goals=9 expectedGoals=6.57 assists=0 minutesPlayed=800
2 Alexander Isak Liverpool FC goals=6 expectedGoals=4.27 assists=0 minutesPlayed=571
3 João Pedro Chelsea goals=5 expectedGoals=3.03 assists=3 minutesPlayed=521
4 Nicolas Jackson Aston Villa goals=5 expectedGoals=2.31 assists=0 minutesPlayed=641
5 Evanilson Bournemouth goals=4 expectedGoals=3.59 assists=4 minutesPlayed=757
sofascore-scraper match 16363891 -i all (trimmed):
{
"match": {
"id": 16363891,
"sport": "football",
"tournament": "Premier League",
"tournament_id": 17,
"season": "Premier League 26/27",
"round": 8,
"start_time": "2026-10-24T14:00:00Z",
"status": "finished",
"home_team": "Arsenal",
"away_team": "Everton",
"home_score": 2,
"away_score": 0,
"home_periods": [1, 1],
"away_periods": [0, 0],
"winner": "home",
"url": "https://www.sofascore.com/football/match/everton-arsenal/RY#id:16363891"
},
"venue": "Emirates Stadium",
"venue_city": "London",
"venue_capacity": 60704,
"attendance": 60207,
"referee": "Tony Harrington",
"home_manager": "Mikel Arteta",
"away_manager": "David Moyes",
"statistics": [
{"period": "ALL", "group": "Match overview", "key": "ballPossession", "name": "Ball possession",
"home": "58%", "away": "42%", "home_value": 58, "away_value": 42}
],
"incidents": [
{"type": "goal", "detail": "regular", "minute": 7, "side": "home", "player": "Ezri Konsa",
"assist": "Viktor Gyökeres", "home_score": 1, "away_score": 0}
],
"shots": [
{"side": "home", "team": "Arsenal", "player": "Declan Rice", "minute": 4, "outcome": "block",
"situation": "assisted", "body_part": "right-foot", "xg": 0.0412, "xgot": 0, "x": 18.1,
"y": 65.8, "goalkeeper": "Jordan Pickford"}
],
"h2h": {"home_wins": 7, "draws": 2, "away_wins": 1, "manager_home_wins": 9, "manager_draws": 3,
"manager_away_wins": 2},
"sections": ["statistics", "lineups", "incidents", "shotmap", "h2h"]
}python examples/match_report.py 16363891:
Premier League - 2026-10-24T14:00:00Z
Arsenal 2-0 Everton (Ended)
at Emirates Stadium, London - attendance 60207
Possession: 58 - 42
xG: 1.96 - 0.63
Goals
7' Ezri Konsa (assist Viktor Gyökeres) 1-0
68' Gabriel Magalhães (assist Ben White) 2-0
Best rated
9 Gabriel Magalhães (Arsenal)
8.2 Declan Rice (Arsenal)
8.1 Ezri Konsa (Arsenal)
8 Martin Ødegaard (Arsenal)
7.7 Ben White (Arsenal)
Shot map
Arsenal: 20 shots, 1.96 xG
Everton: 8 shots, 0.63 xG
The sofascore.com site is a single-page app that loads its data from JSON endpoints under
https://www.sofascore.com/api/v1/ (/event/<id>, /event/<id>/lineups,
/unique-tournament/<id>/season/<id>/standings/total, /player/<id>, ...). The scraper
asks ScrapeUnblocker's getPageSource for those URLs, decodes the JSON and maps it to
dataclasses, so it does not depend on page layout or CSS classes.
A few things worth knowing:
- Requests. One request per endpoint.
matchmakes one request plus one per section (statistics,lineupsandincidentsby default;-i alladdsshotmapandh2h,--basicskips them). Commands that need the current season look it up once per run.watchmakes one request per poll, plus one for each match that finishes. - Dates.
--dateis a UTC date. SofaScore's daily list covers every time zone, so it includes matches from the evening before; the scraper keeps the ones that start on the date you asked for. - Scores.
home_score/away_scoreleave out a penalty shoot-out; the shoot-out goals are inhome_penalties/away_penalties(shown as1-1 (pens 5-3)). - Match minute.
minuteis worked out from the time the current half started, the way the site's clock is. It is set for a running half (or extra-time period) of a football match, and it is as fresh as the request. - Coverage varies. Top competitions have statistics, lineups, player ratings and shot maps; smaller ones may have only the score. A section SofaScore has no data for comes back empty, not as an error.
- Leaderboard statistics are SofaScore's own keys (
goals,expectedGoals,assists,keyPasses,tackles,saves,rating, ...). Run a stat group once to see the names, or read them from a player'sseason_stats. A name SofaScore does not know returns no values (the scraper logs a warning). - Market values are SofaScore's estimates (usually in EUR), not transfer fees.
- Manager cards are incidents with
is_manager: true; SofaScore stores their minute separately, and the scraper uses it.
Please scrape responsibly: keep request rates and watch intervals modest, respect SofaScore's terms, and use the data for research, analysis and personal projects.
sofascore-scraper/
├── src/sofascore_scraper/
│ ├── __init__.py # public API and __version__
│ ├── scraper.py # SofascoreScraper: fetch + retries, matches, standings, players, watch
│ ├── parsing.py # SofaScore JSON -> Match / MatchDetails / Shot / StandingRow / ...
│ ├── models.py # dataclasses with to_dict / to_row / table layouts
│ ├── urls.py # API endpoints, sofascore.com URLs, ID and date parsing
│ ├── options.py # stat groups, rankings, search scopes, tournament aliases
│ ├── export.py # JSON / JSONL / CSV / table output
│ └── cli.py # sofascore-scraper command
├── examples/ # league table, match report, shot dataset, live goal alerts
├── tests/ # offline tests with a mocked client (no API credit used)
├── pyproject.toml
├── Makefile
└── .github/workflows/ci.yml
pip install -e ".[dev]"
make lint # ruff check + ruff format --check
make test # pytest, offline
make format # ruff formatThe tests use synthetic responses shaped like SofaScore's and a fake client, so they run without an API key or network access.
MIT - Copyright (c) 2026 ScrapeUnblocker. This project is not affiliated with or endorsed by SofaScore.