# Sofascore Live Scores & Fixtures Scraper (`teodor_banea/sofascore-live-scores-fixtures-scraper`) Actor

Scrape live scores, fixtures, and results from Sofascore across 21 sports — football, tennis, basketball, and more. Get period scores, tennis points, live match minutes, winners, seeds, and optional betting odds in clean JSON. Filter by tournament, pick any date, and export or automate via API.

- **URL**: https://apify.com/teodor\_banea/sofascore-live-scores-fixtures-scraper.md
- **Developed by:** [Banea Teodor](https://apify.com/teodor_banea) (community)
- **Categories:**
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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 Live Scores & Fixtures Scraper

### What does Sofascore Live Scores & Fixtures Scraper do?

This Actor extracts live scores, fixtures, and final results from **[Sofascore](https://www.sofascore.com)** — one of the world's largest sports data platforms — across **21 sports**: football, tennis, basketball, ice hockey, cricket, esports, MMA, and more. One run returns everything currently in play, or a full day's card of scheduled, live, and finished matches, as clean normalized JSON: period-by-period scores, tennis set/game/point states, live match minutes, tournament context, and optionally live betting odds.

It talks to Sofascore's JSON API directly — no browser, no screenshots — so runs finish in seconds and cost cents.

### Why use this Actor?

- **Every sport, one schema** — a tennis match, a football game, and an NBA game come back with identical field sets. Build one pipeline, cover 21 sports.
- **Real live detail** — in-play tennis returns sets, games, and the current point ("40"–"15"); football returns the live match minute and per-half scores; finished matches carry the winner.
- **Fixtures and results by date** — any past date returns final results, any future date returns the schedule. Sofascore's own priority ordering puts top competitions (Champions League, ATP, NBA) first.
- **Live betting odds included** — optionally attach the featured "Full time" market: opening and current decimal odds for home/draw/away.
- **Fast, filtered runs** — the tournament filter ("Premier League", "ATP", "NBA", or a country) skips non-matching competitions *before* fetching them, so filtered runs are cheaper and faster.
- **Built for pipelines** — every row always has every field (null when a sport doesn't have it), ISO 8601 dates, numeric scores, absolute URLs.

### How much does it cost?

You pay per event returned. Scraping all live football right now (~25–80 events) costs about a cent; a full day of top-flight fixtures with `maxEvents: 200` finishes in under a minute. Use `maxEvents` to put a hard ceiling on any run — unlimited runs without a tournament filter are automatically capped at 10,000 events. Turning on `includeOdds` adds one request per event, which makes runs slower but not more expensive per result.

### Input

| Field | Type | Description | Example |
|---|---|---|---|
| `mode` | string | `live` (everything in play now, default) or `scheduled` (a day's fixtures and results). | `"live"` |
| `sports` | array | Sports to scrape. The result cap is split evenly between them. | `["football", "tennis"]` |
| `date` | date | Day to scrape in scheduled mode (default: today). Past = results, future = schedule. | `"2026-08-27"` |
| `tournamentFilter` | string | Only competitions whose tournament, category, or country name contains this text. | `"Champions League"` |
| `includeOdds` | boolean | Attach the featured "Full time" betting market (decimal odds, opening + current). | `false` |
| `maxEvents` | integer | Hard cap on returned events (= billed results). | `200` |

An **empty input works**: it returns live football.

### Output

One row per match:

```json
{
    "eventId": 14025044,
    "sport": "football",
    "url": "https://www.sofascore.com/football/match/aek-athens-levski-sofia/QobsRgb#id:14025044",
    "tournamentName": "UEFA Champions League, Playoff Round",
    "uniqueTournamentId": 7,
    "uniqueTournamentName": "UEFA Champions League",
    "categoryName": "Europe",
    "countryName": null,
    "seasonName": "UEFA Champions League 26/27",
    "round": 636,
    "roundName": "Playoff round",
    "statusType": "finished",
    "statusDescription": "Ended",
    "startTime": "2026-08-26T18:00:00.000Z",
    "liveMinute": null,
    "winner": "home",
    "homeTeamId": 2687,
    "homeTeamName": "AEK Athens",
    "homeTeamCountry": "Greece",
    "homeTeamSeed": null,
    "awayTeamId": 2342,
    "awayTeamName": "Levski Sofia",
    "awayTeamCountry": "Bulgaria",
    "awayTeamSeed": null,
    "homeScore": 4,
    "awayScore": 0,
    "homeScoreDisplay": 4,
    "awayScoreDisplay": 0,
    "homePeriodScores": [3, 1],
    "awayPeriodScores": [0, 0],
    "homeScorePenalties": null,
    "awayScorePenalties": null,
    "homePoint": null,
    "awayPoint": null,
    "groundType": null,
    "firstToServe": null,
    "oddsMarketName": "Full time",
    "homeOdds": 1.5,
    "drawOdds": 3.75,
    "awayOdds": 6.0,
    "homeOddsInitial": 1.44,
    "drawOddsInitial": 4.0,
    "awayOddsInitial": 6.5,
    "oddsSuspended": false,
    "scrapedAt": "2026-08-27T14:30:00.000Z",
    "runId": "AbC123..."
}
```

Field notes:

- **Period scores are per period**: football halves (`[3, 1]` = 3 first-half goals, 1 second-half), basketball quarters, tennis games per set.
- **Tennis rows** fill `homePoint`/`awayPoint` (current game), `groundType` (surface), `firstToServe`, and seeds; `homeScore` counts sets won.
- **`liveMinute`** is the current match minute for clock sports in play, computed the way Sofascore's own clock works.
- **`winner`** is `"home"`, `"away"`, or `"draw"` once decided.
- **Odds** are decimal (converted from Sofascore's fractional values); `drawOdds` is null on two-way markets like tennis. Events without a market keep null odds rather than being dropped.
- Fields a sport doesn't have are `null`, never omitted — the shape is identical on every row.

### Tips and tricks

- **Live scores dashboard**: schedule the Actor every few minutes with `mode: "live"` and your sports — `eventId` is stable, so downstream you can upsert by it.
- **Results backfill**: loop `mode: "scheduled"` over past dates to build a historical results dataset with final scores and winners.
- **One competition only**: `tournamentFilter: "Premier League"` (or `"ATP"`, `"NBA"`, `"Wimbledon"`, a country name) — filtered tournaments are skipped before fetching, so this is also the cheapest way to run.
- **Odds movement tracking**: run with `includeOdds` on a schedule and diff `homeOdds` against `homeOddsInitial` by `eventId`.
- **Multi-sport runs** split `maxEvents` evenly across the selected sports, so one busy sport can't crowd out the others.

### Integrations

The dataset works with every Apify integration: export to **JSON, CSV, Excel**, push to **Google Sheets**, trigger **webhooks** on finish, or query via the **Apify API** from Python/Node. Typical setups: a scheduled live-scores feed into a Slack webhook, or the [Apify API](https://docs.apify.com/api/v2) pulling each day's results into a stats model.

# Actor input Schema

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

Choose "Live now" for everything currently in play, or "Fixtures & results by date" for a day's full card (scheduled, in-play, and finished with scores).

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

Select one or more sports to scrape.

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

The day to scrape in "Fixtures & results by date" mode. Defaults to today. Past dates return final results, future dates return the schedule.

## `tournamentFilter` (type: `string`):

Only include competitions whose tournament, category, or country name contains this text (case-insensitive) — e.g. "Premier League", "ATP", "NBA", "Romania". In date mode this also skips fetching non-matching tournaments, making runs faster and cheaper.

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

Also fetch the featured "Full time" market (home/draw/away, decimal odds, opening and current) for every event. Costs one extra request per event, so large runs take proportionally longer.

## `maxEvents` (type: `integer`):

Cap on how many events are returned in total. Set to 0 for unlimited — unlimited runs without a tournament filter are capped at 10,000 to protect against surprise bills.

## `maxConcurrency` (type: `integer`):

How many requests run in parallel. The default is safe; lower it if you see rate-limit errors.

## `maxRequestsPerMinute` (type: `integer`):

Throttle the overall request rate.

## Actor input object example

```json
{
  "mode": "live",
  "sports": [
    "football",
    "tennis"
  ],
  "includeOdds": false,
  "maxEvents": 50,
  "maxConcurrency": 5,
  "maxRequestsPerMinute": 120
}
```

# Actor output Schema

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

Matches with live or final scores, period breakdowns, competition context, and optional featured betting odds.

# 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 = {
    "sports": [
        "football",
        "tennis"
    ],
    "maxEvents": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("teodor_banea/sofascore-live-scores-fixtures-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 = {
    "sports": [
        "football",
        "tennis",
    ],
    "maxEvents": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("teodor_banea/sofascore-live-scores-fixtures-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 '{
  "sports": [
    "football",
    "tennis"
  ],
  "maxEvents": 50
}' |
apify call teodor_banea/sofascore-live-scores-fixtures-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,teodor_banea/sofascore-live-scores-fixtures-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/5oBhTm64EHD6zbqeH/builds/vnOM081KreFPo3g9x/openapi.json
