# SofaScore Scraper - Live Scores, Stats, Lineups & Odds (`uber_byte/sofascore-scraper`) Actor

SofaScore sports data: fixtures & results by date, live scores, match stats, lineups, incidents, betting odds, league standings. Football, tennis, NBA, NHL

- **URL**: https://apify.com/uber_byte/sofascore-scraper.md
- **Developed by:** [Marlon Lee](https://apify.com/uber_byte) (community)
- **Stats:** 3 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 matches

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## SofaScore Scraper

Get SofaScore data as clean JSON: fixtures and results for any day, live scores, match statistics with xG, lineups with player ratings, goals and cards, betting odds, league standings and team or player search. Built for betting models, fantasy tools, sports sites and bots that need a SofaScore API without scraping pages by hand.

It covers football (soccer), tennis, basketball, ice hockey, baseball, American football, handball, volleyball, cricket, esports and the other sports SofaScore lists. The Actor reads SofaScore's public JSON API, so you don't need a browser or a login.

### What you get

Pick one of five modes:

| Mode | Input | Output (`itemType`) |
|---|---|---|
| **Matches by date** | sports + date (UTC), optional tournament filter | one `match` per fixture or result |
| **Live matches** | sports, optional tournament filter | one `match` per game in progress |
| **Match details** | SofaScore match IDs or URLs | one `match-details` with stats, lineups, incidents and odds |
| **Standings** | tournament IDs, optional season ID | one `standings` row per team |
| **Search** | text query | one `search-result` per team, player, tournament, manager and so on |

- A `match` has teams, scores by period, status, start time, tournament, season, round and a SofaScore link.
- A `match-details` item adds venue, referee, team statistics per period (possession, xG, shots and more), lineups with formation, player ratings and minutes, missing players, incidents (goals, assists, cards, substitutions) and odds with fractional and decimal prices and their movement.
- A `standings` row has position, matches, wins, draws, losses, goals, points and the promotion zone.

Turn on **Include full match details** in the date or live modes to get `match-details` for every match in one run.

### Use cases

- **Betting models and prediction bots.** Pull xG, shots, possession and player ratings for every match in a league.
- **Fixture and result feeds.** Power a sports site, a Telegram or Discord bot, or a newsletter with each day's matches.
- **Live score monitoring.** Schedule a live-mode run every few minutes.
- **Odds snapshots.** Record pre-match and live odds, such as 1X2, both teams to score and over/under, with the opening price for comparison.
- **League tables.** Feed standings into dashboards and spreadsheets.
- **ID lookup.** Find SofaScore IDs for teams, players and tournaments.

### How to use

1. Open the Actor in the Apify Console and click **Try for free**.
2. Choose **What to scrape**.
3. Fill in the matching input: **Sports** and **Date (UTC)**, **Match IDs or URLs**, **Tournament IDs or URLs**, or a **Search query**.
4. Set **Max items**, and tick **Include full match details** if you want stats, lineups and odds for date or live matches.
5. Click **Start** and download the results as JSON, CSV or Excel.

Useful tournament IDs: 17 Premier League, 8 LaLiga, 23 Serie A, 35 Bundesliga, 34 Ligue 1, 7 Champions League, 679 Europa League, 132 NBA, 234 NHL. Search mode finds any other ID, and it's also the last number in a SofaScore tournament URL.

### Input example

Premier League matches on a given day:

```json
{ "mode": "scheduled", "sports": ["football"], "date": "2026-09-27", "tournamentIds": ["17"] }
```

All tennis and basketball games today (the date defaults to today, UTC):

```json
{ "mode": "scheduled", "sports": ["tennis", "basketball"], "maxItems": 1000 }
```

Everything live in ice hockey, with full details:

```json
{ "mode": "live", "sports": ["ice-hockey"], "includeDetails": true }
```

Match details from a URL:

```json
{ "mode": "details", "eventIds": ["https://www.sofascore.com/football/match/czechia-england/nUbsoUb#id:15534092"] }
```

Premier League and LaLiga tables for the current season:

```json
{ "mode": "standings", "tournamentIds": ["17", "8"] }
```

### Output example

Real items from a run on 29 Sep 2026 (trimmed).

`match`:

```json
{
  "itemType": "match",
  "id": 15534092,
  "url": "https://www.sofascore.com/football/match/czechia-england/nUbsoUb#id:15534092",
  "sport": "football",
  "country": "Europe",
  "tournament": "UEFA Nations League, League A, Gr. 3",
  "uniqueTournamentId": 10783,
  "uniqueTournament": "UEFA Nations League",
  "seasonId": 89945,
  "season": "UEFA Nations League 26/27",
  "round": 2,
  "startTime": "2026-09-29T18:45:00.000Z",
  "status": "2nd half",
  "statusType": "inprogress",
  "homeTeam": { "id": 4714, "name": "Czechia", "shortName": "Czechia", "nameCode": "CZE", "country": "Czechia" },
  "awayTeam": { "id": 4713, "name": "England", "shortName": "England", "nameCode": "ENG", "country": "England" },
  "homeScore": { "current": 0, "periods": { "period1": 0, "period2": 0 } },
  "awayScore": { "current": 1, "periods": { "period1": 0, "period2": 1 } },
  "winnerCode": null,
  "venue": null,
  "referee": null,
  "hasXg": true
}
```

`match-details` adds venue, referee and:

```json
{
  "venue": { "name": "Fortuna Arena", "city": "Prague", "capacity": 19370 },
  "referee": "Halil Umut Meler",
  "statistics": {
    "ALL": {
      "ballPossession": { "name": "Ball possession", "group": "Match overview", "home": 29, "away": 71 },
      "expectedGoals": { "name": "Expected goals", "group": "Shots", "home": 0.24, "away": 0.83 },
      "totalShotsOnGoal": { "name": "Total shots", "group": "Shots", "home": 4, "away": 11 }
    },
    "1ST": { "...": "..." },
    "2ND": { "...": "..." }
  },
  "lineups": {
    "confirmed": true,
    "home": {
      "formation": "4-2-3-1",
      "players": [{ "id": 927366, "name": "Matěj Kovář", "position": "G", "shirtNumber": 1, "substitute": false, "captain": false, "rating": 6.4, "minutesPlayed": 56 }],
      "missingPlayers": [{ "id": 963084, "name": "David Zima", "reason": "Unknown" }]
    },
    "away": { "...": "..." }
  },
  "incidents": [
    { "type": "goal", "class": "regular", "minute": 47, "addedTime": null, "isHome": false, "player": "Anthony Gordon", "assist": "Trent Alexander-Arnold", "playerIn": null, "playerOut": null, "reason": null, "text": null, "homeScore": 0, "awayScore": 1 }
  ],
  "odds": [
    {
      "market": "Full time", "group": "1X2", "period": "Full-time", "line": null, "isLive": false, "suspended": false,
      "choices": [
        { "name": "1", "fractional": "17/2", "decimal": 9.5, "initialDecimal": 5.75, "change": 1 },
        { "name": "X", "fractional": "9/2", "decimal": 5.5, "initialDecimal": 4.33, "change": 1 },
        { "name": "2", "fractional": "3/10", "decimal": 1.3, "initialDecimal": 1.45, "change": -1 }
      ]
    }
  ]
}
```

`standings`:

```json
{
  "itemType": "standings", "seasonId": 96668, "tournament": "Premier League", "uniqueTournamentId": 17,
  "table": "Premier League 26/27", "type": "total", "position": 1, "teamId": 17, "team": "Manchester City",
  "matches": 5, "wins": 5, "draws": 0, "losses": 0, "scoresFor": 13, "scoresAgainst": 5, "scoreDiff": "+8",
  "points": 15, "promotion": "Champions League", "updatedAt": "2026-09-20T17:19:43.000Z"
}
```

`search-result`:

```json
{ "itemType": "search-result", "query": "real madrid", "type": "team", "id": 2829, "name": "Real Madrid", "sport": "football", "country": "Spain", "team": null, "position": null, "url": "https://www.sofascore.com/football/team/real-madrid/2829" }
```

Problems such as an unknown match ID, a cup with no table or a blocked request come back as `itemType: "error"` items.

### Pricing

This Actor charges per result: you pay for each `match`, `match-details`, `standings` row and `search-result` saved to the dataset. Error items are free. Cap the cost with **Max items** or a maximum cost per run in the Apify Console; the Actor stops cleanly when it reaches either.

### FAQ

**Is it legal to scrape SofaScore?**
The Actor reads public sports data that SofaScore shows to any visitor without an account, and no personal data beyond player and referee names. Check SofaScore's terms for your use case, especially for commercial redistribution.

**Why a residential proxy by default?**
SofaScore often blocks datacenter IP ranges. You can switch to datacenter proxy to save cost. If you then see `HTTP 403` error items, switch back to residential.

**Which sports are supported?**
Any sport slug SofaScore uses: `football`, `tennis`, `basketball`, `ice-hockey`, `baseball`, `american-football`, `handball`, `volleyball`, `cricket`, `rugby`, `esports`, `table-tennis`, `mma`, `futsal`, `darts`, `snooker` and more. The depth of statistics, lineups and odds depends on the sport and league.

**What timezone is the date in?**
UTC. A match at 00:30 in Sydney may belong to the previous UTC day.

**How do I get odds for all of today's matches?**
Use **Matches by date** with **Include full match details** on. Each match takes 5 API requests, so add a tournament filter for faster runs.

**Can I get historical results?**
Yes. Pick a past date in **Matches by date**, or a past **Season ID** in **Standings**.

**What are the limits?**

- Odds are the odds SofaScore displays, converted from fractional to decimal. They are not a multi-bookmaker comparison.
- Standings return the total table only, without home and away splits. Knockout-only competitions have no table.
- Player season statistics, heatmaps, shot maps and head-to-head history are not included.
- **Matches by date** sends one request per country or category with matches that day, about 100 for football. Use the tournament filter for quick runs.
- The Actor relies on SofaScore's unofficial public API, which SofaScore can change without notice.

# Actor input Schema

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

What to scrape.

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

SofaScore sport slugs for 'Matches by date' and 'Live' modes, e.g. football, tennis, basketball, ice-hockey, baseball, american-football, handball, volleyball, cricket, rugby, esports, table-tennis, mma.

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

Day to list matches for, YYYY-MM-DD, in UTC. Defaults to today.

## `tournamentIds` (type: `array`):

SofaScore unique tournament IDs (e.g. 17 = Premier League, 8 = LaLiga, 7 = Champions League, 132 = NBA) or tournament URLs. Required for 'Standings'. In 'Matches by date' and 'Live' modes it filters to these tournaments (and makes runs much faster).

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

Optional. Leave empty for the current season.

## `eventIds` (type: `array`):

For 'Match details' mode: SofaScore event IDs (e.g. 15534092) or match URLs ending in #id:15534092.

## `searchQuery` (type: `string`):

For 'Search' mode: team, player or tournament name.

## `includeDetails` (type: `boolean`):

In 'Matches by date' and 'Live' modes, fetch stats, lineups, incidents and odds for every match (5 requests per match, billed as match-details).

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

Maximum number of results to return. See the README for whether this applies per search or to the whole run.

## `proxyConfiguration` (type: `object`):

SofaScore often blocks datacenter IPs, so residential proxy is the default.

## Actor input object example

```json
{
  "mode": "scheduled",
  "sports": [
    "football"
  ],
  "includeDetails": false,
  "maxItems": 200,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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": "scheduled",
    "sports": [
        "football"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("uber_byte/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": "scheduled",
    "sports": ["football"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).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": "scheduled",
  "sports": [
    "football"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call uber_byte/sofascore-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,uber_byte/sofascore-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

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