# SofaScore Scraper | Live Scores & Match Data API (`parsebird/sofascore-scraper`) Actor

\[💰 $0.9 / 1K] Scrape live scores, fixtures, lineups, statistics, odds, and standings from SofaScore. Search by team/player/tournament, paste match links, or pull every live or scheduled match across any sport.

- **URL**: https://apify.com/parsebird/sofascore-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Categories:** Automation, News, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### SofaScore Scraper

Scrape [SofaScore](https://www.sofascore.com/) — live scores, fixtures, lineups, statistics, odds, and standings — by team, player, or tournament keyword, by pasting match links, or by pulling every live or scheduled match for any sport.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Search, paste links, or pull every live/scheduled match, then enrich each one with statistics, lineups, incidents, odds, fan votes, standings, and squads — with built-in change-tracking for recurring monitoring campaigns.
</td>
</tr></table>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

```
parsebird/sofascore-scraper on Apify. Call: ApifyClient("TOKEN").actor("parsebird/sofascore-scraper").call(run_input={...}), then client.dataset(run["defaultDatasetId"]).list_items().items for results. Key inputs: mode (string, "search"/"url"/"live"/"scheduled"), searchQueries (string array, default ["Real Madrid"], search mode), searchType ("all"/"team"/"player"/"tournament"/"match"), urls (string array, url mode — team/player/tournament/match links; match links need "#id:<number>" or "/event/<number>"), sports (string array, default ["football"], live/scheduled modes), date (string, "YYYY-MM-DD" or "today", scheduled mode), daysAhead (integer, default 0), includeStatistics/includeLineups/includeIncidents (boolean, default true), includeOdds/includeVotes/includeSquad (boolean, default false), includeStandings (boolean, default true), maxItems (integer, default 20, 0=unlimited), resumeFromRunId (string, continue an interrupted crawl), incrementalMode (boolean, tags records NEW/CHANGED/UNCHANGED), stateKey (string, name a monitoring campaign), emitUnchanged/emitExpired (boolean, default false). Output fields vary by type ("match"/"team"/"player"/"tournament"): id, name, sport, homeTeam/awayTeam, homeScore/awayScore, statusType, startTimestamp, tournament/uniqueTournament, season, round, venue, referee, statistics/lineups/incidents/odds/votes/standings/squad (when enabled), url, raw. Full actor spec: fetch build via GET https://api.apify.com/v2/acts/parsebird~sofascore-scraper (Bearer TOKEN). Get token: https://console.apify.com/account/integrations
```

### What does SofaScore Scraper do?

This Actor scrapes [SofaScore](https://www.sofascore.com/), the live-score platform covering football, tennis, basketball, and dozens of other sports, by rendering its internal API in a real browser — SofaScore blocks plain HTTP requests at the network-fingerprint level, so a browser is required to get through reliably.

- 🔎 **Four modes** — search by team/player/tournament/match keyword, paste SofaScore links directly, pull every match live right now, or every scheduled fixture across a date range
- 📊 **Deep enrichment, opt-in** — statistics, lineups with player ratings, incidents (goals/cards/subs), pre-match odds, fan prediction votes, full league standings, and complete squads
- 🔁 **Incremental monitoring** — tag every record `NEW`, `CHANGED`, or `UNCHANGED` against a previous run sharing the same `stateKey`, so recurring campaigns only pay attention to what actually moved
- ▶️ **Resumable crawls** — pass a previous run's ID via `resumeFromRunId` to continue an interrupted large crawl without re-fetching or re-billing what it already collected
- ⏱️ **Scheduling** — run this Actor on a timer via Apify Scheduler for live-score monitoring or daily fixture digests
- 🔌 **API access** — trigger runs and pull results programmatically via the Apify API or client libraries
- 📊 **Flexible export** — download results as JSON, CSV, or Excel, or query them via API

### What data can you extract from SofaScore?

| Field | Description |
|-------|-------------|
| `type` | `match`, `team`, `player`, or `tournament` |
| `name` / `homeTeam` / `awayTeam` | Match or entity name |
| `homeScore` / `awayScore` / `homeScoreHalftime` / `awayScoreHalftime` | Scores, full-time and half-time |
| `statusType` / `winnerCode` | Match state (`notstarted`, `inprogress`, `finished`) and result |
| `tournament` / `uniqueTournament` / `season` / `round` | Competition context |
| `venue` / `venueCity` / `latitude` / `longitude` / `referee` / `attendance` | Match logistics |
| `statistics` / `lineups` / `incidents` / `odds` / `votes` | Match detail, when enabled |
| `standings` / `squad` | Tournament table / team roster, when enabled |
| `url` | Direct link back to the SofaScore page |

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `mode` | string | No | `search` | `search`, `url`, `live`, or `scheduled` |
| `searchQueries` | string array | No | `["Real Madrid"]` | Keywords to resolve (search mode) |
| `searchType` | string | No | `all` | Restrict a query to `team`, `player`, `tournament`, or `match` |
| `urls` | string array | No | sample links | SofaScore links (url mode) |
| `sports` | string array | No | `["football"]` | Sports for live and scheduled modes |
| `date` | string | No | `today` | `YYYY-MM-DD` for scheduled mode |
| `daysAhead` | integer | No | `0` | Extra days after `date` |
| `includeStatistics` | boolean | No | `true` | Match and player statistics |
| `includeLineups` | boolean | No | `true` | Match lineups and ratings |
| `includeIncidents` | boolean | No | `true` | Goals, cards, substitutions |
| `includeOdds` | boolean | No | `false` | Pre-match odds markets |
| `includeVotes` | boolean | No | `false` | Fan prediction poll per match |
| `includeStandings` | boolean | No | `true` | Tournament league tables |
| `includeSquad` | boolean | No | `false` | Full team squads |
| `maxItems` | integer | No | `20` | Stop after this many records. `0` = no limit |
| `resumeFromRunId` | string | No | — | Continue one interrupted crawl |
| `incrementalMode` | boolean | No | `false` | Recurring change detection |
| `stateKey` | string | No | — | Name/share an incremental-mode monitoring campaign |
| `emitUnchanged` | boolean | No | `false` | Also return (and bill) `UNCHANGED` entities |
| `emitExpired` | boolean | No | `false` | Also return (and bill) `EXPIRED` entities |
| `proxy` | object | No | Apify proxy | Connection settings |

### Output example

```json
{
  "type": "match",
  "id": 16246416,
  "sport": "football",
  "name": "Indonesia - Vietnam",
  "homeTeam": "Indonesia",
  "awayTeam": "Vietnam",
  "homeScore": 0,
  "awayScore": 2,
  "statusType": "inprogress",
  "winnerCode": null,
  "startTimestamp": 1785763800,
  "tournament": "ASEAN Championship, Group A",
  "uniqueTournament": "ASEAN Championship",
  "season": "2026",
  "round": 4,
  "venue": "Pakansari Stadium",
  "venueCity": "Bogor Regency",
  "referee": "Timothy Danaskos",
  "country": "Asia",
  "url": "https://www.sofascore.com/football/match/vietnam-indonesia/EWbsaQc#id:16246416",
  "hasXg": false,
  "incidents": [{ "incidentType": "goal", "time": 23, "player": { "name": "Player Name" } }],
  "raw": {}
}
```

Download results in **JSON, CSV, or Excel** directly from the Apify Console, or pull them programmatically via the API.

### Use cases

- **Live-score monitoring** — poll `mode: "live"` on a schedule to power a dashboard or alerting pipeline
- **Fixture digests** — pull `mode: "scheduled"` for the day (plus `daysAhead`) to build a daily or weekly preview
- **Competitor/brand research** — pull a team or player's full profile, squad, and standings context in one call
- **Change-tracked monitoring** — run `incrementalMode` on a schedule with a shared `stateKey` to get only what changed since the last check, instead of re-processing everything every time
- **Betting/analytics research** — combine `includeOdds` and `includeVotes` with match statistics for pre-match analysis

### How to scrape SofaScore with this Actor

1. Go to the [SofaScore Scraper](https://apify.com/parsebird/sofascore-scraper) page on Apify Store
2. Click **Try for free** — new users get a free trial to test the Actor before paying
3. Pick a **mode** — search by keyword, paste links, live, or scheduled
4. Toggle the **enrichments** you need (statistics, lineups, incidents, odds, votes, standings, squad)
5. Set `maxItems` to cap the run size (or `0` for unlimited)
6. Click **Start** — the Actor renders SofaScore's own API in a real browser and normalizes every result
7. When the run finishes, download your data as **JSON, CSV, or Excel**, or fetch it via the API

### Use with the Apify API

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("parsebird/sofascore-scraper").call(run_input={
    "mode": "live",
    "sports": ["football"],
    "includeStatistics": True,
    "includeIncidents": True,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(f"{item['name']} - {item['homeScore']}:{item['awayScore']} ({item['statusType']})")
```

**JavaScript**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

const run = await client.actor('parsebird/sofascore-scraper').call({
    mode: 'live',
    sports: ['football'],
    includeStatistics: true,
    includeIncidents: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.log(`${item.name} - ${item.homeScore}:${item.awayScore} (${item.statusType})`);
});
```

See the [Apify API documentation](https://docs.apify.com/api/v2) for full reference, or the Actor's **API** tab for ready-to-run request snippets in more languages.

### How much does it cost to scrape SofaScore?

This Actor uses **Pay-per-event** pricing with two events — you only pay for records actually returned, with no separate platform rental fee.

| Event | Price per event (Free plan) | Price per 1,000 |
|-------|-----------------------------|-----------------|
| `record-scraped` | $0.0015 | $1.50 |
| `detail-enrichment` | $0.0009 | $0.90 |

`record-scraped` is charged once per match, team, player, or tournament pushed to the dataset. `detail-enrichment` is charged once more on top, only when at least one enrichment (statistics, lineups, incidents, odds, votes, standings, or squad) was actually attached. A 1,000-match run with statistics and incidents enabled costs about $2.40 on the Free plan. Start with the free trial and a low `maxItems` to preview results before scaling up.

### FAQ

**Why does SofaScore need a browser instead of a simple API call?**
SofaScore blocks non-browser HTTP clients at the network-fingerprint level — the same request that returns real data from a browser returns a 403 from a plain HTTP library. This Actor renders every request in a real headless browser to get through reliably.

**Why does this Actor default to a country-pinned residential proxy?**
SofaScore also blocks by IP reputation: even a real headless browser gets a 403 from a datacenter IP, and an unpinned residential proxy pool can return a similarly flagged IP. Pinning to a specific country's residential pool (US by default) reliably avoids this — confirmed by direct testing on Apify's own infrastructure.

**How does `searchType: "match"` work?**
SofaScore's own search only returns match results for match-shaped queries (e.g. `"Real Madrid Barcelona"` or `"Real Madrid vs Barcelona"`), not for a single team/player name — that's how the underlying search behaves, not a limitation of this Actor.

**What happens with `mode: "scheduled"` under the hood?**
SofaScore's site no longer exposes a single "all matches for date X" endpoint — it first looks up which tournaments have matches that day, then fetches each tournament's events for that date separately. This Actor reproduces that same two-step lookup, which makes `scheduled` mode slower than `live` or `url` mode, especially across many sports or several `daysAhead`.

**How does incremental mode decide NEW vs. CHANGED vs. UNCHANGED?**
Each record's content (excluding the raw upstream object) is hashed and compared against the previous run that used the same `stateKey`. No previous record with that ID → `NEW`. Same ID but a different hash → `CHANGED`. Same ID and hash → `UNCHANGED` (returned only if `emitUnchanged` is on). An ID seen in the previous run but absent from this one is `EXPIRED` (returned only if `emitExpired` is on, as a minimal placeholder record since fresh data for it isn't available).

**What exactly does `resumeFromRunId` skip?**
It reads the referenced run's dataset, builds a set of already-pushed `type:id` pairs, and skips those specific entities in this run — so a crawl that got cut off partway (e.g. a timeout on a huge `scheduled` run) can continue without re-fetching or re-billing what it already collected.

**Can I schedule recurring runs?**
Yes. Use Apify's [Scheduler](https://docs.apify.com/platform/schedules) to run this Actor on a timer — pair it with `incrementalMode` and a fixed `stateKey` for change-tracked monitoring.

**Is it legal to scrape SofaScore?**
SofaScore's match, team, and player pages are publicly viewable without a login. You're responsible for complying with SofaScore's Terms of Service for your specific use case. See Apify's [blog post on the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) for general background.

**Can I access results via API?**
Yes. Every run's dataset is available through the [Apify API](https://docs.apify.com/api/v2) and client libraries (Python, JavaScript) — see the Actor's **API** tab for ready-made snippets.

**Something not working?**
Open an issue on the Actor's **Issues** tab in Apify Console — the ParseBird team monitors it directly.

### Related Actors

Other sports and monitoring Actors from ParseBird:

- [Polymarket Scraper](https://apify.com/parsebird/polymarket-scraper) — prediction-market odds and pricing data
- [DexScreener Crypto Scraper](https://apify.com/parsebird/dexscreener-crypto-scraper) — real-time market data monitoring
- [HTTP Request Actor](https://apify.com/parsebird/http-request-actor) — general-purpose API/webhook integration

# Actor input Schema

## `mode` (type: `string`):

search: resolve keywords. url: paste SofaScore links. live: every live match right now. scheduled: fixtures for a date range.

## `searchQueries` (type: `array`):

Keywords to resolve, e.g. a team, player, or tournament name. Used when mode is search.

## `searchType` (type: `string`):

Restrict search results to one entity type.

## `urls` (type: `array`):

SofaScore links to team, player, tournament, or match pages. Used when mode is url. Match links must include the numeric id: copy the address bar while on a match page (it ends with #id:<number>), or use an /event/<number> link.

## `sports` (type: `array`):

Sports to cover. Used when mode is live or scheduled, e.g. football, tennis, basketball.

## `date` (type: `string`):

Date for scheduled mode (YYYY-MM-DD), or "today".

## `daysAhead` (type: `integer`):

Extra days to include after date (scheduled mode). 0 = only the given date.

## `includeStatistics` (type: `boolean`):

Match and player statistics (possession, shots, passes, xG, ...).

## `includeLineups` (type: `boolean`):

Match lineups, formations, and player ratings.

## `includeIncidents` (type: `boolean`):

Goals, cards, and substitutions.

## `includeOdds` (type: `boolean`):

Pre-match odds markets.

## `includeVotes` (type: `boolean`):

Fan prediction poll (community sentiment) per match.

## `includeStandings` (type: `boolean`):

Tournament league tables.

## `includeSquad` (type: `boolean`):

Full team squads.

## `maxItems` (type: `integer`):

Stop after this many records. 0 = no limit (bounded by a safety cap).

## `resumeFromRunId` (type: `string`):

Continue a previously interrupted crawl: entities already pushed by that run are skipped (not re-fetched or re-charged) in this run. Leave empty for a normal run.

## `incrementalMode` (type: `boolean`):

Compare this run's results against the last run sharing the same state key, and tag each record NEW, CHANGED, or UNCHANGED.

## `stateKey` (type: `string`):

Name this monitoring campaign so recurring runs (e.g. on a schedule) compare against each other. Leave empty to use a single default campaign.

## `emitUnchanged` (type: `boolean`):

Also return (and bill) records with no change since the last incremental-mode run.

## `emitExpired` (type: `boolean`):

Also return (and bill) a minimal record for entities seen in a previous incremental-mode run that no longer appear in this one.

## `proxy` (type: `object`):

SofaScore blocks both non-browser traffic and datacenter IPs even from a real browser; a country-pinned residential proxy is required for reliable access.

## Actor input object example

```json
{
  "mode": "search",
  "searchQueries": [
    "Real Madrid"
  ],
  "searchType": "all",
  "urls": [
    "https://www.sofascore.com/team/football/real-madrid/2829",
    "https://www.sofascore.com/player/lionel-messi/12994"
  ],
  "sports": [
    "football"
  ],
  "date": "today",
  "daysAhead": 0,
  "includeStatistics": true,
  "includeLineups": true,
  "includeIncidents": true,
  "includeOdds": false,
  "includeVotes": false,
  "includeStandings": true,
  "includeSquad": false,
  "maxItems": 5,
  "resumeFromRunId": "",
  "incrementalMode": false,
  "stateKey": "",
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "search",
    "searchQueries": [
        "Real Madrid"
    ],
    "searchType": "all",
    "urls": [
        "https://www.sofascore.com/team/football/real-madrid/2829",
        "https://www.sofascore.com/player/lionel-messi/12994"
    ],
    "sports": [
        "football"
    ],
    "date": "today",
    "daysAhead": 0,
    "includeStatistics": true,
    "includeLineups": true,
    "includeIncidents": true,
    "includeOdds": false,
    "includeVotes": false,
    "includeStandings": true,
    "includeSquad": false,
    "maxItems": 5,
    "resumeFromRunId": "",
    "incrementalMode": false,
    "stateKey": "",
    "emitUnchanged": false,
    "emitExpired": false,
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/sofascore-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "searchQueries": ["Real Madrid"],
    "searchType": "all",
    "urls": [
        "https://www.sofascore.com/team/football/real-madrid/2829",
        "https://www.sofascore.com/player/lionel-messi/12994",
    ],
    "sports": ["football"],
    "date": "today",
    "daysAhead": 0,
    "includeStatistics": True,
    "includeLineups": True,
    "includeIncidents": True,
    "includeOdds": False,
    "includeVotes": False,
    "includeStandings": True,
    "includeSquad": False,
    "maxItems": 5,
    "resumeFromRunId": "",
    "incrementalMode": False,
    "stateKey": "",
    "emitUnchanged": False,
    "emitExpired": False,
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/sofascore-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "searchQueries": [
    "Real Madrid"
  ],
  "searchType": "all",
  "urls": [
    "https://www.sofascore.com/team/football/real-madrid/2829",
    "https://www.sofascore.com/player/lionel-messi/12994"
  ],
  "sports": [
    "football"
  ],
  "date": "today",
  "daysAhead": 0,
  "includeStatistics": true,
  "includeLineups": true,
  "includeIncidents": true,
  "includeOdds": false,
  "includeVotes": false,
  "includeStandings": true,
  "includeSquad": false,
  "maxItems": 5,
  "resumeFromRunId": "",
  "incrementalMode": false,
  "stateKey": "",
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call parsebird/sofascore-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=parsebird/sofascore-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/uHyxrDkhk5MfIszkE/builds/TBxOz095VTfjgxnP9/openapi.json
