Tennis Scores, Stats & Rankings Scraper
Pricing
from $2.50 / 1,000 tennis matches
Tennis Scores, Stats & Rankings Scraper
Tennis results, fixtures and live scores for ATP, WTA, Challenger and ITF with set-by-set scores, optional match stats (aces, double faults, serve %, break points), surface and seeds, plus ATP/WTA singles and doubles rankings in one clean schema.
Pricing
from $2.50 / 1,000 tennis matches
Rating
0.0
(0)
Developer
Juddroid
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Tennis results, fixtures, live scores, match stats and ATP/WTA rankings in one clean, ready-to-model dataset, from $2.50 per 1,000 matches.
What does Tennis Scores, Stats & Rankings Scraper do?
It collects tennis match data for the ATP Tour, the WTA Tour (including WTA 125 events), the Grand Slams, the ATP Challenger Tour and the ITF World Tennis Tour. Pick results, fixtures, live scores or rankings (or several at once), choose the tours and dates, and every match comes back in the same schema: tournament, category, surface, round, start time, players with country, seed and ranking, set-by-set score with tiebreak points, the winner, and the source links. Switch on match stats to add aces, double faults, first-serve percentage, break points saved and converted, winners, unforced errors and match and set durations. Rankings mode returns the ATP and WTA singles and doubles ranking lists with points, movement and tournaments played.
Why use it
- One schema for every tour. ATP, WTA, Challenger and ITF matches have the same fields, so a Grand Slam final and an M15 first round go into the same table, model or database without per-source code.
- Cheap per match, nothing charged for noise. $2.50 per 1,000 matches and $0.50 per 1,000 ranking rows. Filtered-out matches, status messages and the optional match stats cost nothing extra.
- Built for models. Set scores are numbers (
{ "p1": 7, "p2": 6, "tiebreak": { "p1": 7, "p2": 4 } }), stats come as{ pct, won, total }, statuses are normalized (finished,retired,walkover,cancelled,live,scheduled), times are UTC ISO. - Robust sources with fallbacks. ATP/WTA come from ESPN's public scoreboard JSON and switch to the Flashscore data feed for any day ESPN fails. Rankings fall back between the official WTA API, Flashscore and ESPN. A failed source produces a free status row that says what is missing instead of a silent gap.
- Monitoring that only charges for news. Only new results remembers delivered results between runs, so a schedule every 30 minutes returns (and charges) only matches that finished since the last run.
- Always returns something useful. If the dates you ask for have no completed matches (off-season, rest days), the Actor returns the most recent completed match day and tells you so.
Source coverage
| Data | ATP | WTA | Challenger | ITF | Where it comes from |
|---|---|---|---|---|---|
| Results | Any date, years back | Any date, including WTA 125 | Last 7 days | Last 7 days | ESPN public scoreboard (ATP/WTA), Flashscore public data feed (Challenger/ITF, and ATP/WTA when ESPN fails) |
| Fixtures | As soon as the order of play is out | Same | Next 7 days | Next 7 days | Same as results |
| Live scores (with the current game score) | Yes | Yes | Yes | Yes | ESPN + Flashscore |
| Round, seed, entry (Q/WC/LL), court | Yes | Yes | Qualifying flag only | Qualifying flag only | ESPN |
| Surface and indoor flag | Matches in the last/next 7 days | Same | Yes | Yes | Flashscore |
| Match stats and durations | Last 7 days | Last 7 days | Last 7 days, where published | Where published | Flashscore |
| Player's current singles ranking | Top 150 | Top 150 | No | No | ESPN |
| Singles rankings | Any depth, dated, with tournaments played | Any depth, dated, with tournaments played | No | No | Flashscore (ATP, names checked against ESPN), official WTA API (WTA); ESPN top 150 as a fallback |
| Doubles rankings | Any depth | Any depth | No | No | Flashscore (ATP), official WTA API (WTA) |
| Betting odds | Not included | Not included | Not included | Not included | Not freely available in these sources |
What data you get
Three row types: match (charged), ranking (charged) and status (free).
Match rows (type: "match")
| Field | Description |
|---|---|
matchId, source | ID at the source (espn or flashscore). sourceIds holds both IDs when the match was found in both |
tour, gender, matchType | atp, wta, challenger, itf or mixed (Grand Slam mixed doubles); men/women/mixed; singles/doubles |
tournament | { id, name, category, surface, indoor, location, startDate, endDate }. Category is Grand Slam, ATP Tour, WTA Tour, WTA 125, ATP Challenger, ITF Men or ITF Women |
round, court | For example Quarterfinal, Qualifying 1st Round, Stadium Court |
startAt, startTimeConfirmed | UTC start time; false when the time is still "TBD" |
status, statusDetail | scheduled, live, finished, retired, walkover or cancelled, plus the source's wording (for example 2nd Set) |
player1, player2 | { id, name, country, countryName, seed, entry, ranking }. Doubles teams also have members[] |
winner, winnerSide | Winner's name and 1 or 2 |
score | { sets: [{ p1, p2, tiebreak?, durationMinutes? }], setsWon: { p1, p2 }, summary, currentGame? } from player1's point of view, e.g. 6-7(7-9) 7-6(7-2) 6-3 |
resultNote | The source's one-line result, e.g. (1) Alexander Zverev (GER) bt (9) Alex de Minaur (AUS) 6-4 6-4 |
durationMinutes, stats | With Include match stats: match duration and { player1: {...}, player2: {...} } with aces, doubleFaults, firstServePercentage, firstServePointsWon, secondServePointsWon, breakPointsSaved, breakPointsConverted, firstReturnPointsWon, secondReturnPointsWon, winners, unforcedErrors, netPointsWon, servicePointsWon, returnPointsWon, totalPointsWon, serviceGamesWon, returnGamesWon, totalGamesWon and more where published |
url, flashscoreUrl, scrapedAt | Source page links and the scrape time |
Ranking rows (type: "ranking")
| Field | Description |
|---|---|
tour, rankingsType | atp or wta; singles or doubles |
rank, previousRank, movement | Movement is positive when the player moved up |
player, playerId, country, countryName | Player name and the source's player ID |
points, tournamentsPlayed | Ranking points and the number of counted tournaments |
rankingDate, source | The ranking week (YYYY-MM-DD) and the source list (flashscore, wtatennis or espn) |
Status rows (type: "status", never charged) carry level (info or error) and a message, for example "No live matches right now", an off-season fallback notice or a source error.
How to use
- Open the Actor and pick What to scrape: results, fixtures, live, rankings or a combination.
- Pick the Tours. ATP and WTA include the Grand Slams.
- Optionally set From date / To date (YYYY-MM-DD,
yesterday,today,-3,+2). Empty dates mean yesterday for results and today plus two days for fixtures. - Optionally narrow it down by Tournament name or Player names, and switch on Include doubles or Include match stats.
- Click Start. Matches appear in the Matches view and rankings in the Rankings view; export them as JSON, CSV or Excel, or read them through the API.
Example input: last three days of ATP and Challenger results with stats for two players, plus the ATP top 100.
{"mode": ["results", "rankings"],"tours": ["atp", "challenger"],"dateFrom": "-3","dateTo": "yesterday","players": ["Sinner", "Alexander Zverev"],"includeMatchStats": true,"rankingsType": "singles","maxRankingRows": 100}
Monitoring input for a schedule every 30 minutes (returns only results that are new since the previous run):
{"mode": ["results"],"tours": ["atp", "wta"],"dateFrom": "-1","dateTo": "today","onlyNewResults": true,"stateStoreName": "tennis-results-monitor"}
Output example
A completed ATP match with stats (stats trimmed):
{"type": "match","matchId": "184954","source": "espn","tour": "atp","gender": "men","matchType": "singles","tournament": {"id": "315-2026","name": "Rolex Shanghai Masters","category": "ATP Tour","surface": "hard","indoor": false,"location": "Shanghai, China PR","startDate": "2026-10-05","endDate": "2026-10-18"},"round": "Quarterfinal","court": "Stadium Court","startAt": "2026-10-15T10:10:00.000Z","startTimeConfirmed": true,"status": "finished","statusDetail": "Final","player1": { "id": "2375", "name": "Alexander Zverev", "country": "GER", "countryName": "Germany", "seed": 1, "entry": null, "ranking": 2 },"player2": { "id": "2651", "name": "Alex de Minaur", "country": "AUS", "countryName": "Australia", "seed": 9, "entry": null, "ranking": 9 },"winner": "Alexander Zverev","winnerSide": 1,"score": {"sets": [{ "p1": 6, "p2": 4, "durationMinutes": 37 },{ "p1": 6, "p2": 4, "durationMinutes": 41 }],"setsWon": { "p1": 2, "p2": 0 },"summary": "6-4 6-4"},"resultNote": "(1) Alexander Zverev (GER) bt (9) Alex de Minaur (AUS) 6-4 6-4","durationMinutes": 78,"stats": {"player1": {"aces": 10,"doubleFaults": 1,"firstServePercentage": 80,"firstServePointsWon": { "pct": 80, "won": 35, "total": 44 },"breakPointsSaved": { "pct": 100, "won": 5, "total": 5 },"breakPointsConverted": { "pct": 100, "won": 2, "total": 2 },"winners": 24,"unforcedErrors": 15},"player2": {"aces": 6,"doubleFaults": 2,"firstServePercentage": 63,"firstServePointsWon": { "pct": 81, "won": 25, "total": 31 }}},"url": "https://www.espn.com/tennis/scoreboard/tournament/_/eventId/315-2026/competitionType/1","sourceIds": { "espn": "184954", "flashscore": "ERN0r0Qp" },"scrapedAt": "2026-10-16T12:56:49.062Z","flashscoreUrl": "https://www.flashscore.com/match/tennis/zverev-alexander-dGbUhw9m/de-minaur-alex-EZgZ9Xfh/?mid=ERN0r0Qp"}
A Challenger fixture (names are abbreviated as published for Challenger and ITF):
{"type": "match","matchId": "GI66xd7s","source": "flashscore","tour": "challenger","tournament": { "id": "pKRztbdD", "name": "Olbia", "category": "ATP Challenger", "surface": "hard", "indoor": false, "location": "Olbia, Italy" },"startAt": "2026-10-16T13:00:00.000Z","status": "scheduled","player1": { "id": "pGBaKGOn", "name": "Fearnley J.", "countryName": "United Kingdom" },"player2": { "id": "hMR2isnm", "name": "Mrva M.", "countryName": "Czech Republic" },"url": "https://www.flashscore.com/match/tennis/fearnley-jacob-pGBaKGOn/mrva-maxim-hMR2isnm/?mid=GI66xd7s"}
A ranking row:
{"type": "ranking","tour": "wta","rankingsType": "singles","rank": 3,"previousRank": 5,"movement": 2,"player": "Mirra Andreeva","playerId": "331809","country": "RUS","points": 6371,"tournamentsPlayed": 20,"rankingDate": "2026-10-12","source": "wtatennis"}
Pricing
Pay per event, no subscription:
| Event | Price |
|---|---|
match: one match row (result, fixture or live) | $0.0025 ($2.50 per 1,000) |
ranking-row: one ranking place | $0.0005 ($0.50 per 1,000) |
Worked examples:
- Daily ATP + WTA singles results (about 20 to 60 matches a day in season): about $0.05 to $0.15 a day, $1.50 to $4.50 a month.
- A full week of everything (ATP, WTA, Challenger and ITF, singles and doubles, about 1,900 matches in our test week): about $4.85.
- Top 100 ATP and WTA singles rankings once a week: 200 rows = $0.10 a week.
- The default example run (yesterday's ATP/WTA results plus the top 20 of both rankings, 21 matches + 40 ranking rows in our test): about $0.07.
Not charged: status rows, matches removed by your tour, date, player or tournament filters, results skipped by Only new results, and match stats or durations (they are part of the match row). Max match rows and the run's maximum charge setting cap your spend; the Actor stops cleanly when the limit is reached.
Integrations and scheduling
- Schedules: run it every few minutes for live scores, every 30 to 60 minutes with Only new results for result feeds, or weekly on Monday for rankings.
- Webhooks: trigger your pipeline, a Slack message or a model retrain when a run succeeds.
- API and SDKs: start runs and read the dataset from any language; use
?view=overviewfor the flat match table and?view=rankingsfor rankings. - Integrations: send rows to Google Sheets, Airtable, BigQuery, S3, Zapier or Make with Apify integrations.
- AI agents and MCP: the Actor works as a tool through the Apify MCP server, so an assistant can answer "how did Swiatek do this week?" with fresh data.
FAQ and limitations
How fresh are live scores? Each run is a snapshot taken at run time, including the current game score. Schedule it every 1 to 5 minutes for a live feed. Live mode can return zero matches when nothing is being played; you then get a free status row.
Why do Challenger and ITF matches have abbreviated names and no round or seed? Those tours come from Flashscore's data feed, which publishes names as "Surname I." and does not include rounds or seeds in its daily list. ATP and WTA matches use full names, rounds and seeds from ESPN.
How far back can I go? ATP and WTA results go back years (31 days per run). Challenger and ITF matches, match stats and the surface are available for the last 7 and next 7 days only, so schedule the Actor if you want to build a history.
Which ranking list is used? ATP rankings come from Flashscore's dated list (names and country codes checked against ESPN), WTA rankings from the official WTA rankings API. rankingDate is the ranking week. The per-match player.ranking is ESPN's current list (top 150), which can differ by a few places from the dated official list while a tournament is running.
Are odds or head-to-head records included? Odds are not included because they are not freely available in these sources. For head-to-head records, filter results by both players' names over the dates you need.
Are times local? No. All dates and times are UTC, and the date filters use UTC days.
What happens when a source is down? ESPN days that fail are filled from Flashscore; rankings fall back to another list; anything still missing is explained in a free status row. If a source starts blocking requests, the Actor stops asking it for the rest of the run instead of hammering it.
Responsible use. The Actor collects factual sports data only: names, dates, scores, statistics and ranking numbers from publicly available, unauthenticated feeds. It does not collect logos, photos, flags, editorial articles or any data behind a login, and it keeps request rates low. It is not affiliated with or endorsed by the ATP, WTA, ITF, ESPN or Flashscore. You are responsible for using the data in line with the sources' terms and the law that applies to you, for example when you republish data commercially. Use the data for analysis and entertainment; it is not betting advice.