# TennisExplorer Scraper - Results, Odds, Fixtures & Rankings (`scrapesage/tennisexplorer-scraper`) Actor

Scrape TennisExplorer: ATP and WTA match results by date with set scores, tiebreaks, winners and bookmaker odds; upcoming matches with head-to-head counts and odds; ATP and WTA rankings with points and movement. Any date, any tour. No login, no browser. JSON, CSV, Excel.

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

## Pricing

from $0.83 / 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?

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

## TennisExplorer Scraper - Results, Odds, Fixtures & Rankings

> **Disclaimer:** This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by TennisExplorer or any of its subsidiaries. All trademarks mentioned are the property of their respective owners. "TennisExplorer" is referenced only to describe the publicly available website this Actor collects data from.

Scrape **tennis match results, upcoming fixtures and rankings from TennisExplorer.com** - the site tennis bettors and analysts use for day-by-day ATP and WTA data. Pick a date range and get every finished match with **set-by-set scores, tiebreak points, the winner and the bookmaker odds** the match closed at; pick upcoming days and get the schedule with **head-to-head counts and pre-match odds**; or pull the current **ATP or WTA ranking table** with points and weekly movement. No login, no API key, no browser - JSON, CSV or Excel.

> **Why this actor exists (demand):** the TennisExplorer niche on Apify draws **~180 monthly users**, almost all on one results-only actor with no reviews. This one covers results, fixtures **and** rankings, keeps the odds and tiebreaks the site shows, and adds implied probabilities - the inputs a betting model or a tennis-stats project actually needs.

### Modes

| Mode | What you get | Record |
|---|---|---|
| **results** | Finished matches for each day in the range: tournament (with country and tour), players (with seeds and profile URLs), sets won, per-set games with tiebreak points, winner, closing odds for both players, implied probabilities, match-detail URL | `match` (`status: finished`) |
| **upcoming** | Scheduled matches for each day: time, tournament, players, head-to-head counts, pre-match odds and implied probabilities, match-detail URL | `match` (`status: upcoming`) |
| **rankings** | The current ATP or WTA ranking table: rank, weekly movement, player, country, points, ranking date, profile URL | `ranking` |

Tour filter for results / upcoming: **ATP + WTA singles**, ATP singles only, or WTA singles only.

### Input

Results for a week of the US Open, both tours:

```json
{ "mode": "results", "tour": "all", "dateFrom": "2026-08-25", "dateTo": "2026-08-31", "maxResults": 2000 }
```

Tomorrow's WTA schedule with odds and H2H:

```json
{ "mode": "upcoming", "tour": "wta-single", "dateFrom": "2026-09-03" }
```

Top 200 ATP ranking:

```json
{ "mode": "rankings", "rankingTour": "atp", "maxResults": 200 }
```

- **Date from / Date to** - `YYYY-MM-DD`, inclusive, up to 60 days per run. Results default to yesterday, upcoming to today.
- **Max records** - caps matches or ranking rows across the run.

Leave everything empty and the run returns a small free sample (yesterday's results, all tours, up to 100 matches).

### Example output (`match`)

```json
{
  "type": "match",
  "status": "finished",
  "date": "2026-08-31",
  "time": "23:45",
  "tournament": "US Open",
  "tournamentUrl": "https://www.tennisexplorer.com/us-open/2026/atp-men/",
  "tournamentCountry": "US",
  "tour": "ATP",
  "player1": "Khachanov K.",
  "player1Url": "https://www.tennisexplorer.com/player/khachanov/",
  "player1Seed": null,
  "player2": "Burruchaga R.",
  "player2Url": "https://www.tennisexplorer.com/player/burruchaga/",
  "setsPlayer1": 3,
  "setsPlayer2": 0,
  "score": "6-3 6-0 6-1",
  "sets": [{ "set": 1, "player1": 6, "player2": 3, "tiebreak": null }, { "set": 2, "player1": 6, "player2": 0, "tiebreak": null }, { "set": 3, "player1": 6, "player2": 1, "tiebreak": null }],
  "winner": "Khachanov K.",
  "oddsPlayer1": 1.25,
  "oddsPlayer2": 3.98,
  "impliedProbPlayer1": 80,
  "impliedProbPlayer2": 25.13,
  "matchId": "3307389",
  "matchUrl": "https://www.tennisexplorer.com/match-detail/?id=3307389",
  "scrapedAt": "2026-09-02T06:00:00.000Z"
}
```

`ranking` records: `rank`, `move`, `player`, `playerUrl`, `country`, `points`, `tour`, `rankingDate`.

### Match details (opt-in)

Turn on **Add match details** (results / upcoming) to open each match's detail page and enrich the record with:

- **Head-to-head** - the career H2H record (`h2hPlayer1Wins` / `h2hPlayer2Wins`) plus `h2hMeetings[]`: every prior meeting with year, tournament, surface, round, score and winner.
- **Player comparison** - `player1Detail` / `player2Detail`: singles ranking, birthdate, height, weight and playing hand.
- **All bookmaker odds** - `oddsBookmakers[]` (up to 30 books with each player's price), `bestOddsPlayer1/2` and `avgOddsPlayer1/2` across the market, `oddsBookmakerCount`, and `oddsMarketCounts` (how many Home-Away, Over-Under, Asian-Handicap and Correct-Score lines the match has). The listing-level `oddsPlayer1/2` remain the single closing price.

One extra request per match, so cap it with **Max match details** (default 200). *TennisExplorer does not publish per-point serve statistics (aces, first-serve %), so those are not available from any lane.*

### Use cases

- **Betting models** - closing odds and implied probabilities alongside the actual result, day by day, for both tours.
- **Tennis analytics** - set scores with tiebreak points for surface, form and momentum studies; ranking movement over time when scheduled weekly.
- **Fixture feeds** - tomorrow's schedule with H2H and odds for previews, newsletters and apps.
- **Player tracking** - filter the dataset by `player1` / `player2` or profile URL to follow specific players through a tournament.

### Notes and limits

- Doubles are not included (TennisExplorer lays doubles out differently); Challenger, ITF and qualifying singles that TennisExplorer lists on the day pages are included.
- Odds are the two decimal prices TennisExplorer shows per match (home / away); a missing odd is an honest `null`.
- Match statistics (aces, serve percentages) live on each match-detail page and are not part of this version.

### Use with AI assistants (MCP)

This actor is available through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp), so assistants like Claude can call it as a tool - "give me yesterday's WTA results with the odds" - and get structured data back.

### Agent-ready: autonomous payments (x402 & Skyfire)

This actor is **agent-ready** - AI agents can discover it, run it, and **pay for it autonomously**, with no Apify account and no human in the loop. It uses [pay-per-event](https://docs.apify.com/platform/actors/publishing/monetize/pay-per-event) pricing and [limited permissions](https://docs.apify.com/platform/actors/development/permissions), so it qualifies for Apify's agentic-payment standards:

- **[x402](https://docs.apify.com/platform/integrations/x402)** - an open, HTTP-native payment protocol. Agents pay per run in USDC on the Base network directly through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) - no account, no API key.
- **[Skyfire](https://docs.apify.com/platform/integrations/skyfire)** - agent-to-service payments for fully autonomous AI-agent workflows.

Building an AI agent, MCP tool, or autonomous data pipeline? This scraper is ready to plug in and pay as it goes.

### Pricing

Pay-per-event, tiered by volume: match records from **$0.0015** (down to **$0.00083** on the Gold tier and above) and ranking rows from **$0.001** (down to **$0.00055**). You pay only for records actually returned; days with no matches and blocked requests cost nothing.

Every run finishes with a clear status message; empty runs never crash and never bill.

***

*TennisExplorer is a trademark of its owner. This actor is an independent tool that reads publicly available pages and is not affiliated with or endorsed by TennisExplorer.*

### Automate & schedule

Run this Actor on autopilot and pull results into your own stack:

- **[Apify API](https://docs.apify.com/api/v2)** - start runs, fetch datasets and manage schedules over REST.
- **[apify-client for JavaScript](https://docs.apify.com/api/client/js/)** and **[apify-client for Python](https://docs.apify.com/api/client/python/)** - official SDKs.
- **[Schedules](https://docs.apify.com/platform/schedules)** - run it hourly, daily or weekly and keep your dataset current.
- **[Webhooks](https://docs.apify.com/platform/integrations/webhooks)** - trigger downstream actions (CRM import, Slack alert, email sequence) the moment a run finishes.

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'MY_APIFY_TOKEN' });

const run = await client.actor('scrapesage/tennisexplorer-scraper').call({
    "mode": "results",
    "tour": "all",
    "maxResults": 500
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} records`);
```

### Integrate with any app

Connect the dataset to thousands of apps - no code required:

- **[Make](https://docs.apify.com/platform/integrations/make)** - multi-step automation scenarios.
- **[Zapier](https://docs.apify.com/platform/integrations/zapier)** - push new records straight into your CRM or spreadsheet.
- **[Slack](https://docs.apify.com/platform/integrations/slack)** - get notified when a scheduled run finds something new.
- **[Google Drive / Sheets](https://docs.apify.com/platform/integrations/drive)** - auto-export every run to a spreadsheet.
- **[Airbyte](https://docs.apify.com/platform/integrations/airbyte)** - pipe results into your data warehouse.
- **[GitHub](https://docs.apify.com/platform/integrations/github)** - trigger runs from commits or releases.

### FAQ

**How is this Actor billed?** Pay-per-event: you pay only for the results it delivers, with no monthly rental and no start fee. The per-event price is shown on the Pricing tab.

**Can I schedule it and get results automatically?** Yes - create a [Schedule](https://docs.apify.com/platform/schedules) and add a [webhook](https://docs.apify.com/platform/integrations/webhooks) or an integration (Google Sheets, Slack, Make, Zapier) to push each run's dataset wherever you need it.

**Which export formats are available?** Every run's dataset can be downloaded as JSON, CSV, Excel (XLSX), XML, HTML or RSS from the Apify Console or the API.

**Can I run it from code or an AI agent?** Yes - through the [Apify API](https://docs.apify.com/api/v2) and client libraries, or from Claude, ChatGPT and other assistants via the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp).

**Is it legal to scrape TennisExplorer?** This Actor collects publicly available data only. You are responsible for using the output in compliance with applicable laws (including data-protection law where personal data is involved) and the source's terms. See the **Disclaimer** below.

**Is this an official TennisExplorer tool?** No. It is an independent, third-party Actor with no affiliation to, endorsement by or sponsorship from TennisExplorer. See the **Disclaimer** below.

### Disclaimer

**This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by TennisExplorer or any of its subsidiaries. All trademarks mentioned are the property of their respective owners.**

"TennisExplorer" and any related marks are the property of their respective owners and are used here only in a descriptive, nominative sense - to identify the publicly accessible website from which this Actor collects data. This Actor is not an official TennisExplorer product, is not authorised or certified by TennisExplorer, and does not distribute TennisExplorer software. It collects only publicly available information; you are responsible for ensuring your use of that data complies with applicable laws, regulations and the terms of the source website.

### Need help?

Open an issue on the Actor's **Issues** tab, or visit the [Apify help center](https://help.apify.com/). Feature requests are welcome - this Actor is actively maintained.

# Actor input Schema

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

<b>results</b> - finished matches for each day in the date range with set scores, tiebreaks, winner and odds. <b>upcoming</b> - scheduled matches for each day with head-to-head counts and odds. <b>rankings</b> - the current ATP or WTA ranking table.

## `tour` (type: `string`):

Which singles tour to include. Doubles are not covered (TennisExplorer lays them out differently).

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

First day to scrape (results / upcoming). Defaults to yesterday for results and today for upcoming.

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

Last day to scrape, inclusive (max 60 days per run). Defaults to the same day as <b>Date from</b>.

## `rankingTour` (type: `string`):

Which ranking to scrape in <b>rankings</b> mode.

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

For results / upcoming, open each match's detail page and add: head-to-head record and prior meetings, a player comparison (ranking, birthdate, height, weight, hand), and odds from every bookmaker (best / average home-away prices plus the count of Over-Under, Asian-Handicap and Correct-Score markets). One extra request per match, so it is slower - cap it with the next field.

## `maxMatchDetails` (type: `integer`):

When 'Add match details' is on, stop enriching after this many matches (the rest still ship with their listing-level fields).

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

Maximum number of match records (results / upcoming) or ranking rows to return. Ranking pages hold 100 players each.

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

TennisExplorer serves full pages to Apify datacenter proxies, so the default is enough.

## Actor input object example

```json
{
  "mode": "results",
  "tour": "all",
  "rankingTour": "atp",
  "includeMatchDetails": false,
  "maxMatchDetails": 200,
  "maxResults": 500,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All scraped TennisExplorer records as JSON items in the default 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": "results",
    "tour": "all",
    "rankingTour": "atp",
    "maxMatchDetails": 200,
    "maxResults": 500,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapesage/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",
    "tour": "all",
    "rankingTour": "atp",
    "maxMatchDetails": 200,
    "maxResults": 500,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapesage/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",
  "tour": "all",
  "rankingTour": "atp",
  "maxMatchDetails": 200,
  "maxResults": 500,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapesage/tennisexplorer-scraper --silent --output-dataset

```

## MCP server setup

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