# Flashscore Scraper – Football, Tennis & Basketball Live Scores (`openharvest/flashscore-scraper`) Actor

Flashscore scraper for live scores, fixtures and results in football, tennis, basketball, ice hockey and 25+ other sports. Period and set scores, match statistics, goals, cards and incidents. Fast, no browser, pay only per match.

- **URL**: https://apify.com/openharvest/flashscore-scraper.md
- **Developed by:** [Enes Bulanık](https://apify.com/openharvest) (community)
- **Categories:** Sports, Automation, Developer tools
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 match scrapeds

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

## Flashscore Scraper – Football, Tennis & Basketball Live Scores

Flashscore scraper for live scores, fixtures and results in football, tennis, basketball, ice hockey and 25+ other sports. Period and set scores, match statistics, goals, cards and incidents. Fast, no browser, pay only per match.

One run can return thousands of matches from any day in the last week or the next week. Export to JSON, CSV, Excel, or connect via API, webhooks, Make, Zapier or n8n.

### What can this Flashscore scraper do?

- ⚽ **Football / soccer scores** – every league Flashscore covers (Premier League, LaLiga, Serie A, Bundesliga, Ligue 1, Champions League, MLS, Brasileirão, Süper Lig and thousands of lower leagues).
- 🎾 **Tennis results** – ATP, WTA, Challenger, ITF; set scores and tiebreak points.
- 🏀 **Basketball scores** – NBA, EuroLeague, NCAA and more, with quarter scores.
- 🏒 **Ice hockey** – NHL, KHL, AHL, with period, overtime and shoot-out scores.
- 🏈⚾🤾🏐🏏🎯🎮 American football, baseball, handball, volleyball, cricket, darts, eSports, table tennis, rugby, futsal, snooker and more.
- 📅 **Fixtures** (up to 7 days ahead), **results** (up to 7 days back) and **live matches** right now.
- 📊 **Match details** (optional): statistics per half/set, incidents (goals with assists, cards, substitutions, penalties), referee, stadium, attendance.
- 🔎 Filters by **tournament/country**, **team/player**, and **status** (scheduled, live, finished…).
- ⚡ Fast & cheap: uses Flashscore's lightweight data feed, no headless browser. 5,000 matches in ~15 seconds.

### Use cases

- **Betting models & sports trading** – collect historical results, xG and stats to train and backtest prediction models; poll live scores for in-play strategies.
- **Sports analytics & research** – build datasets of results, period scores and team statistics across leagues.
- **Apps, websites & bots** – power livescore widgets, Telegram/Discord bots, fantasy apps and newsletters with fixtures and results.
- **Media & content** – auto-generate match reports, daily result round-ups and fixture lists.
- **Monitoring** – schedule the Actor every few minutes and get notified when your team scores.

### How to use

1. Click **Try for free** / **Start**.
2. Select one or more **sports**.
3. Choose the **day range** (0 = today, -1 = yesterday, 1 = tomorrow; -7…+7).
4. Optionally filter by tournament (e.g. `Premier League, LaLiga`), team (e.g. `Real Madrid`) or status, or tick **Only live matches**.
5. Tick **Include match details** if you need statistics and incidents.
6. Run and download your data as JSON, CSV, Excel or HTML.

### Input

| Field | Type | Description |
|---|---|---|
| `sports` | array | Sports to scrape, e.g. `["football", "tennis"]`. Default `["football"]`. |
| `dayOffsetFrom` | integer | First day relative to today (-7…7). Default `0` (today). |
| `dayOffsetTo` | integer | Last day relative to today (-7…7). Defaults to `dayOffsetFrom`. |
| `onlyLive` | boolean | Only matches in progress right now. |
| `statusFilter` | array | `scheduled`, `live`, `finished`, `postponed`, `cancelled`, `abandoned`, `interrupted`. |
| `tournamentFilter` | string | Comma-separated substrings matched against tournament/country, e.g. `ENGLAND: Premier League, Champions League`. |
| `teamFilter` | string | Comma-separated substrings matched against home/away team or player. |
| `includeMatchDetails` | boolean | Add statistics, incidents and match info (extra charge per match). |
| `maxItems` | integer | Max matches to save (0 = unlimited). Default `50`. |
| `timezoneOffset` | integer | Hours from UTC that define the "day" boundaries. Default `0` (UTC). |
| `proxyConfiguration` | object | Optional proxy. Not needed in normal use. |

Example – all of last week's finished Premier League and LaLiga matches with stats:

```json
{
    "sports": ["football"],
    "dayOffsetFrom": -7,
    "dayOffsetTo": -1,
    "statusFilter": ["finished"],
    "tournamentFilter": "ENGLAND: Premier League, SPAIN: LaLiga",
    "includeMatchDetails": true,
    "maxItems": 0
}
```

### Output

Each match is one dataset item. Real example (shortened – `statistics` contains ~100 rows for this match):

```json
{
    "matchId": "j944GznD",
    "url": "https://www.flashscore.com/match/j944GznD/",
    "sport": "Football",
    "sportSlug": "football",
    "country": "Brazil",
    "category": "Brazil",
    "tournament": "Serie B",
    "tournamentFullName": "BRAZIL: Serie B",
    "tournamentUrl": "https://www.flashscore.com/football/brazil/serie-b/",
    "tournamentId": "lOEwe4o4",
    "startTime": "2026-10-06T22:30:00.000Z",
    "startTimestamp": 1791325800,
    "status": "finished",
    "statusDetail": "Finished",
    "statusCode": 3,
    "homeTeam": "Sport Recife",
    "awayTeam": "Sao Bernardo",
    "homeTeamId": "KIBeGAFO",
    "awayTeamId": "Wp4nyhLR",
    "homeScore": 2,
    "awayScore": 1,
    "regularTimeHomeScore": 2,
    "regularTimeAwayScore": 1,
    "penaltiesHomeScore": null,
    "penaltiesAwayScore": null,
    "periodScores": [
        { "period": 1, "name": "1st Half", "home": 1, "away": 0 },
        { "period": 2, "name": "2nd Half", "home": 1, "away": 1 }
    ],
    "winner": "home",
    "homeLogo": "https://static.flashscore.com/res/image/data/WrU0J0Qq-fezSJdFa.png",
    "awayLogo": "https://static.flashscore.com/res/image/data/plaFSegT-AP3c0ay7.png",
    "lastUpdated": "2026-10-07T00:27:46.000Z",
    "details": {
        "periodScores": [
            { "period": "1st Half", "home": 1, "away": 0 },
            { "period": "2nd Half", "home": 1, "away": 1 }
        ],
        "incidents": [
            {
                "period": "1st Half", "time": "17'", "team": "home", "type": "Goal", "typeCode": 3,
                "player": "Neto Pessoa", "playerId": "hAC6Qegp", "score": "1-0",
                "related": [{ "type": "Assistance", "player": "Chrystian Barletta", "playerId": "2agS5CnN" }]
            },
            {
                "period": "2nd Half", "time": "59'", "team": "home", "type": "Substitution - Out", "typeCode": 6,
                "player": "Juan Alano", "playerId": "2gTENNBg",
                "related": [{ "type": "Substitution - In", "player": "Andrade K.", "playerId": "ABBFeKO2" }]
            },
            {
                "period": "2nd Half", "time": "86'", "team": "home", "type": "Goal", "typeCode": 3,
                "player": "Patrick de Paula", "playerId": "KQpVDN6N", "score": "2-1"
            }
        ],
        "statistics": [
            { "period": "Match", "group": "Top stats", "name": "Ball possession", "home": "48%", "away": "52%" },
            { "period": "Match", "group": "Shots", "name": "Expected goals (xG)", "home": "1.63", "away": "1.99" },
            { "period": "Match", "group": "Shots", "name": "Total shots", "home": "19", "away": "20" },
            { "period": "Match", "group": "Attack", "name": "Corner kicks", "home": "5", "away": "9" },
            { "period": "Match", "group": "Passes", "name": "Passes", "home": "86% (382/444)", "away": "89% (414/466)" }
        ],
        "matchInfo": {
            "referee": "Junior R.",
            "refereeCountry": "Bra",
            "venue": "Estadio Adelmar da Costa Carvalho",
            "city": "Recife",
            "attendance": "18 258",
            "capacity": "26 418"
        }
    },
    "scrapedAt": "2026-10-07T18:06:48.547Z"
}
```

#### Field notes

- `status` – `scheduled`, `live`, `finished`, `postponed`, `cancelled`, `abandoned`, `interrupted`. `statusDetail` gives the exact stage (`1st Half`, `Half Time`, `Set 3`, `After Extra Time`, `After Penalties`, `Walkover`, …).
- `homeScore`/`awayScore` – the score as shown on Flashscore. Football after penalties shows the score after extra time (e.g. `0-0`) and the shoot-out in `penaltiesHomeScore/AwayScore`. In ice hockey and handball the shoot-out winner gets +1 goal, exactly like Flashscore displays it.
- Tennis/volleyball/darts/eSports: `homeScore`/`awayScore` are sets (or maps/legs); `periodScores` contain games per set and `homeTiebreak`/`awayTiebreak` where played.
- `regularTimeHomeScore/AwayScore` – score after regular time (before overtime/extra time).
- `country` is empty for international categories without a country (e.g. ATP tennis); `category` always contains the group name (e.g. `ATP - Singles`).
- All times are UTC ISO 8601.

### Pricing

This Actor uses **pay-per-event** pricing – you only pay for the data you get:

| Event | Price |
|---|---|
| Match scraped (`match`) | **$0.001** per match ($1 per 1,000 matches) |
| Match details (`match-details`) | **$0.003** per match with details enabled |

Examples: today's 50 football matches ≈ **$0.05**. A full week of football results (~2,000 matches) ≈ **$2**. 100 matches with statistics and incidents ≈ **$0.40**. Platform usage is minimal because no browser is used.

You can set a **maximum cost per run** in the run options – the Actor stops cleanly when it is reached.

### FAQ

**Is it legal to scrape Flashscore?**
This Actor only collects publicly available sports data (scores, fixtures, statistics) that anyone can see on the website without logging in. It does not collect personal data. You are responsible for using the data in compliance with Flashscore's terms and the laws of your jurisdiction. This Actor is not affiliated with, endorsed by, or connected to Flashscore or Livesport in any way.

**How fresh are live scores?**
Data is fetched at run time directly from the feed that powers the website, so it is as fresh as the website. For a live ticker, schedule the Actor (e.g. every 1–5 minutes) with `onlyLive: true`.

**Can I get older results than 7 days?**
Not with this Actor yet – Flashscore's daily feed covers today ±7 days. Run it daily on a schedule to build your own history.

**Can I get odds, lineups or H2H?**
Not in the current version. Open an issue if you need them.

**Why is a match missing details?**
Lower leagues often have no statistics or incidents on Flashscore. In that case `statistics`/`incidents` are empty arrays. Scheduled matches have no details yet.

**Which sports are supported?**
Football, tennis, basketball, ice hockey, American football, baseball, handball, volleyball, rugby union & league, cricket, darts, snooker, eSports, table tennis, badminton, beach volleyball, futsal, floorball, bandy, water polo, field hockey, Aussie rules, beach soccer, netball, MMA, boxing, pesäpallo and kabaddi. Race-type sports (golf, motorsport, cycling, horse racing, winter sports) are not supported.

**Cricket scores?**
For cricket, `homeScore`/`awayScore` contain total runs as provided by the feed; wickets/overs are not parsed.

**The Actor stopped working – what now?**
Flashscore sometimes changes its internals. The Actor automatically re-discovers the feed signature from the website. If something still breaks, please report it in the Issues tab and it will be fixed quickly.

# Actor input Schema

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

Which sports to scrape. You can select several.

## `dayOffsetFrom` (type: `integer`):

First day to scrape, relative to today: 0 = today, -1 = yesterday, 1 = tomorrow. Flashscore provides data from -7 (one week ago) to +7 (one week ahead).

## `dayOffsetTo` (type: `integer`):

Last day to scrape (inclusive), relative to today. Leave empty to scrape only the 'From day'. Example: From -7 To -1 = results of the whole last week.

## `onlyLive` (type: `boolean`):

Return only matches that are in progress right now. Overrides the day range.

## `statusFilter` (type: `array`):

Keep only matches with these statuses. Leave empty for all.

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

Keep only matches whose tournament or country contains this text (case-insensitive). Separate several with commas, e.g. 'Premier League, LaLiga, Serie A' or 'ENGLAND, SPAIN'.

## `teamFilter` (type: `string`):

Keep only matches where the home or away team (or tennis player) contains this text. Separate several with commas, e.g. 'Real Madrid, Barcelona'.

## `includeMatchDetails` (type: `boolean`):

For each match also download match statistics (possession, shots, aces, ...), incidents (goals, cards, substitutions, assists) and match info (referee, venue). Charged as an extra 'match-details' event per match and makes the run slower.

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

Maximum number of matches to save. 0 = no limit.

## `timezoneOffset` (type: `integer`):

Defines where a 'day' starts and ends. 0 = UTC days. Example: 1 for London summer time, -5 for New York. Start times in the output are always in UTC (ISO 8601).

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

Usually not needed. Use Apify Proxy if you get blocked.

## Actor input object example

```json
{
  "sports": [
    "football"
  ],
  "dayOffsetFrom": 0,
  "onlyLive": false,
  "statusFilter": [],
  "includeMatchDetails": false,
  "maxItems": 50,
  "timezoneOffset": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped items in the default dataset (JSON, CSV, Excel and more via the dataset export).

## `files` (type: `string`):

Records saved in the default key-value store, e.g. the run summary.

# 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"
    ],
    "dayOffsetFrom": 0,
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("openharvest/flashscore-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"],
    "dayOffsetFrom": 0,
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("openharvest/flashscore-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"
  ],
  "dayOffsetFrom": 0,
  "maxItems": 50
}' |
apify call openharvest/flashscore-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,openharvest/flashscore-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/erWPssMn0Q48tH3gE/builds/hrKe9X6pZSg7O0D98/openapi.json
