# TennisExplorer Scraper — ATP/WTA Results, Fixtures & Odds (`hipersoft/tennisexplorer-scraper`) Actor

Scrape tennis match results and upcoming fixtures from TennisExplorer: ATP, WTA, Challenger and ITF singles and doubles with set scores, tiebreaks, winners, betting odds, H2H, rankings, surface and round. Any date range. Export CSV, JSON or Excel.

- **URL**: https://apify.com/hipersoft/tennisexplorer-scraper.md
- **Developed by:** [hiper soft](https://apify.com/hipersoft) (community)
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.003 / match

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

## TennisExplorer Scraper — ATP & WTA Results, Fixtures, Odds and H2H

**TennisExplorer Scraper** exports **tennis match results and upcoming fixtures** from TennisExplorer for any date or date range. It covers **ATP, WTA, Challenger and ITF** singles and doubles. Each match row includes **set-by-set scores with tiebreaks, the winner, closing betting odds, tournament, country and start time**. You can also turn on match details to add **round, surface, player rankings, age, height, playing hand, head-to-head record and odds from every bookmaker, both opening and current**. Export to **CSV, Excel, JSON or XML** for betting models, backtesting, tennis analytics and fantasy sports.

### What does TennisExplorer Scraper do?

TennisExplorer Scraper turns TennisExplorer's daily results and match pages into a clean, flat tennis dataset:

- 🎾 **Match results** for any day, week, month or season, covering every ATP, WTA, Challenger and ITF match listed.
- 📅 **Upcoming matches** with scheduled start times, pre-match odds and how many times the players have met.
- 🧮 **Set scores with tiebreaks**, sets won and the winner, ready for modelling.
- 💰 **Betting odds**: the main home/away odds on every row, plus per-bookmaker opening and current odds with match details.
- 🧑 **Player details**: full name, singles and doubles ranking, birthdate, height, weight, playing hand and year turned pro.
- 🔁 **Head-to-head record** and **round and surface** for every match.
- 🔎 **Filters** by tournament name and player name.

### What tennis data can you scrape?

| Match data | With match details |
|---|---|
| Match ID and link | Round (final, semifinal, quarterfinal…) |
| Date, local time and UTC start time | Surface (hard, clay, grass, indoors) |
| Match type (men's/women's singles/doubles) | Full player names |
| Tournament name, link and country | Singles and doubles rankings |
| Player 1 and player 2, profile links and seeds | Birthdate, height, weight |
| Winner | Plays (right/left) and turned pro |
| Sets won by each player | Head-to-head wins for each player |
| Set-by-set games and tiebreak points | Odds from every bookmaker: opening and current |
| Score string, e.g. `7-6(4), 6-3` | Highlights video link |
| Home/away betting odds | |
| Status (finished, scheduled…) and H2H matches count | |

### Use cases for tennis data

- **Betting models and backtesting**: years of results with closing and opening odds for ROI, value-bet and market-movement studies.
- **Tennis analytics**: serve win rates by surface, upset frequency by ranking gap, tiebreak performance and more.
- **Fantasy tennis and tipping**: upcoming schedules with odds and head-to-head context.
- **Sports media and apps**: feed daily results and fixtures into websites, newsletters and bots.
- **Machine learning datasets**: clean labeled match outcomes with player features.
- **Odds comparison**: compare bookmaker prices for every match.

### How to scrape tennis results from TennisExplorer

1. Click **Try for free** to open TennisExplorer Scraper in Apify Console.
2. Choose **Match results** or **Upcoming matches**.
3. Select the **match types** (men's/women's, singles/doubles) and a **start date** and optional **end date**.
4. Optionally filter by **tournament** or **player**, and switch on **Include match details**.
5. Click **Start**, then download your tennis dataset as **CSV, Excel or JSON**.

### Input

#### Example input

```json
{
  "mode": "results",
  "matchTypes": ["atp-single", "wta-single"],
  "startDate": "2026-09-01",
  "endDate": "2026-09-30",
  "tournamentFilter": "",
  "playerFilter": "",
  "includeMatchDetails": true,
  "maxMatches": 0
}
```

| Field | Description |
|---|---|
| **What to scrape** | `results` (finished matches) or `upcoming` (scheduled matches). |
| **Match types** | Men's singles, women's singles, men's doubles, women's doubles. ATP/WTA lists include Challenger and ITF events. |
| **Start date / End date** | The date range. Leave the end date empty for a single day. |
| **Tournament contains** | Only matches from tournaments whose name contains this text. |
| **Player contains** | Only matches involving a player whose name contains this text. |
| **Include match details** | Adds round, surface, rankings, player bio, head-to-head record and per-bookmaker odds. |
| **Max matches** | Stop after this many matches (0 = no limit). |
| **Proxy configuration** | Optional, not needed for normal use. |

#### Scrape a whole tournament or season

Set a date range covering the event and put its name in **Tournament contains**, for example `Wimbledon` with dates from 2026-06-29 to 2026-07-12. To get a whole season, set January 1 to December 31.

#### Get tomorrow's matches every day

Choose **Upcoming matches** and leave the dates empty, then create an Apify [schedule](https://docs.apify.com/platform/schedules) to run it every morning.

### Output

#### Match result example (with match details)

```json
{
  "matchId": "3338963",
  "matchUrl": "https://www.tennisexplorer.com/match-detail/?id=3338963",
  "matchType": "atp-single",
  "date": "2026-10-04",
  "time": "13:10",
  "startTimeUtc": "2026-10-04T11:10:00.000Z",
  "status": "finished",
  "tournament": "Beijing",
  "tournamentCountry": "CN",
  "player1": "Djokovic N.",
  "player1Seed": "6",
  "player2": "Zverev A.",
  "player2Seed": "1",
  "winner": "Djokovic N.",
  "setsPlayer1": 2,
  "setsPlayer2": 1,
  "score": "4-6, 6-4, 6-4",
  "sets": [
    { "set": 1, "player1": 4, "player2": 6, "tiebreak": null },
    { "set": 2, "player1": 6, "player2": 4, "tiebreak": null },
    { "set": 3, "player1": 6, "player2": 4, "tiebreak": null }
  ],
  "oddsPlayer1": 3.16,
  "oddsPlayer2": 1.35,
  "round": "quarterfinal",
  "surface": "hard",
  "player1Details": { "fullName": "Djokovic Novak", "ranking": 11, "birthdate": "22. 5. 1987", "heightCm": 187, "weightKg": 80, "plays": "right", "turnedPro": "2003" },
  "player2Details": { "fullName": "Zverev Alexander", "ranking": 2, "birthdate": "20. 4. 1997", "heightCm": 198, "weightKg": 90, "plays": "right" },
  "h2hPlayer1Wins": 11,
  "h2hPlayer2Wins": 7,
  "bookmakerOdds": [
    { "bookmaker": "10Bet", "player1": 3.1, "player2": 1.33, "player1Opening": 2.63, "player2Opening": 1.45 }
  ]
}
```

#### Output schema

| Field | Type | Description |
|---|---|---|
| `matchId` | string | TennisExplorer match ID. |
| `matchUrl` | string (URL) | Match page. |
| `matchType` | string | `atp-single`, `wta-single`, `atp-double` or `wta-double`. |
| `date` | string | Match date (YYYY-MM-DD). |
| `time` | string | Local start time (Central European time). |
| `startTimeUtc` | string (ISO date) | Start time in UTC. |
| `status` | string | `finished`, `incomplete`, `not-played`, `scheduled` or `live-or-finished`. |
| `tournament` | string | Tournament name. |
| `tournamentUrl` | string (URL) | Tournament page. |
| `tournamentCountry` | string | Host country code. |
| `player1`, `player2` | string | Player names (doubles teams as "A / B"). |
| `player1Url`, `player2Url` | string (URL) | Player profile pages. |
| `player1Seed`, `player2Seed` | string | Seed or entry status (e.g. `1`, `Q`, `WC`). |
| `winner` | string | Winner's name. |
| `setsPlayer1`, `setsPlayer2` | integer | Sets won. |
| `score` | string | Score string with tiebreaks, e.g. `7-6(4), 6-3`. |
| `sets` | array | Per-set games for each player and tiebreak points. |
| `oddsPlayer1`, `oddsPlayer2` | number | Main decimal betting odds. |
| `h2hMatches` | integer | Previous meetings (upcoming matches). |
| `round` | string | Round (with match details). |
| `surface` | string | Court surface (with match details). |
| `player1Details`, `player2Details` | object | Full name, rankings, birthdate, height, weight, plays, turned pro. |
| `h2hPlayer1Wins`, `h2hPlayer2Wins` | integer | Head-to-head record. |
| `bookmakerOdds` | array | Per-bookmaker current and opening odds. |
| `highlightsUrl` | string (URL) | Match highlights video, if available. |
| `scrapedAt` | string (ISO date) | When the row was collected. |

### How much does it cost to scrape TennisExplorer?

TennisExplorer Scraper uses **pay-per-match** pricing: a small fixed price for each match row. Higher Apify subscription plans get an automatic discount. See the **Pricing** tab for the exact price per match. A typical day of ATP and WTA singles has about 300 to 600 matches.

### More sports data

- [Flashscore Scraper](https://apify.com/hipersoft/flashscore-scraper): live scores, results and fixtures across sports.
- [ESPN Sports Scraper](https://apify.com/hipersoft/espn-sports-scraper): scores, schedules and standings.
- [UFCStats Scraper](https://apify.com/hipersoft/ufcstats-scraper): UFC fights, fighters and stats.
- [TheSportsDB Scraper](https://apify.com/hipersoft/thesportsdb-scraper): teams, players and events.

### FAQ

**Which tournaments are covered?**
Everything TennisExplorer lists: Grand Slams, ATP and WTA tour events, Challengers, WTA 125 and ITF tournaments.

**How far back can I go?**
TennisExplorer has results going back many years. Set any start and end date.

**Are the odds opening or closing odds?**
The main `oddsPlayer1`/`oddsPlayer2` columns are TennisExplorer's headline odds for the match. With match details on, `bookmakerOdds` gives each bookmaker's current and opening odds.

**What time zone are the times in?**
`time` is shown as on TennisExplorer (Central European time), and `startTimeUtc` gives the same moment in UTC.

**Can I get doubles matches?**
Yes. Select men's or women's doubles in **Match types**.

**How do I get only one player's matches?**
Enter their surname in **Player contains**, for example `Sinner`, and set the date range.

**What formats can I export?**
CSV, Excel, JSON, XML, HTML and RSS, or read the results through the Apify API.

**Can I integrate TennisExplorer Scraper with other apps?**
TennisExplorer Scraper can be connected with almost any cloud service or web app thanks to [integrations on the Apify platform](https://apify.com/integrations). It works with [Make](https://apify.com/integrations/make), [Zapier](https://apify.com/integrations/zapier), [Slack](https://docs.apify.com/platform/integrations/slack), [Airbyte](https://docs.apify.com/platform/integrations/airbyte), [GitHub](https://docs.apify.com/platform/integrations/github), [Google Drive](https://docs.apify.com/platform/integrations/drive) and [many more](https://apify.com/integrations), plus the [Apify API](https://docs.apify.com/api/v2), JS/Python clients and MCP. Or use [webhooks](https://docs.apify.com/platform/integrations/webhooks) to trigger an action whenever a run finishes.

**Is it legal to scrape TennisExplorer?**
The scraper only collects publicly available sports results. You are responsible for using the data in line with TennisExplorer's terms.

### Related Actors

- [Flashscore Scraper](https://apify.com/hipersoft/flashscore-scraper)
- [ESPN Sports Scraper](https://apify.com/hipersoft/espn-sports-scraper)
- [TheSportsDB Scraper](https://apify.com/hipersoft/thesportsdb-scraper)

### Notes

Original clean-room implementation. Returns only public data; you are responsible for compliance with TennisExplorer's terms. Not affiliated with TennisExplorer.

# Actor input Schema

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

Finished match results or upcoming fixtures (with pre-match odds and head-to-head count).

## `matchTypes` (type: `array`):

Which tours to include. ATP and WTA lists also cover Challenger and ITF events.

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

First day to scrape (YYYY-MM-DD). Defaults to yesterday for results and today for upcoming matches.

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

Last day to scrape (YYYY-MM-DD). Leave empty to scrape only the start date. Long ranges such as a whole season are supported.

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

Only keep matches whose tournament name contains this text, e.g. Beijing, Wimbledon, Challenger.

## `playerFilter` (type: `string`):

Only keep matches where a player name contains this text, e.g. Djokovic.

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

Also open each match page to add round, surface, full player names, rankings, age, height, weight, playing hand, head-to-head record, highlights and odds from every bookmaker (current and opening). Slower.

## `maxMatches` (type: `integer`):

Stop after this many matches. 0 means no limit.

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

Not required. Use a proxy only for very large date ranges if you run into rate limits.

## Actor input object example

```json
{
  "mode": "results",
  "matchTypes": [
    "atp-single",
    "wta-single"
  ],
  "includeMatchDetails": false,
  "maxMatches": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

The results as dataset items.

# 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": "results",
    "matchTypes": [
        "atp-single",
        "wta-single"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("hipersoft/tennisexplorer-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": "results",
    "matchTypes": [
        "atp-single",
        "wta-single",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("hipersoft/tennisexplorer-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": "results",
  "matchTypes": [
    "atp-single",
    "wta-single"
  ]
}' |
apify call hipersoft/tennisexplorer-scraper --silent --output-dataset

```

## MCP server setup

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