SofaScore Scraper ⚽ Live Scores, Stats, Players & Odds avatar

SofaScore Scraper ⚽ Live Scores, Stats, Players & Odds

Pricing

from $1.00 / 1,000 results

Go to Apify Store
SofaScore Scraper ⚽ Live Scores, Stats, Players & Odds

SofaScore Scraper ⚽ Live Scores, Stats, Players & Odds

From $1/1K. Pull structured sports data from SofaScore across football, basketball, tennis, and 20+ sports. Search by keyword, paste URLs, fetch live matches, or download fixtures by date. Returns scores, stats, lineups, incidents, odds, teams, players, tournaments, and more.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

2

Bookmarked

549

Total users

94

Monthly active users

12 hours

Issues response

4 days ago

Last modified

Share

SofaScore Scraper: Live Scores, Stats, Lineups & Odds

SofaScore Scraper turns SofaScore into a clean sports data API. Get live scores, full match statistics, lineups with player ratings, goals and cards, betting odds, league tables, team squads and player profiles for football, basketball, tennis and 20+ other sports. Football matches can also carry the full shotmap (every shot's xG, coordinates, type and outcome) and the touch heatmap of every player who took part. Search by name, paste links, grab every live match, or download a whole day of fixtures, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

Why This Scraper?

  • Four ways to find data. Search by keyword, paste SofaScore links, pull every live match, or list all fixtures on a date. No need to build URLs by hand.
  • Four record types, fully expanded. Matches, teams, players and tournaments each come with 100+ named fields, plus the complete source object so nothing is lost.
  • Match depth on demand. Switch statistics, lineups, incidents, odds, fan votes, head-to-head history, the shot-level xG map and per-player touch heatmaps on or off per run, and pay only for what you use.
  • League tables and squads. Tournament records can carry full standings; team records can carry the whole squad.
  • 20+ sports. Football, basketball, tennis, ice hockey, American football, baseball, cricket, rugby, MMA and more.
  • Built for schedules. Incremental mode returns only new and changed matches on recurring runs, and a refused run fails loudly instead of returning an empty dataset.

Use Cases

  • Sports betting and odds research: collect pre-match odds, fan prediction votes and head-to-head records to build and backtest models.
  • Live score apps and dashboards: feed live matches, incidents and statistics into your own site, bot or alerting tool.
  • Fantasy sports and scouting: track player ratings, positions, market values and squad changes across leagues.
  • Sports analytics and data science: build historical datasets of results, xG-bearing statistics and lineups for machine learning. The shotmap gives shot-level xG with pitch coordinates, and player heatmaps give raw touch coordinates for spatial models.
  • Media and content teams: generate match previews, reports and league tables automatically.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
type"match" (also "team", "player", "tournament")
id10000001
sport"football"
name"Home Team - Away Team"
homeTeam / awayTeam"Home Team" / "Away Team"
homeScore / awayScore2 / 1
homeScoreHalftime / awayScoreHalftime1 / 0
statusType"finished"
startTimestamp1700000000
tournament / season / round"Sample League" / "24/25" / 12
venue / venueCity"Sample Stadium" / "Sample City"
referee / attendance"Referee Name" / 40000
urlSofaScore link to the match, team, player or tournament
statisticspossession, shots, passes, xG (when enabled)
lineupsstarters, subs, formations, player ratings (when enabled)
incidentsgoals, cards, substitutions (when enabled)
odds / votespre-match markets; fan prediction poll home / draw / away (when enabled)
headToHeadpast meetings and managers' record (when enabled)
shotmapfootball shot-by-shot map (when enabled): each shot's xG and xGoT, pitch coordinates, situation (open play, assisted, corner, set piece, fast break, penalty or direct free kick), outcome (goal, saved, blocked, miss), body part, shooter and goalkeeper
playerHeatmapsfootball touch heatmaps (when enabled): per player who took part, the total touch count and every touch's pitch coordinate
standingsfull league table on tournament records (when enabled)
currentRoundcurrent round of the tournament's latest season on tournament records (round, plus name and slug for cup rounds when the site supplies them); null when the season has no rounds
squadfull player list on team records (when enabled)
position / shirtNumber / marketValueplayer records: "F" / 10 / 50000000
rawthe complete source object

Team records also carry the manager, venue, capacity, colours and crest; player records carry the photo, preferred foot, contract end and market value currency; tournament records carry the tier, title holder and record title winner.

How to Use

  1. Pick a mode: search (by name), url (paste links), live (every live match now) or scheduled (all fixtures on a date).
  2. Fill in the fields for that mode, and switch on the match details you need.
  3. Set Max items to control run size and cost, then click Start.
  4. Download the dataset as JSON, CSV or Excel, or read it through the API.

Search for a team:

{
"mode": "search",
"searchQueries": ["Real Madrid"],
"searchType": "team",
"maxItems": 5
}

Every live football and tennis match right now:

{
"mode": "live",
"sports": ["football", "tennis"],
"includeStatistics": true,
"includeIncidents": true
}

All fixtures for a date, plus the next two days:

{
"mode": "scheduled",
"sports": ["football"],
"date": "2024-06-15",
"daysAhead": 2,
"maxItems": 200
}

Paste links (match, team, player, tournament):

{
"mode": "url",
"urls": [
"https://www.sofascore.com/team/football/real-madrid/2829",
"https://www.sofascore.com/player/lionel-messi/12994"
]
}

Match links must include the numeric id: copy the address bar on a match page (it ends with #id:<number>, with or without ?tab=...), or use an /event/<number> link. A match link with only the short code and no #id: is skipped with a warning.

Supported link types (any host: www.sofascore.com, m.sofascore.com, sofascore.com, sofascore.app):

LinkExample
Match with #id:https://www.sofascore.com/football/match/athletic-club-londrina/xPsAfMc#id:15526334
Eventhttps://www.sofascore.com/event/15526334
Teamhttps://www.sofascore.com/team/football/real-madrid/2829 or /football/team/real-madrid/2829
Tournamenthttps://www.sofascore.com/football/tournament/england/premier-league/17 or /tournament/football/england/premier-league/17 (returns the tournament record; turn on expandTournamentMatches to get its matches, see below)
Tournament seasonhttps://www.sofascore.com/football/tournament/england/championship/18#id:77347 (the trailing #id:<number> is the season the page shows)
Playerhttps://www.sofascore.com/player/erling-haaland/839956
Daily fixtureshttps://www.sofascore.com/football/2026-10-15 (every fixture that day, up to Max items)

All matches of a league or season: paste the tournament link and turn on expandTournamentMatches. The actor then lists every match of that tournament and returns each one as a normal match record, with statistics, lineups, incidents and the other detail options applied to every match. No need to paste match links one by one.

{
"mode": "url",
"urls": ["https://www.sofascore.com/football/tournament/england/championship/18#id:77347"],
"expandTournamentMatches": true,
"maxItems": 0
}
  • A link ending in #id:<number> lists that one season (the number is the season id the page shows). The example above is the whole 2025/26 season.
  • A link without it lists the season set by tournamentSeasons: current (latest season, the default) or all (every season the site holds for the tournament, newest first).
  • Both played and upcoming matches are listed, plus postponed and cancelled fixtures with their statusType (a postponed match that was replayed appears twice, once per site entry). A match appears once even if several links cover it.
  • Each match is a billed record like any other, so set Max items to the number you want; 0 means no limit. Switch off the detail options you do not need (each one is an extra request per match) to make a large run faster and cheaper.
  • If the platform time limit gets close, the run stops cleanly and keeps what it collected. Run again with Resume to continue.

Default change: if you run URL mode without setting urls, the actor now scrapes one sample each of a match, team, tournament, player and daily fixtures page instead of nothing. The full list of shapes is pre-filled in the form; the match link without #id: is skipped with a warning. If you send only startUrls, those links replace the sample list (they are never added to it).

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/sofascore-scraper").call(run_input={"mode": "live", "sports": ["football"]})
for match in client.dataset(run["defaultDatasetId"]).iterate_items():
print(match["name"], match["homeScore"], match["awayScore"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/sofascore-scraper').call({ mode: 'live', sports: ['football'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

How maxItems shapes a scheduled run

A single day of football holds several hundred fixtures across roughly a hundred competitions. Scheduled mode collects a day competition by competition, most important first (world and continental, then major national leagues, then the long tail), and stops once maxItems is reached. A capped run therefore returns the day's most prominent fixtures. To get the entire day, raise maxItems or set it to 0. Competitions are taken whole, so a run can return slightly more than maxItems.

Resume and recurring updates

  • Resume (resumeFromRunId) continues one interrupted run: paste its run or dataset ID and the actor skips everything already collected there, so you don't pay twice.
  • Incremental mode (incrementalMode) is for scheduled runs over the same scope. Each record is classified NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED or EXPIRED (only after a run that scanned the whole scope, and only with emitExpired). stateKey names or shares the stored state. A record is UPDATED when any returned field changed (score, status, venue, incidents, statistics, standings, squad and so on). Odds, fan votes and the live-clock and change-feed bookkeeping inside the raw event are excluded from the comparison and from changedFields (they are still returned in the row), so they alone never produce UPDATED. Add more with ignoreFieldsForChanges (dotted paths such as raw.venue work). Partial scans (Max items reached, Resume, refused targets) never mark records EXPIRED. With incremental mode off, output is exactly as before.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch, url, live, or scheduled.
searchQueriesarray["Real Madrid"]Names to look up (search mode).
searchTypestringallRestrict a search to team, player, tournament, or match.
urlsarrayone sample per link typeSofaScore links (url mode).
expandTournamentMatchesbooleanfalseURL mode: list every match of each tournament link instead of the tournament record.
tournamentSeasonsstringcurrentcurrent or all; which seasons to list for a tournament link without #id:<season>.
sportsarray["football"]Sports for live and scheduled modes.
datestringtodayYYYY-MM-DD for scheduled mode.
daysAheadinteger0Extra days after date.
includeStatisticsbooleantrueMatch and player statistics.
includeLineupsbooleantrueMatch lineups and ratings.
includeIncidentsbooleantrueGoals, cards, substitutions.
includeOddsbooleanfalsePre-match odds markets.
includeVotesbooleanfalseFan prediction poll per match.
includeH2HbooleanfalseHead-to-head history per match.
includeShotmapbooleanfalseFootball shotmap: xG, coordinates, situation and outcome per shot.
includePlayerHeatmapsbooleanfalseFootball touch heatmaps for every player who took part (one request per player, about 25-30 per match).
includeStandingsbooleantrueTournament league tables.
includeSquadbooleanfalseFull team squads.
maxItemsinteger20Stop after this many records (0 = no limit).
resumeFromRunIdstring(none)Continue one interrupted run.
incrementalModebooleanfalseReturn only new and changed records on scheduled runs.
ignoreFieldsForChangesarray[]Incremental mode only: field names (dotted paths allowed) excluded from change detection.
stateKeystring(none)Name or share an incremental-mode state.
emitUnchangedbooleanfalseAlso return (and bill) unchanged records.
emitExpiredbooleanfalseAlso return (and bill) expired records.
proxyobjectApify ProxyConnection settings.
mcpConnectorsarray(none)Optional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which records are created.
maxNotifyListingsinteger50Cap on items written to each connector per run.

Output Example

The Output tab offers one table per record kind: Matches, Teams, Players, Tournaments, plus a Changes table (change type, changed fields, first and last seen) for incremental runs. Every record carries a type field (match, team, player, tournament). Each run also saves a run summary to the key-value store under OUTPUT (records by type, targets scanned and refused).

Sample shape: values are illustrative placeholders, not from a live record.

{
"type": "match",
"id": 10000001,
"sport": "football",
"name": "Home Team - Away Team",
"homeTeam": "Home Team",
"awayTeam": "Away Team",
"homeTeamLogo": "https://img.sofascore.com/api/v1/team/2000001/image",
"awayTeamLogo": "https://img.sofascore.com/api/v1/team/2000002/image",
"homeScore": 2,
"awayScore": 1,
"statusType": "finished",
"winnerCode": 1,
"startTimestamp": 1700000000,
"tournament": "Sample League",
"season": "24/25",
"round": 12,
"venue": "Sample Stadium",
"referee": "Referee Name",
"attendance": 40000,
"country": "Country",
"url": "https://www.sofascore.com/football/match/home-team-away-team/AbCdEf#id:10000001",
"statistics": [{ "period": "ALL", "groups": [] }],
"incidents": [{ "incidentType": "goal", "time": 23, "player": { "name": "Player Name" } }],
"raw": {}
}

Plan Requirement

Datacenter connections are often refused by this site's API. The actor retries automatically on other connections and, when the default connection is refused, falls back to a residential or backup connection (it logs "Served over the backup connection (the default connection was unavailable)." when that happens). For reliable runs choose the residential group under Proxy & connection; residential traffic is billed to your Apify plan. Apify proxy access needs a paid Apify plan. On a plan without it, the run stops with a clear message instead of an empty result: "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required". If you choose residential on a free plan, the message says residential proxies are unavailable and asks you to upgrade or supply your own proxy URLs. If nothing could be loaded for another reason you get "Could not load any results page ... This is a connection problem, not an empty search."

FAQ

How much does it cost?

Pay per event. The current rates are shown on the Pricing tab (paid Apify plans get lower tiered rates). The events and when each one is charged:

EventWhen it is charged
Result (apify-default-dataset-item)once for each record pushed to the dataset
Detail enrichment (detail-enrichment)once per returned record that needed at least one extra detail lookup, no matter how many: match statistics, lineups, incidents, odds, votes, head-to-head or the shotmap; a team squad (includeSquad); player season statistics (includeStatistics); or the tournament season lookup, which every tournament record makes. A match record with the player heatmaps section delivered bills this event once for every 10 players mapped (the record's own lookups fold into the first block, so a typical match with about 30 players mapped is charged 3 events, and a record whose heatmaps could not be read stays at 1). Records that needed no extra lookup (for example a team without squad, or a match with all detail switches off) are not charged this event
Actor Start (apify-actor-start)once per run, per GB of memory

Unchanged or suppressed records in incremental mode are not billed. Use Max items to cap the cost of any run.

This actor collects only publicly available sports data. You are responsible for how you use it: follow SofaScore's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Sports results and statistics are generally facts, but logos, photos and odds may be subject to third-party rights.

Can I get only new or changed matches on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated records, and unchanged ones are not billed.

Why did a run return fewer matches than a full day?

Scheduled mode stops at Max items, most important competitions first. Set it higher, or to 0, to collect the whole day.

How do I get all matches of a league?

Use URL mode, paste the league page link, turn on expandTournamentMatches and set Max items to 0. Add #id:<season> to the link (copy it from the address bar) for one particular season, or set tournamentSeasons to all for every season. Cup rounds and league rounds are both included.

Why did my run fail instead of returning an empty dataset?

If the site refuses every request, the run stops with a clear message so "no matches today" is never confused with "nothing could be read". Run it again in a few minutes. If only some sports or dates could be read, you still get what was found.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

🔗 Want more sports data?

Pair this actor with these related scrapers from the same team:

⚽ FotMob Scraper ⚽ Match Details, Stats, Lineups & Players
Pull structured football data from FotMob: match details with scores, team stats, events...
⚽ OneFootball Scraper
Scrape public OneFootball data including football news, upcoming fixtures, match results...
⚽ Sportsbook Odds Scraper (1xBet, Melbet, Linebet, Paripulse)
Collect live and prematch betting odds from 1xBet, Melbet, Linebet and Paripulse. Give it...
⚽ Globo Esporte Scraper
Scrape public sports content from ge.globo.com, including news, videos, matches and feed...
⚽ Eventim Scraper
Scrape CTS Eventim Germany and EU event catalogue: concerts, festivals, comedy, sports...
⚽ JioHotstar Scraper
Scrape the JioHotstar catalog by content type or URL. Extract shows, movies, episodes...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.