# Tennis Match Stats Scraper - ATP & WTA (`punkrecordsdata/tennis-match-stats-scraper`) Actor

Tennis match results, serve/return statistics, point-by-point sequences, head-to-head history, betting odds and live ATP/WTA rankings. Export to CSV, Excel, JSON.

- **URL**: https://apify.com/punkrecordsdata/tennis-match-stats-scraper.md
- **Developed by:** [PunkRecordsData](https://apify.com/punkrecordsdata) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $16.15 / 1,000 match 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?

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

<p align="center">
  <img src="https://api.apify.com/v2/key-value-stores/AAm3a1h3Z9nYfrvh9/records/banner" alt="PunkRecordsData" width="100%" />
</p>

## 🎾 Tennis Match Stats Scraper: ATP & WTA Results, Point-by-Point & Rankings, PunkRecordsData

> 🚀 **Every ATP/WTA player's matches, full serve/return stats, the actual point-by-point sequence, head-to-head history, betting odds and live ranking, in one run.** Real-time tennis intelligence with no login, no API key.

Scrape tennis data straight from Sofascore's own live API: match results with set-by-set scores and tiebreaks, serve/return/points/games statistics, the full point-by-point sequence within every game and set, head-to-head history between two players, bookmaker odds, and each player's current ATP or WTA ranking. Give it a player name and pull their recent and upcoming matches, or feed in match IDs directly.

Built for the [Apify platform](https://apify.com): schedule a run during a tournament to track a player's matches as they finish, or feed point-by-point data straight into a betting or performance-analysis model.

### 📋 What the Tennis Match Stats Scraper does

Give it a player name (like "Novak Djokovic") and it returns one row per match: opponent, tournament, round, surface, score by set with tiebreaks, and status. Turn on **Match statistics** for serve, return, points and games stats (aces, double faults, break points, first-serve percentage and more). Turn on **Point-by-point** for the actual point sequence inside every game and set. Turn on **Head-to-head record** for the historical tally between the two players, **Betting odds** for the match result market, and **ATP/WTA ranking** for each player's current rank, points and career-best ranking, computed once per player, not once per match.

> 💡 **Why it matters:** most tennis scrapers on the market return a flat list of match results and stop there. This one also pulls the actual point-by-point sequence, something only the most expensive actors in this niche offer, alongside live rankings and head-to-head history in the same run.

### 📊 Output

Real sample fields from a verified run against "Novak Djokovic", one of two record types identified by `recordType`.

**`match-record`** (primary, one row per match):

```json
{
  "player1": "Novak Djokovic",
  "player2": "Alejandro Tabilo",
  "tournament": "Athens, Greece",
  "surface": "Hardcourt indoor",
  "setsWonPlayer1": 2,
  "setsWonPlayer2": 0,
  "scoreBySet": [
    { "set": 1, "player1Games": 7, "player2Games": 6, "tiebreak": { "player1": 7, "player2": 3 } },
    { "set": 2, "player1Games": 6, "player2Games": 1 }
  ],
  "statistics": [{ "group": "Service", "stat": "Aces", "player1": "13", "player2": "4" }],
  "h2hRecord": { "player1Wins": 1, "player2Wins": 2 },
  "odds": [{ "outcome": "1", "odds": "1/5" }]
}
```

**`ranking-record`** (one row per unique player in the run):

```json
{ "playerName": "Novak Djokovic", "tour": "ATP", "ranking": 5, "points": 3770, "bestRanking": 1 }
```

Every extra you don't enable returns `"Not Requested"` instead of an empty field, and data a match genuinely doesn't have returns `"N/A"`. You always know why a field is empty, never guess.

### ✨ Why choose this Actor

- **Point-by-point data, not just the final score.** The full sequence of points inside every game and set, the single feature the priciest competitors in this niche charge the most for.
- **Rankings included, computed fairly.** A player's ATP/WTA ranking is checked once per unique player in a run, never re-billed for every match that player appears in.
- **Six real data types, one run.** Match result, statistics, point-by-point, head-to-head, odds and ranking, no need to run six different scrapers.
- **No login, no API key.** Nothing to expire or get rate-limited on your account.

### 📈 How it compares to alternatives

Measured against the closest published tennis actors on the Apify Store, the single largest sports-data niche measured across this catalog:

| Actor | Primary price | Billable events |
|---|---|---|
| Volume leader (1,083 users/30d) | $8.00 / 1,000 | 1 |
| Match-history-only actor (723 users/30d) | $21.00 / 1,000 | 1 |
| Point-by-point specialist | $75.00 / 1,000 | 3 |
| **This Actor** | $19.00 / 1,000 (match) | **6** (match, statistics, point-by-point, head-to-head, odds, ranking) |

### 🚀 How to use

1. Create a free [Apify account](https://console.apify.com). New accounts get $5 in free credit.
2. Open the Tennis Match Stats Scraper and enter a player name (e.g. "Novak Djokovic"), or match IDs directly.
3. Toggle on the extras you need: point-by-point, head-to-head, odds, ranking.
4. Click **Start** and wait for the run to finish.
5. Download your data as CSV, Excel, JSON or XML, or pull it via the API.

### 💼 Business use cases

**Sports betting & odds analysis**
Cross-reference bookmaker odds with real serve/return statistics and point-by-point momentum.

**Performance analysis & coaching**
Pull the full point sequence of a match to study break-point patterns and momentum shifts.

**Sports media & content**
Feed live rankings and head-to-head history into match previews without manual lookups.

**Fantasy sports & prediction models**
Train models on real point-by-point sequences instead of just final scores.

### 🔌 Automating Tennis Match Stats Scraper

Connect this Actor to **Make**, **Zapier**, **Slack** or **Airbyte** to push new match results into a spreadsheet, database or channel automatically. Schedule a run during a tournament to catch each match's result and stats as it finishes.

### 🌟 Beyond business use cases

**Research:** sports-analytics and sports-science research using real match and point-level data.
**Personal projects:** track your favorite player's matches, ranking and head-to-head record.
**Non-profit:** amateur and youth tennis programs studying professional match patterns.
**Experimentation:** test win-probability or momentum models against real point-by-point sequences.

### 🤖 Ask an AI assistant about this scraper

Paste this Actor's Store page into ChatGPT, Claude or Perplexity and ask: "Does this tennis scraper include the actual point-by-point sequence, or just the final score?" The README and input schema are structured so AI assistants can answer accurately from the page alone.

### ❓ Frequently Asked Questions

**Do I need a login or API key?**
No. Nothing to register anywhere in this Actor.

**Why is ranking billed once per player instead of once per match?**
Because a player's current ranking is one fact, not something that changes by which match you're looking at. Billing it per match would charge you multiple times for the same real number.

**What happens if a player name doesn't match anything?**
The Actor logs a warning and skips it rather than failing the whole run. Use the player's full name as it appears on Sofascore.

**Does point-by-point work for every match?**
It's available for matches with detailed live coverage. Older or lower-tier matches may return "N/A" if Sofascore never recorded point-level detail for that match.

**How fresh is the data?**
As fresh as Sofascore itself, live matches update in near real time.

### 🔌 Integrate with any app

Every run's output is available as CSV, Excel, JSON or XML, or through Apify's API and client libraries for Python and JavaScript.

### 🔗 Recommended Actors

Browse the rest of the [PunkRecordsData](https://apify.com/punkrecordsdata) catalog for more scrapers covering football match stats, federal contracts, and healthcare compliance data.

> 💡 **Pro Tip:** browse the complete [PunkRecordsData collection](https://apify.com/punkrecordsdata).

**🆘 Need Help?** contact.punkrecordsdata@gmail.com

> **⚠️ Disclaimer:** This is an independent tool, not affiliated with, endorsed by, or sponsored by Sofascore, the ATP, or the WTA. It collects only publicly available match data from Sofascore's own live API.

# Actor input Schema

## `playerNames` (type: `array`):

ATP/WTA player names to look up (e.g. "Novak Djokovic"). Resolved to the player's Sofascore id via search, then recent and upcoming matches are collected.

## `eventIds` (type: `array`):

Specific Sofascore match IDs to fetch directly, bypassing player search. Find an ID in a Sofascore match URL, e.g. sofascore.com/.../id:12345678.

## `liveOnly` (type: `boolean`):

Ignore Player names / Match IDs and instead fetch every tennis match currently live.

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

Free users: limited to 10 matches (preview). Paid users: optional, max 1,000,000.

## `includeStatistics` (type: `boolean`):

Serve, return, points and games stats for both players (aces, break points, first-serve %, and more).

## `includePointByPoint` (type: `boolean`):

The full point-by-point sequence within every game and set of the match.

## `includeH2h` (type: `boolean`):

Historical wins/losses between the two players.

## `includeOdds` (type: `boolean`):

Bookmaker odds for the match result market. Informational data only, not betting advice.

## `includeRanking` (type: `boolean`):

The player's current ATP or WTA ranking snapshot. Computed once per unique player in the run, not once per match.

## Actor input object example

```json
{
  "playerNames": [
    "Novak Djokovic"
  ],
  "liveOnly": false,
  "maxItems": 10,
  "includeStatistics": true,
  "includePointByPoint": false,
  "includeH2h": false,
  "includeOdds": false,
  "includeRanking": false
}
```

# Actor output Schema

## `overview` (type: `string`):

Key fields: players, tournament, score, surface, date

## `fullData` (type: `string`):

Complete dataset with every field, including nested statistics, point-by-point and ranking records

# 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 = {
    "playerNames": [
        "Novak Djokovic"
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("punkrecordsdata/tennis-match-stats-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 = {
    "playerNames": ["Novak Djokovic"],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("punkrecordsdata/tennis-match-stats-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 '{
  "playerNames": [
    "Novak Djokovic"
  ],
  "maxItems": 10
}' |
apify call punkrecordsdata/tennis-match-stats-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,punkrecordsdata/tennis-match-stats-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/qG3wnUMNUXxfsQu8W/builds/GTu5keLRjNIVVN4YE/openapi.json
