Tennis Match Data
Pricing
from $1.53 / 1,000 match rows
Tennis Match Data
ATP and WTA match results, schedules, live status, and rankings by date, with set scores, seeds, round, and court as flat rows. Tested on dates back to 2007, with no login. Filter by player, tournament, draw, and status. Refused reads are free.
Pricing
from $1.53 / 1,000 match rows
Rating
0.0
(0)
Developer
Mamba Labs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
an hour ago
Last modified
Categories
Security
Limited permissionsShare
Give a date or a date range and get ATP and WTA matches as flat rows: players, seeds, round, status, set scores, winner, and court. Set mode to rankings for the current ATP and WTA lists. You pay per row returned, and refused reads and summary rows are free.
Features
- Results, schedules, and live status. A date in the past returns results, today returns what is live and scheduled, and a date ahead returns what is scheduled so far.
- Singles and doubles. Men's, women's, and mixed draws, including qualifying rounds. Doubles rows carry both names.
- Scores you can read.
scoreis winner first, a tiebreak reads7-6(7-3),retmarks a retirement, andW/Omarks a walkover.set_scoresholds one entry per set. - Filters. Player, tournament, draw, status, and tour. A filter never charges for the rows it removes.
- A whole tournament at once. Set
whole_tournamentto yes to get every match of each tournament running on your dates. - One charge per match. A match that appears under both tours is one row.
- Restart aware. If Apify moves the run to another host, it resumes from its saved position and does not charge a match twice.
How the data is read
The actor reads the public ESPN tennis scoreboard and rankings JSON, the same calls those ESPN pages make, on the Apify default proxy pool. It uses no login, no key, no residential proxy, and no other developer's actor. A refused read is one free row with no retry on another address.
source_url on each row shows the address that was read. The data belongs to ESPN and its sources. ESPN's terms restrict scraping and compiling data sets, and you are responsible for how you use the rows.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
mode | string | matches | matches (default) reads results and schedules by date. rankings returns the current ATP and WTA lists. |
date_from | string | First UTC date as YYYY-MM-DD, or today, yesterday, or tomorrow. Needed in matches mode. | |
date_to | string | Last UTC date. Empty means the same as date from. A run reads at most 366 days. | |
tours | array | atp, wta, or both (default both). Mixed doubles appears under either. | |
draws | array | mens-singles, womens-singles, mens-doubles, womens-doubles, mixed-doubles, or the shortcuts singles and doubles. Empty means all. | |
statuses | array | final, retired, walkover, in_progress, scheduled, other, or the shortcuts finished, live, and upcoming. Empty means all. | |
tournaments | array | Keep tournaments whose name holds one of these words, such as wimbledon. | |
players | array | Keep matches with a player whose name holds one of these words, such as sinner. | |
include_qualifying | string | yes | yes (default) or no. |
whole_tournament | string | no | no (default) keeps matches played on the dates asked for. yes returns every match of each tournament running on those dates. |
max_matches | string | 500 | The most match rows in a run. Default 500. |
top_n | string | 100 | Rankings mode: rows per tour, up to 150. Default 100. |
max_charge_usd | string | Optional. The run stops before a charge that would pass this amount. Summary rows are always returned. |
Output
| Field | Type | What it holds |
|---|---|---|
row_type | string | One of: match, ranking, empty_read, source_report, run_summary. run_summary is the one free row written when the input is refused. |
match_id | string | ESPN match ID. Stable, and unique in a run. |
match_date_utc | string | Scheduled or actual start in UTC. |
match_day_utc | string | The UTC date. date_from and date_to filter on this. |
start_time_confirmed | string | true when ESPN marks the time as valid, as text. |
tournament | string | Tournament name. |
tournament_id | string | ESPN tournament and year. |
grand_slam | string | true for a major, as text. |
season | integer | Season year. |
draw | string | Draw name. |
draw_slug | string | mens-singles, womens-singles, mens-doubles, womens-doubles, or mixed-doubles. |
round | string | Round name. |
qualifying | string | true for a qualifying round, as text. |
status | string | final, retired, walkover, in_progress, scheduled, or other. |
status_detail | string | ESPN status text. |
player_1 | string | First listed player, or both names for doubles. On ranking rows, the ranked player. |
player_1_id | string | ESPN player ID, or the pair ID for doubles. |
player_1_country | string | Country as ESPN lists it. |
player_1_seed | integer | Tournament seed, when seeded. |
player_2 | string | Second listed player, or both names for doubles. |
player_2_id | string | ESPN player ID, or the pair ID for doubles. |
player_2_country | string | Country as ESPN lists it. |
player_2_seed | integer | Tournament seed, when seeded. |
winner | string | Winner, when the match has one. |
score | string | Sets, winner first. A tiebreak reads 7-6(7-3). ret marks a retirement and W/O a walkover. In a live match, first listed side first. |
set_scores | array | One entry per set, same order as score. |
result_text | string | ESPN result line. |
court | string | Court name. |
location | string | Tournament city and country. |
rank | integer | Current rank, on ranking rows. |
previous_rank | integer | Rank in the previous list, on ranking rows. |
points | integer | Ranking points, on ranking rows. |
rank_trend | string | Change, on ranking rows. |
tour_read | string | The ESPN tour endpoint that returned this row: atp or wta. |
source_url | string | The ESPN address that was read. |
reads_total | integer | Reads planned, on the summary row. |
reads_refused | integer | Reads the source refused, on the summary row. |
rows_returned | integer | Charged rows in this run, on the summary row. |
empty_reads | integer | Reads that held no fitting match, on the summary row. |
matches_without_players | integer | Listed matches with no named player, skipped, on the summary row. |
row_status | string | ok, or why this row carries no data: no_results, no_change, partial, blocked, or error. |
error_reason | string | Why the row is not ok. A refused input reads input_invalid: followed by what to fix. |
billable_events_json | string | What this row was billed as, for example {"match-row":1}. {} means free. |
scraped_at | string | When the row was written, UTC. |
Pricing
Pay per event. Mamba Labs pays the platform costs of the run. Summary rows, refused reads, and a refused input are free.
Each date is read once per tour. A read with no match that fits your filters is free for the first 2 in a run, then charged as empty-read, because a long filtered range costs money to read. Narrow date_from and date_to to pay less, and set max_charge_usd to cap a run.
| Event | Free plan | Bronze | Silver | Gold |
|---|---|---|---|---|
match-row, one match | $0.0018 | $0.00171 | $0.00162 | $0.00153 |
ranking-row, one ranked player | $0.001 | $0.00095 | $0.0009 | $0.00085 |
empty-read, one date and tour with no fitting match, after the first 2 free | $0.002 | $0.0019 | $0.0018 | $0.0017 |
apify-actor-start, once per run (one per GB of memory; the default 256 MB is one) | $0.006 | $0.006 | $0.006 | $0.006 |
Per 1,000 rows of match-row: $1.80 on the free plan, $1.53 on Gold.
Free plan cap: 1.50 USD of evaluation a month, about 833 rows. Any paid Apify plan removes the cap, and it resets on the 1st. The run stops before a charge that passes your maximum charge per run in Apify or your max_charge_usd input.
Mamba Labs pays the platform costs of your run, Apify proxy traffic included.
Usage examples
Finals day at Wimbledon 2025.
{"date_from": "2025-07-13","tournaments": ["wimbledon"],"draws": ["singles"]}
Every Sinner match in July 2025.
{"date_from": "2025-07-01","date_to": "2025-07-31","players": ["sinner"],"statuses": ["finished"]}
Today's schedule and live matches.
{"date_from": "today","statuses": ["live", "upcoming"]}
Top 50 WTA.
{"mode": "rankings","tours": ["wta"],"top_n": "50"}
Clay. Number and on or off inputs are text fields, which is what Clay sends. A list input takes a JSON list, so wrap a column in a one item list.
MCP. The Mamba Labs MCP server @mambalabsdev/mcp-tennis-match-data exposes this actor to Claude and other MCP clients.
Error handling
| Case | What you get |
|---|---|
| Missing or unreadable input | One free row, row_type run_summary, error_reason starting input_invalid: |
| ESPN refuses a read | One free source_report row with row_status blocked, and the run goes on. After 4 refusals in a row the run stops |
| No match fits your input | One free summary row with row_status no_results |
max_matches or max_charge_usd is reached | The rows so far, and a free summary row with row_status partial |
| The run is close to its timeout | The actor stops starting new work 90 seconds before the timeout and delivers what it has, with a partial summary row |
Limitations
- This reads ESPN, an unofficial source with no published contract for these addresses. ESPN can change or close them without notice, and then reads return free
source_reportrows until the actor is updated. - No point by point data, match statistics, odds, or player profile pages.
- ATP and WTA tours as ESPN lists them, with their qualifying rounds. ITF and most Challenger events are not covered.
match_day_utcis the UTC date of the start time. A late night match can fall on the next UTC date, and a time ESPN has not confirmed showsstart_time_confirmedfalse.- A date in a period ESPN holds no record for returns no rows. In testing, Wimbledon final weekends returned matches from 2007 to 2025 and none from 2003 to 2006. Coverage of smaller events in older years was not checked.
- Rankings are the current list only, up to 150 per tour.
- A scheduled match with no named player yet has no row and is counted on the summary row.
- Reading many dates takes time: about 6 seconds a date in testing.
Mamba Labs actor suite
Built by Mamba Labs.