# SofaScore Football Scraper (`crawlstone/sofascore-football-scraper`) Actor

Extract comprehensive SofaScore football data, including live matches, fixtures, competitions, match details, team records, and player statistics.

- **URL**: https://apify.com/crawlstone/sofascore-football-scraper.md
- **Developed by:** [Crawl Stone](https://apify.com/crawlstone) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 3 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.00 / 1,000 successful 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 Football Scraper

We built SofaScore Football Scraper to provide a straightforward, query-based way to collect comprehensive football data. This Actor connects directly to **SofaScore** to gather public match, player, team, and competition data on-demand, allowing you to focus on analysis rather than data scraping.

Instead of writing custom browser automation or managing rotating proxy setups, you can retrieve structured results instantly using our seven pre-built modes.

> **Unofficial Actor:** This is an independent tool and is not affiliated with, authorized, or endorsed by SofaScore.

> **Looking for tennis data?** Use our companion [Tennis Scraper](https://apify.com/crawlstone/tennis-scraper) for live matches, tournaments, point-by-point data, and historical player statistics.

***

### What you can do with this Actor

We designed seven focused ways into the football data so you can run specific data-mining jobs without getting bogged down in boilerplate code. You can daisy-chain these modes together using the unique IDs returned in your datasets.

#### 1. Track live matches and odds (`liveMatches`)

Run the scraper with no configuration to get a current snapshot of matches currently in progress in the active SofaScore live football feed. Each row represents a live match with scores, match periods, red cards, and match-level 1X2 odds when available.

#### 2. Get matches by date (`matchesByDate`)

Pass a specific date (`YYYY-MM-DD`) and page number to retrieve scheduled matches. It selects a specific scheduled-competition page for that date, returning match details, status, current scores, and odds.

#### 3. Discover competition seasons (`competitionSeasons`)

Provide a unique SofaScore competition ID (like Premier League `17`) to get a flat list of all historical and current seasons with their unique season IDs, names, and years.

#### 4. Explore competition details (`competitionDetails`)

Pass a competition ID and an optional season ID to retrieve a full competition aggregate, including standings, historical/upcoming match pages, rounds, cup trees, top leaderboards, and seasonal awards.

#### 5. Inspect match anatomy (`matchDetails`)

Pass a unique match ID to extract in-depth details: available lineups (with player ratings and match stats), incidents (goals, cards, VAR, substitutions), team statistics, shot maps, and extensive odds markets.

#### 6. Deep-dive into team records (`teamDetails`)

Pass a unique team ID alongside distinct standings and statistics competition/season contexts. The Actor returns the team's squad roster (with birthdates, market values, and contract info), trophies, and competition-wide overall statistics. Standings and statistics contexts must be supplied separately.

#### 7. Retrieve player profiles (`playerDetails`)

Pass a unique player ID alongside a statistics competition and season ID. This compiles the player's profile, recent match ratings, overall season statistics, strengths and weaknesses, and career totals.

***

### ID Discovery & Chaining Workflow

To scrape detailed records for matches, competitions, teams, or players, you must provide their respective unique SofaScore IDs. This workflow outlines how you can discover and chain these IDs together in a clean data pipeline:

```text
               ┌───────────────────────┐
               │  liveMatches          │
               │  or matchesByDate     │
               └───────────┬───────────┘
                           │
        ┌──────────────────┼──────────────────┐
        ▼                  ▼                  ▼
  [  matchId  ]     [ competitionId ]    [  teamId  ]
        │                  │                  │
        ▼                  ▼                  ▼
┌───────────────┐  ┌───────────────┐  ┌───────────────┐
│ matchDetails  │  │ competition-  │  │  teamDetails  │
└───────┬───────┘  │   Seasons     │  └───────────────┘
        │          └───────┬───────┘
        ▼                  ▼
  [ playerId ]        [ seasonId ]
        │                  │
        ▼                  ▼
┌───────────────┐  ┌───────────────┐
│ playerDetails │  │ competition-  │
└───────────────┘  │   Details     │
                   └───────────────┘
```

1. **Discover Core IDs:** Run `liveMatches` or `matchesByDate` to find match event IDs (`matchId`), competition IDs (`competitionId`), and team IDs (`teamId`).
2. **Resolve Season IDs:** Run `competitionSeasons` using your chosen `competitionId` to resolve the available season IDs. Note that `teamDetails` and `playerDetails` require you to explicitly supply these standings and statistics contexts as separate inputs.
3. **Discover Player IDs:** Inspect available lineups inside `matchDetails` or leaderboard stats in `competitionDetails` to extract unique player IDs (`playerId`).
4. **Run Detail Aggregates:** Feed these IDs into `matchDetails`, `teamDetails` (providing both standings and statistics contexts), or `playerDetails` for high-resolution profiles.

***

### Quick Start

1. Click **Try for free** on the Actor page.
2. Under **Scraper mode**, choose **Live matches** or your desired mode.
3. Click **Start**.
4. Open the **Dataset** tab when the run finishes.

For your first run, you can use the default live match mode with no extra input:

```json
{
  "mode": "liveMatches"
}
```

If no matches are live when you run the Actor, the run succeeds with an empty dataset.

#### Other Typical Inputs

Retrieve scheduled matches for a specific date (returns one scheduled-competition page):

```json
{
  "mode": "matchesByDate",
  "date": "2026-07-27",
  "page": 1
}
```

Deep-dive into team records (requires separate standings and statistics contexts):

```json
{
  "mode": "teamDetails",
  "teamId": 42,
  "standingsCompetitionId": 17,
  "standingsSeasonId": 76986,
  "statsCompetitionId": 17,
  "statsSeasonId": 76986
}
```

***

### Data Structure & Examples

Each dataset row represents a single football record. The Apify Dataset stores nested arrays and objects, and JSON exports preserve this rich hierarchical structure. (Tabular exports like CSV or Excel will flatten or serialize these fields).

*Note: Odds and optional detail resources (such as lineup stats, shotmaps, or V2 momentum charts) may be unavailable depending on the match status or coverage.*

#### Live Match Snippet (`liveMatches`)

*This is an abridged preview of selected fields, not a complete Dataset row.*

```json
{
  "id": 14025099,
  "slug": "arsenal-chelsea",
  "status": "inprogress",
  "currentPeriod": "period1",
  "tournamentName": "Premier League",
  "homeTeamName": "Arsenal",
  "awayTeamName": "Chelsea",
  "score": {
    "home": 1,
    "away": 0,
    "periods": [
      { "period": "period1", "home": 1, "away": 0 }
    ]
  },
  "odds": {
    "home": { "decimal": 1.85, "fractional": "17/20" },
    "draw": { "decimal": 3.6, "fractional": "13/5" },
    "away": { "decimal": 4.2, "fractional": "16/5" }
  }
}
```

#### Match Details Snippet (`matchDetails`)

*This is an abridged preview of selected fields, demonstrating the rich nested statistics returned.*

```json
{
  "id": 14025099,
  "slug": "arsenal-chelsea",
  "status": "finished",
  "homeTeamName": "Arsenal",
  "awayTeamName": "Chelsea",
  "score": { "home": 2, "away": 1 },
  "venueName": "Emirates Stadium",
  "refereeName": "Michael Oliver",
  "playerOfTheMatchName": "Bukayo Saka",
  "playerOfTheMatchRating": 8.7,
  "incidents": [
    { "incidentType": "goal", "time": 15, "playerName": "Bukayo Saka", "assistName": "Martin Ødegaard" }
  ],
  "homeLineupPlayers": [
    {
      "id": 934235,
      "name": "Bukayo Saka",
      "position": "M",
      "rating": 8.7,
      "substitute": false,
      "statistics": { "goals": 1, "assists": 1, "totalShots": 3, "keyPasses": 4 }
    }
  ],
  "statistics": [
    {
      "period": "ALL",
      "groups": [
        {
          "name": "Shots",
          "items": [
            { "name": "Total shots", "home": "14", "away": "8", "homeValue": 14, "awayValue": 8 }
          ]
        }
      ]
    }
  ]
}
```

***

### Operational & Billing Details

#### Managed Proxies

To handle rate limits and source blocks, SofaScore requests on Apify are automatically routed through residential proxies. No user-side proxy configuration or credentials are required. Note that while this helps protect runs from immediate blocking, it does not guarantee uninterrupted source availability.

#### Pay-per-Event Billing

We utilize Apify's Pay Per Event (PPE) model, which charges you based on successful operations rather than compute time or row counts:

- **One Successful Result Event:** A successful run charges exactly one custom `successful-result` event, regardless of how many rows are returned.
- **Uncharged Scrape Failures:** If a scraping operation terminates due to an unrecoverable source error or IP block, a terminal scrape failure is recorded. When possible, the Actor writes a diagnostic error row containing the failure details to help you troubleshoot. These terminal scrape failures do not charge the `successful-result` event.
- **Empty Successes:** If a run returns zero results under a valid query (for example, if no matches are live or a valid competition response contains no season rows), it is considered a valid successful operation and charges one `successful-result` event. Note that invalid parameters or incorrect IDs may trigger a run failure rather than an empty success.

Check the Actor's **Pricing** tab for current rates.

***

### Use with Apify MCP

If you are integrating football data into AI workflows, you can run this Actor through Apify's hosted Model Context Protocol (MCP) server to connect directly to compatible AI clients (such as Claude Desktop):

```text
https://mcp.apify.com?tools=crawlstone/sofascore-football-scraper
```

Once connected, you can query match details, live scores, team lineups, standings, and player statistics using natural language through your AI assistant.

***

### Frequently Asked Questions

#### What should I do when a run returns zero rows?

This is normal. The scraper returns empty datasets when there are no live matches in progress (e.g., late at night between matchdays) or when a valid competition query returns zero season rows. If you need regular updates, configure an Apify Schedule to run the Actor periodically.

#### How do I fetch team details if they require standings and statistics contexts?

To run `teamDetails`, you must supply distinct standings and statistics contexts (such as `standingsCompetitionId` and `statsCompetitionId`, alongside their respective season IDs). You can find the available season IDs for your chosen competition by running `competitionSeasons` first. Note that each Actor run executes exactly one selected mode at a time.

#### Can I get continuous real-time updates?

No. This Actor is designed for static, on-demand Dataset snapshots. If you need regular snapshots of active match events, configure an Apify Schedule to run the Actor at set intervals.

***

### Support

If you need assistance, please open a ticket on this Actor's **Discussion** tab and include:

- Your Apify **Run ID**.
- The selected **Mode** and the **Input** values you provided.
- A description of what you expected versus what occurred.

Do not share your Apify API Token or other private credentials in support tickets.

# Actor input Schema

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

Select the operation for this run. The form preselects liveMatches. Fields that belong to another mode are ignored by the runtime.

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

Required only for matchesByDate. Enter a real calendar date in YYYY-MM-DD format.

## `page` (type: `integer`):

Used only for matchesByDate. Selects one scheduled-competition page.

## `competitionId` (type: `integer`):

Required for competitionSeasons and competitionDetails. This must be a SofaScore unique-tournament ID, not a concrete tournament or stage ID.

## `seasonId` (type: `integer`):

Optional for competitionDetails. Omit it to use the first season returned by SofaScore.

## `matchId` (type: `integer`):

Required only for matchDetails. Use a positive SofaScore event ID.

## `teamId` (type: `integer`):

Required only for teamDetails. Use a positive SofaScore team ID.

## `playerId` (type: `integer`):

Required only for playerDetails. Use a positive SofaScore player ID.

## `standingsCompetitionId` (type: `integer`):

Required only for teamDetails. This is a SofaScore unique-tournament ID. Every matching concrete tournament instance for the selected season is returned.

## `standingsSeasonId` (type: `integer`):

Required only for teamDetails. Selects the season used with standingsCompetitionId.

## `statsCompetitionId` (type: `integer`):

Required for teamDetails and playerDetails. This must be a SofaScore unique-tournament ID.

## `statsSeasonId` (type: `integer`):

Required for teamDetails and playerDetails. Selects the season for statistics and analytics.

## `historicalMatchesPage` (type: `integer`):

Used for competitionDetails and teamDetails. Selects one historical-match page.

## `upcomingMatchesPage` (type: `integer`):

Used for competitionDetails and teamDetails. Selects one upcoming-match page.

## `matchesPage` (type: `integer`):

Used only for playerDetails. Selects one recent-match page.

## Actor input object example

```json
{
  "mode": "liveMatches",
  "date": "2026-07-27",
  "page": 1,
  "competitionId": 17,
  "seasonId": 76986,
  "matchId": 14025099,
  "teamId": 42,
  "playerId": 12994,
  "standingsCompetitionId": 242,
  "standingsSeasonId": 69243,
  "statsCompetitionId": 17,
  "statsSeasonId": 76986,
  "historicalMatchesPage": 1,
  "upcomingMatchesPage": 1,
  "matchesPage": 1
}
```

# Actor output Schema

## `results` (type: `string`):

Live matches and competition seasons produce zero or more direct rows. Matches by date produces one page envelope. Competition, match, team, and player detail modes produce one aggregate row. A terminal scrape failure may produce one generic error row.

# 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": "liveMatches"
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlstone/sofascore-football-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": "liveMatches" }

# Run the Actor and wait for it to finish
run = client.actor("crawlstone/sofascore-football-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": "liveMatches"
}' |
apify call crawlstone/sofascore-football-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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