# FlashScore Leagues & Fixtures Scraper (`romy/flashscore-leagues-scraper`) Actor

Fetches named league/competition directories plus paginated past results and upcoming fixtures from FlashScore, keyed by sport or tournament stage id. Uses the internal API of the official FlashScore Android app — no account or API key needed. Split out from romy/flashscore-all-in-one-api.

- **URL**: https://apify.com/romy/flashscore-leagues-scraper.md
- **Developed by:** [Romy](https://apify.com/romy) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.10 / 1,000 records

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

### What does FlashScore Leagues & Fixtures Scraper do?

**FlashScore Leagues & Fixtures Scraper** takes a sport and/or a list of tournament stage ids and pushes named leagues, the raw country/competition tree, and paginated past results / upcoming fixtures — one dataset row per league, competition-tree record, or match event.

It talks directly to the same internal API the official [FlashScore](https://www.flashscore.com/) Android app uses, reverse-engineered by capturing and analyzing live traffic from the real app with Frida on a real device. No FlashScore account, no API key. This is the leagues/competitions slice of [FlashScore All-in-One API](https://apify.com/romy/flashscore-all-in-one-api), split out as its own focused, batch (dataset-based) Actor.

### Why use FlashScore Leagues & Fixtures Scraper?

- **Three data sources in one run** — named leagues (with ready-to-use `tournamentId`/`tournamentStageId`), the raw competition tree, and paginated results/fixtures, all as plain dataset rows
- **Enum sport parameter, not opaque numbers** — `sport` takes a readable name (`SOCCER`, `TENNIS`, ...) resolved from the app's own internal identifiers, not guessed
- **Automatic pagination** — results and fixtures are paginated for you, page by page, until the upstream API signals no more pages or `maxPages` is hit
- **No account needed** — every call works fully anonymously
- **Use cases:** building a league directory, tracking a season's results/fixtures, feeding tournament stage ids into other FlashScore spin-off Actors (e.g. [flashscore-standings-scraper](https://apify.com/romy/flashscore-standings-scraper))

### Input

| Field                    | Type     | Description                                                                                                                          |
| ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `sport`                  | string   | Sport name (case-insensitive, e.g. `SOCCER`) or numeric id. Fetches the named league list for this sport.                            |
| `includeRawCompetitions` | boolean  | Fetch the full raw country/competition tree (unmapped pass-through records). Default `false`.                                        |
| `tournamentStageIds`     | string\[] | Tournament stage ids to fetch results/fixtures for (from this Actor's own `league` rows, or the parent Actor's `/leagues` endpoint). |
| `fetchResults`           | boolean  | For each tournament stage id, fetch paginated past results. Only relevant when `tournamentStageIds` is given. Default `true`.        |
| `fetchFixtures`          | boolean  | For each tournament stage id, fetch paginated upcoming fixtures. Only relevant when `tournamentStageIds` is given. Default `true`.   |
| `maxPages`               | integer  | Stop paginating results/fixtures after this many pages per tournament stage id. Default `5`.                                         |

At least one of `sport`, `includeRawCompetitions`, or `tournamentStageIds` must be given.

Example:

```json
{
    "sport": "SOCCER",
    "includeRawCompetitions": true,
    "tournamentStageIds": ["CfoA8Dmm"],
    "maxPages": 2
}
```

### Output

One dataset row per league, competition-tree record, or match event, each tagged with a `type` field. Real rows from this Actor's own smoke test:

A `league` row (English Premier League):

```json
{
    "type": "league",
    "name": "Premier League",
    "region": "England",
    "tournamentId": "SY30SsKF",
    "stages": [{ "tournamentStageId": "CfoA8Dmm", "name": "Main", "order": 1 }]
}
```

A `competition-tree-record` row (raw, unmapped fields — `SA` groups by sport id, `SG` lists semicolon-separated `{countryId}_{competitionId}` pairs):

```json
{
    "type": "competition-tree-record",
    "SA": "1",
    "SG": "198_dYlOSQOD;198_2DSCa5fE;77_KIShoMk3;81_W6BOzpK2;..."
}
```

A `result` row (trimmed — real Premier League match, past result):

```json
{
    "type": "result",
    "tournamentStageId": "CfoA8Dmm",
    "page": 1,
    "id": "4S67nB0K",
    "startTime": 1788103800,
    "event": {
        "eventParticipants": [
            { "id": "b9jIngSq", "name": "Man Utd", "type": { "side": "HOME" }, "state": { "result": "5" } },
            { "id": "6ZgQpXdd", "name": "Ipswich", "type": { "side": "AWAY" }, "state": { "result": "2" } }
        ],
        "eventRound": { "value": "Round 2" }
    }
}
```

A `fixture` row (trimmed — real Premier League match, upcoming fixture):

```json
{
    "type": "fixture",
    "tournamentStageId": "CfoA8Dmm",
    "page": 1,
    "id": "27MtCUO7",
    "startTime": 1788202800,
    "event": {
        "eventParticipants": [
            { "id": "KbkIs7pm", "name": "Aston Villa", "type": { "side": "HOME" } },
            { "id": "hQ2PuoFa", "name": "Arsenal", "type": { "side": "AWAY" } }
        ],
        "eventRound": { "value": "Round 2" }
    }
}
```

### Known limitations

- **The raw competition tree (`competition-tree-record` rows) is unmapped** — only the fields cross-checked against the rendered UI elsewhere in the parent Actor are given clean names; here the raw short codes (`SA`, `SG`) are returned as-is.
- **Results/fixtures pagination stop condition:** the response DOES carry a `hasNextPage` boolean (confirmed live during this Actor's own smoke test) — this Actor uses it as the primary stop signal, falling back to "empty or short page" if it's ever absent, as a safety net against the parent Actor's more general "no total-count field" caveat.
- **`event`'s inner fields are passed through as-is** — this Actor doesn't individually map every nested field (scores, incidents, participant images), since the parent client itself only types this response as `unknown`.
- This is an unofficial, reverse-engineered integration, not affiliated with or endorsed by FlashScore. Behavior may change if FlashScore changes its API.

### Pricing

Pay per event. Charged **$0.004 per `record`** — one dataset row produced (league, raw competition-tree record, result, or fixture). See the Actor's Pricing tab for current rates across tiers.

# Actor input Schema

## `sport` (type: `string`):

Fetch the named league list for this sport (each row includes tournamentId and stage ids). Leave empty to skip.

## `includeRawCompetitions` (type: `boolean`):

Fetch the full raw country/competition tree (unmapped pass-through records).

## `tournamentStageIds` (type: `array`):

Tournament stage ids (from this Actor's own "league" rows, or the parent Actor's /leagues endpoint) to fetch results/fixtures for.

## `fetchResults` (type: `boolean`):

For each tournament stage id, fetch paginated past results. Only relevant when tournamentStageIds is given.

## `fetchFixtures` (type: `boolean`):

For each tournament stage id, fetch paginated upcoming fixtures. Only relevant when tournamentStageIds is given.

## `maxPages` (type: `integer`):

Stop paginating results/fixtures after this many pages per tournament stage id. There is no total-count field upstream, so this also acts as a safety cap.

## Actor input object example

```json
{
  "includeRawCompetitions": false,
  "tournamentStageIds": [
    "CfoA8Dmm"
  ],
  "fetchResults": true,
  "fetchFixtures": true,
  "maxPages": 5
}
```

# Actor output Schema

## `dataset` (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 = {
    "tournamentStageIds": [
        "CfoA8Dmm"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("romy/flashscore-leagues-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 = { "tournamentStageIds": ["CfoA8Dmm"] }

# Run the Actor and wait for it to finish
run = client.actor("romy/flashscore-leagues-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 '{
  "tournamentStageIds": [
    "CfoA8Dmm"
  ]
}' |
apify call romy/flashscore-leagues-scraper --silent --output-dataset

```

## MCP server setup

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