# Flashscore Results Scraper: Full Seasons by League (`zerolag/flashscore-results-scraper`) Actor

Full-season match results from public Flashscore league, tournament and team pages. Scores, half-time, periods, extra time and penalties for football, tennis, basketball, hockey and more. Past seasons, date filters, upcoming matches. No proxy, no login.

- **URL**: https://apify.com/zerolag/flashscore-results-scraper.md
- **Developed by:** [ZeroLag Data](https://apify.com/zerolag) (community)
- **Categories:** Sports, Automation, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 for full seasons. Paste a league, tournament or team address from flashscore.com and get every match as a clean row: final score, half-time, periods, penalties, round and start time.

- **Price:** $1.00 per 1,000 matches on the Free plan, $0.70 on Business. Platform usage is included.
- **Input:** Flashscore addresses. Add past seasons, dates or upcoming matches when you need them.
- **Output:** teams, score, winner, half-time, periods, penalties, stage, round, start time and match link.
- **Measured:** all 380 matches of the 2023/2024 Premier League in 24 seconds on Apify.

Found a bug, need a field, or want a new Actor? Open an issue on the **Issues** tab. If it works well for you, a short review helps others find it.

### How to use it

1. Open a league, tournament or team on [flashscore.com](https://www.flashscore.com/) and copy the address.
2. Paste it into **League, tournament or team addresses**. Add as many as you need.
3. Set **Seasons per league** and **Maximum results**, then click **Start**.
4. Export the results as JSON, CSV or Excel.

| Address | You get |
| --- | --- |
| `flashscore.com/football/england/premier-league/` | The current season |
| `flashscore.com/football/england/premier-league-2023-2024/` | That season |
| `flashscore.com/tennis/atp-singles/wimbledon-2023/` | That tournament, qualifying included |
| `flashscore.com/team/arsenal/hA1Zm19f/` | That team in all competitions, newest first |

Tabs in the address, such as `/results/` or `/standings/`, make no difference.

Example input:

```json
{
    "urls": ["https://www.flashscore.com/football/england/premier-league-2023-2024/"],
    "maxItems": 400
}
```

Football, tennis, basketball, hockey, baseball, American football, handball, volleyball, rugby, cricket, darts, snooker, futsal and Australian football were tested.

### What data you get

Rows have the same fields in every sport. A value the source does not show is `null`.

| Field | What it holds |
| --- | --- |
| `matchId`, `matchUrl` | Match ID and link |
| `sport`, `category` | Sport, then the country, region or tour |
| `league`, `leagueUrl`, `season` | Competition. `season` is empty for team addresses |
| `stage`, `round` | For example `Play Offs` and `Semi-finals`. Empty where the source has none |
| `startTime` | Start in UTC |
| `status` | `finished`, `abandoned`, `scheduled` or `live`. `other` means a state the Actor does not know yet |
| `resultType` | `regular time`, `extra time`, `penalties`, `retired`, `walkover` or `awarded` |
| `homeTeam`, `awayTeam` | Teams, or the first and second player |
| `homeTeamId`, `awayTeamId` | Flashscore IDs, the same in every season |
| `homeScore`, `awayScore` | Final score as the results list shows it, or sets won in tennis |
| `winner` | `home`, `away` or `draw`. A shoot-out counts |
| `halfTimeHomeScore`, `halfTimeAwayScore` | Half-time score in football, futsal, handball and rugby |
| `regularTimeHomeScore`, `regularTimeAwayScore` | Score before any extra time |
| `penaltiesHomeScore`, `penaltiesAwayScore` | Shoot-out score |
| `periods` | Score of each half, quarter, period, set or inning. Tennis sets add `tieBreakHome` and `tieBreakAway` |
| `note` | Flashscore's note, such as an aggregate score or how a cricket match was won |
| `sourceUrl`, `retrievedAt` | Where and when the row was read |

One real row:

```json
{
    "recordType": "match",
    "matchId": "jXP8f29S",
    "matchUrl": "https://www.flashscore.com/match/jXP8f29S/",
    "sport": "football",
    "category": "England",
    "league": "Premier League",
    "stage": null,
    "leagueUrl": "https://www.flashscore.com/football/england/premier-league/",
    "season": "2023/2024",
    "round": "Round 38",
    "startTime": "2024-05-19T15:00:00.000Z",
    "status": "finished",
    "resultType": "regular time",
    "homeTeam": "Arsenal",
    "awayTeam": "Everton",
    "homeTeamId": "hA1Zm19f",
    "awayTeamId": "KluSTr9s",
    "homeScore": 2,
    "awayScore": 1,
    "winner": "home",
    "halfTimeHomeScore": 1,
    "halfTimeAwayScore": 1,
    "regularTimeHomeScore": 2,
    "regularTimeAwayScore": 1,
    "penaltiesHomeScore": null,
    "penaltiesAwayScore": null,
    "periods": [
        {
            "home": 1,
            "away": 1,
            "tieBreakHome": null,
            "tieBreakAway": null
        },
        {
            "home": 1,
            "away": 0,
            "tieBreakHome": null,
            "tieBreakAway": null
        }
    ],
    "note": null,
    "sourceUrl": "https://www.flashscore.com/football/england/premier-league-2023-2024/results/",
    "retrievedAt": "2026-11-06T01:29:07.769Z"
}
```

### How much does it cost?

You pay for each saved match. Rows that only explain an empty result are free. Each run also has a start charge of $0.00005 per GB of memory.

| Plan | Price per 1,000 matches |
| --- | --- |
| Free | $1.00 |
| Starter | $0.90 |
| Scale | $0.80 |
| Business | $0.70 |

Example: a Premier League season has 380 matches. That costs $0.38 on the Free plan and $0.27 on Business.

### How to build a dataset of several seasons

Give the newest season you want and how many to read. This input reads five seasons, from 2023/2024 back to 2019/2020.

```json
{
    "urls": ["https://www.flashscore.com/football/italy/serie-a-2023-2024/"],
    "seasons": 5,
    "maxItems": 2000
}
```

On 6 November 2026 this input saved 1,901 Serie A matches in 80 seconds. Use `homeTeamId` and `awayTeamId` to follow a team across seasons.

### How to keep a results table up to date

Set **First day** to a short length and add an Apify Schedule. Recent matches are in the page itself, so these runs do not open a browser.

```json
{
    "urls": [
        "https://www.flashscore.com/football/england/premier-league/",
        "https://www.flashscore.com/football/spain/laliga/"
    ],
    "dateFrom": "7 days",
    "maxItems": 300
}
```

Join rows on `matchId`. You pay again for a match you read again, so keep the window as short as your schedule allows.

### How to list upcoming matches

Set **Matches** to **Upcoming matches**. Use **Last day** for the end of the window. A length such as `7 days` counts forward here.

```json
{
    "urls": ["https://www.flashscore.com/football/germany/bundesliga/"],
    "matchType": "fixtures",
    "dateTo": "7 days",
    "maxItems": 100
}
```

### Limits

- **No odds, lineups, goal scorers or match statistics.** Rows come from the results list, so they hold what that list holds.
- **No list of all matches of one day.** The Actor reads league, tournament and team pages, so name the leagues you need. Flashscore's robots.txt closes its day pages.
- **Only sports with two sides.** Golf, motorsport and cycling pages have no match list and give a free notice row. Player pages are not supported.
- **A browser is needed beyond the newest matches.** A page holds about 100 matches, and the rest load in steps of about 100, or 40 on team pages. The Actor opens the page and presses its **Show more matches** button.
- **Long lists take time.** Each press of the button gets slower as the page grows. Two full seasons of MLB and NBA, 3,850 matches, took 163 seconds. One team page took 25 minutes for 4,320 matches, so use **First day** or **Maximum results** there.
- **Football `periods` holds two halves.** Goals in extra time appear only in `homeScore`.
- **Some sports have less.** Australian football has final points but no `periods`. Cricket scores are runs, without wickets or overs.
- **Pace:** one page or one press of the button at a time, on purpose.
- **A run reads what Flashscore shows at that moment.** A `live` row is a snapshot and does not update.

### API and integrations

Start runs and read results through the [Apify API](https://docs.apify.com/api/v2) or the JavaScript and Python clients. Use Schedules for repeat runs and webhooks to send the data on when a run ends.

Only need tennis? [Tennis Scraper](https://apify.com/zerolag/tennis-scraper) adds average odds, rankings and head-to-head records from another source.

### FAQ

**Do I need a proxy or a Flashscore account?**
No. The Actor reads public pages, and the test runs on Apify used no proxy.

**Why is there a row with `recordType` set to `notice`?**
It explains why part of your input gave nothing, for example an address with no page, or that a long list stopped early. These rows are free.

**How far back does the data go?**
It depends on the league. The Premier League archive on Flashscore lists 115 seasons, the oldest is 1901/1902. A test run read 306 matches of that oldest season.

**Why does a shoot-out look different in football and hockey?**
The Actor keeps each sport as the results list shows it. In football `homeScore` stays at the score after extra time, and the shoot-out is only in `penaltiesHomeScore`. In hockey the final score already counts the shoot-out win.

**Which time zone are the dates in?**
`startTime`, **First day** and **Last day** are all UTC.

**Why did a run stop before the end of a season?**
It reached **Maximum results** or your spending limit, and the status message says which. A season of 380 matches needs a limit above 380. If the page itself failed, a free notice row says how many matches were read.

**Can I use this data in a commercial product?**
Check first. The terms of use of Flashscore limit commercial use, scraping and copying large parts of its database. You are responsible for how you use the data.

*This Actor is an independent tool with no connection to Flashscore or Livesport. All trademarks belong to their owners.*

# Actor input Schema

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

Paste Flashscore pages. A league page such as <code>https://www.flashscore.com/football/england/premier-league/</code> gives the current season, a season page such as <code>.../premier-league-2023-2024/</code> gives that season, and a team page such as <code>https://www.flashscore.com/team/arsenal/hA1Zm19f/</code> gives that team's matches in all competitions. Tabs like <code>/results/</code> are fine.

## `seasons` (type: `integer`):

How many seasons to read for each league address, counting back from the season in the address. 1 reads that season only, 5 adds the four seasons before it. Team addresses ignore this.

## `matchType` (type: `string`):

Finished matches, upcoming matches, or both. Upcoming matches exist only for the current season.

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

The run stops after saving this many matches. You pay only for saved matches. A Premier League season has 380, so raise this for full seasons.

## `dateFrom` (type: `string`):

Optional, in UTC. Keeps matches from this day on. <code>7 days</code> counts back from today for results and forward for upcoming matches. A date filter also makes the run faster, because the Actor stops loading once it passes the dates.

## `dateTo` (type: `string`):

Optional, in UTC. Keeps matches up to this day.

## Actor input object example

```json
{
  "urls": [
    "https://www.flashscore.com/football/england/premier-league-2023-2024/"
  ],
  "seasons": 1,
  "matchType": "results",
  "maxItems": 50
}
```

# 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 = {
    "urls": [
        "https://www.flashscore.com/football/england/premier-league-2023-2024/"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("zerolag/flashscore-results-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 = {
    "urls": ["https://www.flashscore.com/football/england/premier-league-2023-2024/"],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("zerolag/flashscore-results-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 '{
  "urls": [
    "https://www.flashscore.com/football/england/premier-league-2023-2024/"
  ],
  "maxItems": 50
}' |
apify call zerolag/flashscore-results-scraper --silent --output-dataset

```

## MCP server setup

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