# Flashscore Tennis Scraper - Live Scores, Stats, H2H & Odds (`sourabhbgp/flashscore-tennis-scraper`) Actor

Scrape ATP, WTA, Challenger and ITF tennis from Flashscore: results, fixtures and live scores with set by set scores, tiebreaks and the current game score. Both doubles players are identified. Switch modes for statistics, head to head history or bookmaker odds. No proxy needed.

- **URL**: https://apify.com/sourabhbgp/flashscore-tennis-scraper.md
- **Developed by:** [Sourabh Kumar](https://apify.com/sourabhbgp) (community)
- **Categories:** Sports, Automation, Developer tools
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 tennis row delivereds

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/platform/actors/running/actors-in-store#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

### Flashscore tennis scraper: scores, statistics, head to head and odds

Pull tennis results and fixtures from Flashscore with set by set scores and tiebreaks. Switch modes to add match statistics, head to head history, or bookmaker odds with the opening price and how far it has moved.

**$1 per 1,000 results. No per-run fee. Every mode, one flat price.**

Covers ATP, WTA, Challenger, ITF men and women, juniors, and team events like the Davis Cup.

### Why this scraper?

- 💵 **$1 per 1,000 rows with no per-run fee**, so a run that returns nothing costs you nothing.
- 🎾 **Four modes in one actor.** Scores, statistics, head to head and odds usually mean four separate scrapers, each billing you separately.
- 👥 **Both doubles players, fully identified** with their own ID, nationality and photo, so a mixed nationality pair is not flattened into one country.
- 🔴 **Live game score and who is serving** on in play matches, not just the set scores.
- ⚠️ **Walkovers, withdrawals and retirements are flagged separately**, so a 6-0 6-0 that never happened does not pollute your results.
- 📈 **Odds carry the opening price and the movement**, not just today's number, so you can see which way a line drifted.
- 🌍 **Read any country's bookmakers from one run.** Great Britain returns up to 20, Brazil the widest Latin American set. No proxy setup, no VPN.
- ⚡ **Fast and cheap to run.** Plain HTTP with no browser, so a 250 row pull finishes in about 13 seconds.
- 🎯 **Filter before you pay.** Narrow by tournament URL, tour, draw, surface, status or specific days, and matches with nothing published are skipped and never billed.

### What data can you extract?

<table>
<tr><td>🏟️ Tournament and surface</td><td>🔗 Tournament URL</td><td>🕐 Start time (UTC)</td><td>📊 Set by set scores</td></tr>
<tr><td>🥇 Winner</td><td>🔢 Tiebreak points</td><td>🔴 Live game score</td><td>🎾 Who is serving</td></tr>
<tr><td>🌍 Player nationality</td><td>🆔 Player IDs and slugs</td><td>👥 Both doubles players</td><td>🖼️ Player photos</td></tr>
<tr><td>⚠️ Walkovers, withdrawals, retirements</td><td>🎯 Aces and double faults</td><td>🎾 Break points won and saved</td><td>💥 Winners and unforced errors</td></tr>
<tr><td>🤝 Head to head record</td><td>📉 Recent form both sides</td><td>💰 Bookmaker odds</td><td>📈 Opening price and drift</td></tr>
</table>

### Scraping modes

#### 🎾 Matches (default)

Fixtures and results for a date range, with set by set scores, tiebreaks, winner, nationality and tournament detail. Live matches also carry the current game score and the server.

```json
{ "mode": "matches", "dateFrom": "2026-08-12", "dateTo": "2026-08-13", "tours": ["ATP", "WTA"], "drawType": "singles", "maxItems": 200 }
```

Point it at a tournament instead of a date range by pasting its Flashscore address:

```json
{ "mode": "matches", "startUrls": ["https://www.flashscore.com/tennis/atp-singles/cincinnati/"], "maxItems": 200 }
```

Or pick individual days, which do not have to be next to each other:

```json
{ "mode": "matches", "dayOffsets": ["0", "1"], "maxItems": 200 }
```

#### 📊 Statistics

Twenty statistics per match and per set: aces, double faults, first serve percentage, break points saved and converted, winners, unforced errors, service and return points won.

```json
{ "mode": "statistics", "tours": ["ATP", "WTA"], "statuses": ["finished"], "maxItems": 50 }
```

#### 🤝 Head to head

Past meetings between the two players plus recent form for each side. Trim how much history you keep with `h2hMaxPerSection`.

```json
{ "mode": "h2h", "tours": ["ATP"], "h2hMaxPerSection": 10, "maxItems": 25 }
```

#### 💰 Odds

Bookmaker prices for each match, with the opening price, the current price and the direction it moved. Pick the market with `oddsCountry`.

```json
{ "mode": "odds", "oddsCountry": "GB", "oddsBetTypes": ["HOME_AWAY", "OVER_UNDER"], "oddsScopes": ["FULL_TIME"], "maxItems": 50 }
```

### How to scrape Flashscore tennis: step by step

1. [Create a free Apify account](https://console.apify.com/sign-up). Takes 30 seconds, no card needed.
2. Open [Flashscore Tennis Scraper](https://console.apify.com/actors/QYy9xZMBbXvOr2Sb8?addFromActorId=QYy9xZMBbXvOr2Sb8) in the Apify Console.
3. Pick a mode, then set a date range and any filters you want. Leave the dates empty for today.
4. Click **Start**. Most runs finish in under 15 seconds.
5. Export as JSON, CSV, or Excel, or fetch it from the API.

### How much does Flashscore Tennis Scraper cost?

You pay **$1.00 per 1,000 rows**, and there is no per-run fee. The Apify Free plan gives you $5 in usage credits a month, which is roughly **5,000 rows**. The $29/month Starter plan covers about **29,000 rows** a month.

Rows are only charged when they are delivered. If a match has no statistics or no odds published, it is skipped and you are not billed for it.

### Input

```json
{
  "mode": "matches",
  "dateFrom": "2026-08-12",
  "dateTo": "2026-08-13",
  "tours": ["ATP", "WTA"],
  "drawType": "singles",
  "surfaces": ["hard"],
  "statuses": ["finished"],
  "tournamentQuery": ["Cincinnati", "Toronto"],
  "maxItems": 200
}
```

| Field | Type | Default | Notes |
|---|---|---|---|
| `mode` | string | `matches` | `matches`, `statistics`, `h2h` or `odds` |
| `startUrls` | array | none | Flashscore tournament addresses. Keeps only matches from those tournaments |
| `dayOffsets` | array | none | Individual days from `-7` to `1`. Replaces the date range, and they need not be consecutive |
| `dateFrom` / `dateTo` | string | today | `YYYY-MM-DD`. Flashscore serves 7 days back through tomorrow |
| `tours` | array | all | `ATP`, `WTA`, `CHALLENGER`, `ITF_MEN`, `ITF_WOMEN`, `JUNIORS`, `TEAMS` |
| `drawType` | string | `all` | `singles` or `doubles` |
| `surfaces` | array | all | `hard`, `clay`, `grass`, `carpet` |
| `statuses` | array | all | `scheduled`, `live`, `finished` |
| `tournamentQuery` | array | none | Keep tournaments whose name contains any one of these |
| `matchIds` | array | none | Scrape exact match IDs and ignore every filter above |
| `maxItems` | integer | 100 | Your cost ceiling, since you pay per row |
| `oddsCountry` | string | `GB` | `GB`, `BR`, `US`, `DE` or `IN`. Odds mode only |
| `oddsBetTypes` | array | `HOME_AWAY` | Also `OVER_UNDER`, `ASIAN_HANDICAP`, `CORRECT_SCORE`, `ODD_OR_EVEN` |
| `oddsScopes` | array | `FULL_TIME` | Also `FIRST_SET`, `SECOND_SET` |
| `h2hMaxPerSection` | integer | 10 | Past matches kept per section. H2H mode only |

**How the filters combine.** Entries inside one filter are an "any of" list, and separate filters all have to be satisfied. So two tournament URLs return matches from either one, but adding `statuses: ["finished"]` on top keeps only the finished ones. Note that Flashscore gives singles and doubles separate addresses, so a `.../atp-singles/...` URL returns no doubles.

Already have match IDs from an earlier run? Pass them straight in:

```json
{ "mode": "odds", "matchIds": ["fqlRb8xp", "YT1HRITp"], "oddsCountry": "GB" }
```

### Output

**Matches**

```json
{
  "matchId": "fqlRb8xp",
  "url": "https://www.flashscore.com/match/fqlRb8xp/",
  "matchType": "singles",
  "startTimestamp": 1786572600,
  "startTime": "2026-08-12T22:10:00.000Z",
  "endTimestamp": 1786580150,
  "endTime": "2026-08-13T00:15:50.000Z",
  "status": "finished",
  "statusDetailCode": 3,
  "note": null,
  "isWalkover": false,
  "isWithdrawn": false,
  "isRetired": false,
  "endedEarly": false,
  "winner": "away",
  "isInPlay": false,
  "currentGameScoreHome": null,
  "currentGameScoreAway": null,
  "server": null,
  "homePlayer": {
    "name": "Jodar R.",
    "names": [
      "Jodar R."
    ],
    "players": [
      {
        "name": "Jodar R.",
        "participantId": "OdngshVK",
        "playerId": "voyKqlqS",
        "slug": "jodar-rafael",
        "country": "Spain",
        "countryId": 176,
        "imageUrl": "https://static.flashscore.com/res/image/data/zqkYjime-bJuw1oYE.png"
      }
    ],
    "playerId": "voyKqlqS",
    "participantId": "OdngshVK",
    "participantId2": null,
    "slug": "jodar-rafael",
    "abbreviation": "JOD",
    "country": "Spain",
    "countryId": 176,
    "imageUrl": "https://static.flashscore.com/res/image/data/zqkYjime-bJuw1oYE.png"
  },
  "awayPlayer": {
    "name": "Nakashima B.",
    "names": [
      "Nakashima B."
    ],
    "players": [
      {
        "name": "Nakashima B.",
        "participantId": "ETGnbrpH",
        "playerId": "80RkvS6k",
        "slug": "nakashima-brandon",
        "country": "USA",
        "countryId": 200,
        "imageUrl": "https://static.flashscore.com/res/image/data/Ao55Oc7k-I3vxtblK.png"
      }
    ],
    "playerId": "80RkvS6k",
    "participantId": "ETGnbrpH",
    "participantId2": null,
    "slug": "nakashima-brandon",
    "abbreviation": "NAK",
    "country": "USA",
    "countryId": 200,
    "imageUrl": "https://static.flashscore.com/res/image/data/Ao55Oc7k-I3vxtblK.png"
  },
  "homeSetsWon": 0,
  "awaySetsWon": 2,
  "setsPlayed": 2,
  "sets": [
    {
      "set": 1,
      "home": 6,
      "away": 7,
      "homeTiebreak": 3,
      "awayTiebreak": 7
    },
    {
      "set": 2,
      "home": 4,
      "away": 6,
      "homeTiebreak": null,
      "awayTiebreak": null
    }
  ],
  "scoreSummary": "6-7(3), 4-6",
  "tournament": {
    "tournamentId": "IyRQC2vM",
    "stageId": "jakzJP44",
    "name": "Montreal",
    "fullName": "ATP - SINGLES: Montreal (Canada), hard",
    "tour": "ATP",
    "tourLabel": "ATP - Singles",
    "drawType": "singles",
    "surface": "hard",
    "country": "Canada",
    "isQualification": false,
    "urlPath": "/tennis/atp-singles/montreal/",
    "url": "https://www.flashscore.com/tennis/atp-singles/montreal/"
  },
  "scrapedAt": "2026-08-13T15:08:57.755Z"
}
```

**A doubles pair,** with each player separated out. Marcelo Arevalo is Salvadoran and Mate Pavic is Croatian, so a single country on the row would be wrong for one of them:

```json
{
  "matchId": "IarlCOB7",
  "matchType": "doubles",
  "homePlayer": {
    "name": "Arevalo M./Pavic M.",
    "names": ["Arevalo M.", "Pavic M."],
    "players": [
      { "name": "Arevalo M.", "participantId": "2Dnk4gai", "playerId": "8IxTwFIq", "slug": "arevalo-marcelo", "country": "El Salvador", "countryId": 70, "imageUrl": "https://static.flashscore.com/res/image/data/ClGancWH-jc6XgREf.png" },
      { "name": "Pavic M.", "participantId": "zLNFemL9", "playerId": null, "slug": null, "country": "Croatia", "countryId": 59, "imageUrl": "https://static.flashscore.com/res/image/data/buhflOiT-OhNpdMM4.png" }
    ],
    "participantId": "2Dnk4gai",
    "participantId2": "zLNFemL9"
  }
}
```

**A live match,** with the game score and the server:

```json
{
  "matchId": "AN06zHRi",
  "status": "live",
  "isInPlay": true,
  "scoreSummary": "3-6, 7-6(5), 5-4",
  "currentGameScoreHome": "0",
  "currentGameScoreAway": "0",
  "server": "away",
  "endTime": null
}
```

The game score is text, not a number: it is `0`, `15`, `30`, `40` or `A` for advantage during a normal game, and a plain point count during a tiebreak.

**Statistics**

```json
{
  "matchId": "fVjaLWSG",
  "homePlayer": "Giron M.",
  "awayPlayer": "Rocha H.",
  "periods": ["Match", "Set 1", "Set 2"],
  "statisticsCount": 49,
  "statistics": [
    { "period": "Match", "group": "Service", "stat": "Aces", "home": "2", "away": "5" },
    { "period": "Match", "group": "Service", "stat": "1st serve percentage", "home": "52%", "away": "68%" },
    { "period": "Match", "group": "Return", "stat": "Break Points Converted", "home": "2/8", "away": "3/9" }
  ]
}
```

**Head to head**

```json
{
  "matchId": "C8MVcxVh",
  "homePlayer": "Mejia N.",
  "awayPlayer": "Fearnley J.",
  "tournamentName": "Cincinnati",
  "headToHeadCount": 1,
  "headToHead": [
    {
      "matchId": "C8MVcxVh",
      "date": "2026-08-12T22:30:00.000Z",
      "tournament": "Cincinnati",
      "surface": "hard",
      "homePlayer": "Mejia N.",
      "awayPlayer": "Fearnley J.",
      "score": "2:1",
      "homeSetsWon": 2,
      "awaySetsWon": 1,
      "winner": "home"
    }
  ],
  "homeRecentForm": [
    { "date": "2026-08-12T22:30:00.000Z", "tournament": "Cincinnati", "score": "2:1", "winner": "home", "resultForSectionPlayer": "w" }
  ],
  "awayRecentForm": [
    { "date": "2026-08-12T22:30:00.000Z", "tournament": "Cincinnati", "score": "2:1", "winner": "home", "resultForSectionPlayer": "l" }
  ]
}
```

**Odds**

```json
{
  "matchId": "YT1HRITp",
  "homePlayer": "Siniakova K./Zhang S.",
  "awayPlayer": "Mihalikova T./Nicholls O.",
  "oddsCountry": "GB",
  "bookmakerCount": 20,
  "offerCount": 74,
  "odds": [
    {
      "bookmakerId": 15,
      "bookmakerName": "William Hill",
      "betType": "HOME_AWAY",
      "betScope": "FULL_TIME",
      "side": "home",
      "playerName": "Siniakova K./Zhang S.",
      "opening": "1.4",
      "current": "1.22",
      "movement": "down"
    }
  ]
}
```

### Use cases

- 📊 **Model building and backtesting.** Pull results with set by set detail to train or check a match prediction model.
- 📈 **Line movement tracking.** Compare the opening price against the current one across 20 bookmakers to spot where money went.
- 🔍 **Bookmaker comparison.** See which book is offering the best price on the same match in Britain, Brazil, Germany, the US or India.
- 📰 **Live scoreboards and content.** Feed a site, newsletter or bot with fixtures and results across every tour.
- 🎾 **Player form research.** Combine head to head history with recent form to preview a matchup.
- 📉 **Serve and return analysis.** Use the per set statistics to break down where a match was won.
- 🤖 **Fantasy and prediction games.** Score entries against real results without maintaining a scraper yourself.
- 🗄️ **Building a results archive.** Run daily to accumulate history well past the nine day window Flashscore itself serves.

### Limitations

- **Nine day window.** Flashscore publishes 7 days of past results plus today and tomorrow, so run daily if you want a longer archive.
- **Three things Flashscore does not publish for tennis:** player rankings, round name, and best of three or five. A "ranking" field on another scraper whose value repeats across unrelated players from the same country is the country ID, which this actor names `countryId` and never calls a rank.
- **No match duration, and it is not guessable.** The only timestamps in the source are the scheduled start and a marker for the end of the last completed set, so a match that starts two hours late would look two hours longer than it was. This actor ships neither a duration nor a guess.
- **End time only on finished matches.** It is null while a match is in play, and absent on some finished lower tier matches where Flashscore never recorded it.
- **Doubles pairs carry one player ID.** Both players get a name, participant ID, nationality and photo; the longer `playerId` and profile `slug` are for the lead player only, and the three letter abbreviation is singles only.
- **Odds are pre-match, and statistics need a started match.** Live in play pricing is not claimed, and scheduled matches have no statistics yet so they are skipped and never charged.

### FAQ

#### How much does Flashscore Tennis Scraper cost?

It uses pay-per-result pricing. You pay **$1.00 for 1,000 results** and there is no per-run fee. The Apify Free plan gives you $5 in usage credits a month, enough for around 5,000 results. If you run regularly, the $29/month Starter plan covers about 29,000 results.

No subscription lock-in. Pause whenever.

#### Is it legal to scrape Flashscore?

Scraping public data is generally allowed in the US and most of the EU, as long as you don't collect personal data covered by GDPR or CCPA without a lawful basis. This actor only touches publicly accessible pages, but how you use the output is on you.

Apify's full breakdown: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/).

#### Can I integrate it with other tools?

Push results into **Make, Zapier, Slack, Airbyte, GitHub, Google Sheets, Google Drive**, and more. Apify treats every actor as a webhook source, so anything that consumes webhooks or pulls from an API works.

Full list: [Apify integrations](https://docs.apify.com/platform/integrations).

#### Can I use it with the Apify API?

Yes. Every run is available via the Apify REST API:

```bash
curl -X POST "https://api.apify.com/v2/acts/sourabhbgp~flashscore-tennis-scraper/runs?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode": "matches", "tours": ["ATP"], "maxItems": 50}'
```

Docs: [Apify API reference](https://docs.apify.com/api/v2).

#### Can I use it through an MCP Server?

Yes. Apify ships an MCP server that exposes every actor as a tool, so Claude Desktop, Cursor, and any other MCP-capable client can call this scraper. Setup: [Apify MCP docs](https://docs.apify.com/platform/integrations/mcp).

### Your feedback

Bug, missing field, or odd behavior? Drop a note in the [Issues tab](https://console.apify.com/actors/QYy9xZMBbXvOr2Sb8/issues). Reports go to a human and fixes usually ship the same week.

# Actor input Schema

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

Matches returns fixtures and results with set by set scores. Statistics, head to head and odds each add one row per match on top of the same match selection, so they cost more per match. Start with matches.

## `startUrls` (type: `array`):

Keep only matches from these Flashscore tournaments, for example https://www.flashscore.com/tennis/atp-singles/cincinnati/. Deeper addresses such as the results or draw page of the same tournament work too. A category address such as https://www.flashscore.com/tennis/atp-singles/ keeps every tournament under it. Singles and doubles have separate addresses on Flashscore, so a singles URL returns no doubles. Combine with the date fields to choose which days to search.

## `dayOffsets` (type: `array`):

Pick individual days instead of a continuous range, for example today and tomorrow only. When set, this replaces the date from and date to fields. Only the days Flashscore actually publishes are offered.

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

First match day to include, as YYYY-MM-DD. Flashscore only serves a rolling 9 day window: 7 days back through 1 day ahead. Dates outside that window are clamped and reported in the run log. Days follow Flashscore's own scheduling day, so a late night match can carry a startTime on the previous UTC date. Leave empty for today. Ignored when Specific days is set.

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

Last match day to include, as YYYY-MM-DD. Must be on or after the date from. Leave empty to use the date from. Ignored when Specific days is set.

## `tours` (type: `array`):

Keep only these tours. Leave empty to include every tour.

## `drawType` (type: `string`):

Keep only singles or only doubles matches.

## `surfaces` (type: `array`):

Keep only matches on these surfaces. Team events often have no surface listed and are excluded when this filter is set.

## `statuses` (type: `array`):

Keep only matches in these states. Leave empty to include every state.

## `tournamentQuery` (type: `array`):

Keep only matches whose tournament name contains any one of these, for example Cincinnati. Case insensitive, and one entry per line. Use this when you know the event by name; use Tournament URLs when you have the exact Flashscore address.

## `matchIds` (type: `array`):

Scrape these exact Flashscore match IDs instead of searching by date, for example fVjaLWSG. The ID is the last part of a Flashscore match URL. When set, every date and filter field above is ignored.

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

Stop after this many rows. You are charged per row delivered, so this is your cost ceiling.

## `oddsCountry` (type: `string`):

Which country's bookmaker line up to return. This selects the market, not your own location, and needs no proxy. Great Britain returns the widest set.

## `oddsBetTypes` (type: `array`):

Which markets to return. Each extra bet type adds bookmaker lines to the row but never adds rows or charges. Correct score is by far the largest.

## `oddsScopes` (type: `array`):

Whole match, first set or second set lines.

## `h2hMaxPerSection` (type: `integer`):

How many past matches to keep for each player's recent form and for the head to head list. Flashscore serves up to 50 per player, which is large for CSV export, so this trims it.

## Actor input object example

```json
{
  "mode": "matches",
  "startUrls": [],
  "dayOffsets": [],
  "tours": [],
  "drawType": "all",
  "surfaces": [],
  "statuses": [],
  "tournamentQuery": [],
  "matchIds": [],
  "maxItems": 50,
  "oddsCountry": "GB",
  "oddsBetTypes": [
    "HOME_AWAY"
  ],
  "oddsScopes": [
    "FULL_TIME"
  ],
  "h2hMaxPerSection": 10
}
```

# Actor output Schema

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

View the scraped tennis rows in the dataset.

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

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

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

```

## MCP server setup

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