# Flashscore Tennis Scraper for Tennis Matches and Stats (`cleanscrape/tennis-match-data`) Actor

Tennis match data from Flashscore. Type a tournament or player name, paste a link, or collect by day. Match results with tiebreaks, match statistics with counts, set durations, point-by-point, form and head-to-head. From $1 per 1,000 matches.

- **URL**: https://apify.com/cleanscrape/tennis-match-data.md
- **Developed by:** [CleanScrape](https://apify.com/cleanscrape) (community)
- **Categories:** Other, Developer tools, AI
- **Features:** Limited permissions
- **Stats:** 4 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 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 Tennis Scraper for Tennis Matches and Stats

Download tennis match data from Flashscore as CSV, Excel or JSON. Type a tournament or player name, paste a Flashscore link, or leave the list empty to collect matches by day.

Each match comes with the score including tiebreaks, the round and an exact status. Optional extras:

- match statistics with counts
- set durations and the umpire
- point-by-point
- recent form and head-to-head

It is built for people who model, analyse or write about tennis. The numbers keep their counts ("58 of 80 first-serve points won"), and every row says what Flashscore had for that match. Nothing is filled in by guesswork.

No Flashscore account, cookies or API key is needed. This is an independent tool, maintained by CleanScrape. For the current ATP and WTA rankings, see the [ATP and WTA Tennis Rankings Scraper](https://apify.com/cleanscrape/tennis-rankings-scraper).

Here is a walkthrough with Wimbledon 2025: every singles match with statistics, and what the totals say about how Sinner won. Type your own tournament or player for another project.

https://www.youtube.com/watch?v=eDn2dKHsRXA

### Start with a small run

The form opens with **Wimbledon 2025** and a maximum of 20 matches, which gives the latest rounds of the first draw (the men's singles, from the final back) with statistics. Start it as it is to see the output, then raise the maximum for both full draws or change the list.

1. In **Tournaments, players or matches**, type what you want, one per line. Leave it empty to collect by day.
2. If the list is empty, pick the **Days**.
3. Set **Maximum matches** and start the run. With several lines, the maximum is shared evenly between them.

Open the **Matches**, **Statistics** or **Form and head-to-head** view, then export. Use JSON when you need the nested data (per-set statistics, point-by-point, form lists).

### What you can type

| You type | You get |
| --- | --- |
| `Wimbledon 2025` | The 2025 men's and women's singles draws, including qualifying |
| `Wimbledon` | The latest edition. Set **Editions per tournament** to 5 for the last five years |
| `US Open women 2024`, `Australian Open doubles`, `Wimbledon juniors` | Just those draws |
| `Sinner`, `Swiatek 2025` | The player's matches, newest first, or only that year |
| A Flashscore link | The tournament, player or match it points to. Any page of it works (results, draw, summary), from any Flashscore site, with or without https |
| A match ID such as `Glwf9adK` | That match |

Common names work too: `Roland Garros` finds the French Open and `ATP Finals` finds Turin. The run report shows how each line was read, for example *"Wimbledon 2025" was read as ATP Wimbledon 2025, WTA Wimbledon 2025*. If a name is unclear, the report says so and nothing unrelated is collected. Paste the Flashscore link in that case.

### Collect by day

Leave the list empty and choose **Days**: yesterday, today, tomorrow, the last or next 3 or 7 days, or custom dates. Flashscore's daily lists go 7 days back and 7 days ahead (UTC). For anything older, add the tournament or player to the list.

**Tours**, **Match type** and **Match status** narrow the days. The defaults are ATP and WTA, singles and finished matches. Tours also decide which draws a tournament name gives you. A pasted tournament link, a player or a match link is not limited by tour.

### Examples

Yesterday's ATP and WTA singles with statistics:

```json
{ "dayRange": "yesterday", "maxResults": 100 }
```

The last five Wimbledon editions, men and women:

```json
{ "targets": ["Wimbledon"], "seasons": 5, "maxResults": 3000 }
```

A player's 2026 matches with point-by-point:

```json
{ "targets": ["Sinner 2026"], "pointByPoint": true, "maxResults": 200 }
```

Upcoming matches with form and head-to-head:

```json
{ "dayRange": "next-3-days", "statuses": ["scheduled"], "statistics": false, "setDetails": false, "formAndH2H": true }
```

### What each match contains

| Column | Meaning |
| --- | --- |
| Start (UTC), Status | Scheduled start in UTC. Status is `finished`, `retired`, `walkover`, `scheduled`, `live`, `cancelled`, `postponed`, `interrupted`, `abandoned` or `awarded` |
| Tour, Type, Tournament, Country, Surface, Round, Qualifying, Season | Event details. Round is, for example, `Final` or `1/16-finals`; qualifying rounds start with `Qualification` |
| Home player, Away player | As listed by Flashscore. Doubles show both names and have partner columns |
| Winner, Sets won (home/away), Score | The home player comes first in the score. A tiebreak score in brackets is the points of the player who lost the set: `7-6(5) 6-7(5) 6-2`. Retirements end with `ret.`, walkovers show `w/o` |
| Sets (JSON) | Games, tiebreak points and duration for each set |
| Duration (min), Umpire | Match duration and the chair umpire, when **Set durations and umpire** is on |
| IDs and links | Match, player and tournament IDs and links. Keep ID columns as text in spreadsheets |
| Coverage notes | What was not available for this match, in plain words |

#### Statistics (Match statistics on)

Each statistic has a home and an away column. Ratios keep both numbers, so `firstServePointsWonHome` = 58 and `firstServePointsPlayedHome` = 80.

- **Service:** aces, double faults, first serve in (%), first-serve and second-serve points won and played, break points saved and faced.
- **Return:** first-return and second-return points won and played, break points converted and opportunities.
- **Points and games:** service, return and total points; service, return and total games.
- **Bigger events also have:** winners, unforced errors, net points, average first and second serve speed (km/h) and distance covered (m).

The same statistics for each set are in `setStatistics`. `statisticsLevel` is `full`, `basic` (only a couple of counters) or `none`.

#### Point-by-point (optional)

For every set, each game has its server, its winner, whether serve was broken, and every point score. Points that were break points, set points or match points are marked. Tiebreaks are listed point by point with the server of each point.

#### Form and head-to-head (optional)

- Head-to-head matches and the win count for each side. Each earlier meeting's sets are given from the current match's sides, so `2-1` means the home player won two sets.
- Each player's latest matches, overall and on the current surface: date, tournament, opponent, result and score.
- Summary columns (`homeFormWon` of `homeFormPlayed` and so on) for quick filtering.

Form lists are Flashscore's latest lists at collection time. For a past match they can include matches played after it.

### Coverage

What Flashscore publishes depends on the event, season and individual match. This table describes typical coverage, not a guarantee that every match has every field:

| Event | Score and status | Statistics | Point-by-point | Form and H2H |
| --- | --- | --- | --- | --- |
| ATP, WTA, Challenger, Grand Slams | Yes | Full | Yes | Yes |
| ITF | Yes | Usually none or basic | Sometimes | Yes |
| Walkover | Status only | None | None | Yes |
| Scheduled | Start time | After the match | After the match | Yes |

Matches from earlier years keep their details on Flashscore, so tournament and player history comes with statistics too. Round names come from the tournament's own lists. A few events, such as the Laver Cup, have no round names.

Every run saves a **Run report**: how each line was read, what it returned, how many matches matched your settings, detail coverage, and why the run stopped. Open it from the Output tab.

### Pricing

You pay per result, with no start fee:

| What is saved | Price per 1,000 |
| --- | --- |
| Match | $1.00 |
| Match details: statistics, set details or point-by-point, when Flashscore has them | $1.50 |
| Form and head-to-head | $0.50 |

Details and form are charged only when they are actually saved for that match. For example:

- 100 matches with statistics cost $0.25.
- 239 matches with statistics cost $0.5975. The number available depends on the draws, qualifying and source coverage.

Apify tier discounts apply. Set a spending limit for large runs; the run stops cleanly when it is reached. The limit must cover a match and all the extras you selected; if it cannot, that match is not saved or charged.

### Ready-to-run examples

Each example opens with its input filled in. Change the input and run it.

| Example | What it does |
| --- | --- |
| [Wimbledon 2025 results with statistics](https://apify.com/cleanscrape/tennis-match-data/examples/tennis-wimbledon-2025-statistics) | Every men's and women's singles match of Wimbledon 2025, including qualifying: scores with tiebreaks, set durations, umpire and match statistics with counts. |
| [Yesterday's ATP and WTA results](https://apify.com/cleanscrape/tennis-match-data/examples/tennis-yesterday-atp-wta-results) | All ATP and WTA singles matches finished yesterday (UTC), with scores, rounds, set durations and match statistics. |
| [Upcoming matches with form and head-to-head](https://apify.com/cleanscrape/tennis-match-data/examples/tennis-upcoming-form-head-to-head) | ATP and WTA singles matches scheduled for the next 3 days, each with the head-to-head record and both players' last 10 matches, overall and on the surface. |

### Use it from an AI agent

This Actor works as a tool in Claude, Cursor and other AI assistants that support MCP, through Apify's MCP server. Add this server and sign in with your Apify account when asked:

```
https://mcp.apify.com?tools=cleanscrape/tennis-match-data
```

Then ask in plain words, for example: "Get today's ATP results from Flashscore with the match statistics." The assistant runs the Actor in your Apify account and reads the results. The price per result is the same as in Console.

### Common questions

#### Where can I get tennis match statistics?

This Actor exports them from Flashscore: aces, double faults, serve and return points, break points and more, with the counts behind each percentage. Type a tournament or player name, or collect every match by day.

#### Which tours are covered?

ATP, WTA, Challenger, ITF, juniors, team events such as the Davis Cup, and exhibitions. Choose them under **Tours**.

#### Can I get past seasons?

Yes. Add a year (Wimbledon 2019) or set **Editions per tournament** to collect several years. Detailed statistics are mostly available for recent seasons.

#### Does it include betting odds?

No. It collects results, statistics, point-by-point, form and head-to-head.

#### How much does it cost?

$1 per 1,000 matches, plus $1.50 per 1,000 for statistics or other match details and $0.50 per 1,000 for form and head-to-head. 100 matches with statistics cost $0.25. See **Pricing** above.

### Good to know

- Times are UTC.
- Live matches are a snapshot at collection time.
- Bookmaker odds are not included. For the ATP and WTA rankings, use the [ATP and WTA Tennis Rankings Scraper](https://apify.com/cleanscrape/tennis-rankings-scraper); it uses the same player IDs, so rankings and matches can be joined.
- The maximum is a limit, not a promise that so many matches exist.
- If Flashscore changes its data feed, the run stops with a clear message instead of saving empty rows.

Questions or a reproducible problem: use the Issues tab or email contact.cleanscrape@gmail.com with the run ID.

Happy with the results? A quick review on the Store page would help me a lot. If something’s off, tell me in the Issues tab and I’ll fix it. – Niko / CleanScrape

CleanScrape is independent of Flashscore, the ATP, the WTA and the ITF. Match data comes from Flashscore's public pages.

### More tools from CleanScrape

- [Casino Bonus Checker](https://apify.com/cleanscrape/casino-bonus-checker): the casino bonus each affiliate and review site shows, with promo codes, 18+ notices and affiliate IDs
- [Kick Sponsor Tracker](https://apify.com/cleanscrape/kick-sponsor-tracker): which brands Kick streamers promote, with promo codes, affiliate links and broadcast hours
- [Google Jobs Scraper](https://apify.com/cleanscrape/google-jobs-scraper): job listings with salaries, descriptions and apply links from Google Jobs
- [App Store Reviews & Google Play Reviews Scraper (Play Store)](https://apify.com/cleanscrape/app-store-reviews-scraper): reviews from both app stores in one table
- [Google Trends Scraper API for Interest Over Time](https://apify.com/cleanscrape/google-trends-scraper): search interest over time, by region, related queries and trending searches
- [Map Your Show Exhibitor List Scraper for Trade Shows](https://apify.com/cleanscrape/event-exhibitor-monitor): trade show exhibitor lists and booth changes
- [Shopify Product Reviews Scraper for Judge.me and Okendo](https://apify.com/cleanscrape/shopify-reviews-scraper): Judge.me and Okendo reviews from Shopify product links
- [Google News Scraper and RSS Feed Reader](https://apify.com/cleanscrape/google-news-scraper): headlines from Google News and publisher feeds
- [Pinterest Scraper API](https://apify.com/cleanscrape/pinterest-scraper): keyword search, public pin links and board previews; search results may lack a pin link
- [Google Hotels Scraper](https://apify.com/cleanscrape/google-hotels-scraper): hotel prices and booking offers for your dates
- [TikTok Shop Product Scraper](https://apify.com/cleanscrape/tiktok-shop-product-scraper): US TikTok Shop prices, sellers and ratings
- [Whatnot Seller Tracker](https://apify.com/cleanscrape/whatnot-seller-tracker): top Whatnot sellers per category, items sold, sales per day and followers over time
- [Whatnot Scraper](https://apify.com/cleanscrape/whatnot-scraper): Whatnot listings with prices and live shows by keyword or category
- [Meta Threads Scraper](https://apify.com/cleanscrape/threads-scraper): public Threads posts from accounts or post links
- [Likee Scraper API](https://apify.com/cleanscrape/likee-scraper): Likee videos and comments
- [Bilibili Scraper](https://apify.com/cleanscrape/bilibili-scraper): Bilibili videos, danmaku, top comments and creators, no login
- [Career Site Job Listings from Workday, Greenhouse and Lever](https://apify.com/cleanscrape/career-site-jobs-scraper): open jobs from company career pages, with salaries and new or closed jobs per company
- [Video Frame Extractor for Scene Changes and Thumbnails](https://apify.com/cleanscrape/video-frame-extractor): still images from video files at scene changes, intervals or timestamps, with contact sheets
- [Economic Calendar Scraper for Official Release Dates](https://apify.com/cleanscrape/economic-calendar-api): CPI, jobs, GDP and central bank decision dates from the official agencies of five economies, with UTC times
- [Audio Transcription and Speech to Text for Podcasts](https://apify.com/cleanscrape/podcast-transcription): podcast feeds, Apple Podcasts links and audio files to text with timestamps and subtitles
- [Google Flights Scraper and Fare Tracker](https://apify.com/cleanscrape/google-flights-scraper): flight prices, airlines, stops and times for your routes and dates, with only new flights or lower prices on a schedule
- [Google Shopping Scraper and Price Tracker](https://apify.com/cleanscrape/google-shopping-scraper): product prices, stores and ratings from Google Shopping, each store’s price for a product, and price changes on a schedule
- [Telegram Channel Messages Scraper with Comments](https://apify.com/cleanscrape/telegram-channel-messages-scraper): public Telegram channel posts with views, reactions, media and comments, exact subscriber counts, and only new posts on a schedule

# Actor input Schema

## `targets` (type: `array`):

Type a name or paste a Flashscore link, one per line. For example: Wimbledon 2025, Sinner, Swiatek 2026, US Open women, or a match link. Leave the list empty to collect matches by day instead.

## `dayRange` (type: `string`):

All matches Flashscore lists for these days (UTC), from 7 days back to 7 days ahead.

## `maxResults` (type: `integer`):

Total for the run, shared evenly across the lines in your list. Start small to check the output. Fewer matches may be available.

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

Used for days, and to choose the draws when you type a tournament name (Wimbledon gives the ATP and WTA singles). A pasted tournament link or a player is not limited by tour.

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

Used for days, players and tournament names. Typing "doubles" with a tournament name also works.

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

Match links are always returned. Each saved match shows its exact status.

## `startDate` (type: `string`):

Your own first day, used with Days on Custom dates or left on Yesterday. Within the last 7 days or the next 7 days (UTC).

## `endDate` (type: `string`):

Optional. Defaults to the start date.

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

For a tournament without a year: 1 is the latest edition, 5 adds the four before it. With a year (Wimbledon 2024) only that edition is collected.

## `includeQualifying` (type: `boolean`):

Qualifying matches are marked in the Qualifying and Round columns.

## `since` (type: `string`):

For players. Only matches on or after this date. A year after the name (Sinner 2025) also works. Without either, the newest matches come first until Maximum matches is reached.

## `statistics` (type: `boolean`):

Aces, double faults, serve and return points with counts, break points and games; for bigger events also winners, unforced errors, net points, serve speed and distance. Per match and per set.

## `setDetails` (type: `boolean`):

Duration of each set and the match, tiebreak points and the chair umpire.

## `pointByPoint` (type: `boolean`):

Every game with server and hold or break, and each point with break, set and match points marked. Best exported as JSON.

## `formAndH2H` (type: `boolean`):

Head-to-head record and each player's latest matches, overall and on this surface. Most useful before a match.

## `formMatches` (type: `integer`):

How many recent matches to include for each player when Form and head-to-head is on.

## Actor input object example

```json
{
  "targets": [
    "Wimbledon 2025"
  ],
  "dayRange": "yesterday",
  "maxResults": 20,
  "tours": [
    "atp",
    "wta"
  ],
  "matchType": "singles",
  "statuses": [
    "finished"
  ],
  "seasons": 1,
  "includeQualifying": true,
  "statistics": true,
  "setDetails": true,
  "pointByPoint": false,
  "formAndH2H": false,
  "formMatches": 10
}
```

# Actor output Schema

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

No description

## `report` (type: `string`):

No description

## `summary` (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 = {
    "targets": [
        "Wimbledon 2025"
    ],
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("cleanscrape/tennis-match-data").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 = {
    "targets": ["Wimbledon 2025"],
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("cleanscrape/tennis-match-data").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 '{
  "targets": [
    "Wimbledon 2025"
  ],
  "maxResults": 20
}' |
apify call cleanscrape/tennis-match-data --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cleanscrape/tennis-match-data"
        }
    }
}
```

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/KE3jGjlJIfaRgbYn7/builds/NkGOzyKj0VJtzgRZ4/openapi.json
