Tennis Abstract Scraper | ATP/WTA Match History, Stats, Elo
Pricing
from $1.39 / 1,000 matches
Tennis Abstract Scraper | ATP/WTA Match History, Stats, Elo
Scrape complete ATP and WTA career match logs from Tennis Abstract. Every match a player has played, with aces, double faults, break points, dominance ratio, Elo ratings by surface, head-to-head records and shot-by-shot point-by-point detail. 112 fields per match, back to 1995.
Pricing
from $1.39 / 1,000 matches
Rating
0.0
(0)
Developer
Zen Studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
10 hours ago
Last modified
Categories
Share
Tennis Abstract Scraper | ATP & WTA Career Match Stats, Elo Ratings, Point by Point
From Zen Studio, creators of PrizePicks Player Props, Underdog Player Props and DraftKings Odds, with 50,000+ combined lifetime runs across those three.
Why choose this actor?
- Every player, one run. Type names the way you would say them, as many as you need. An owner-measured run returned the complete careers of Roger Federer, Novak Djokovic and Serena Williams, 4,136 matches in 5.5 seconds.
- Only the matches you need. Filter by surface, level, round, result, opponent, opponent ranking and date before anything is saved. Billing is per match delivered, $1.99 per 1,000.
- The numbers behind every result. Aces, double faults, break points, dominance ratio and more rates for both players, plus shot-by-shot point by point on charted matches and today's rankings and Elo lists.
Try three careers
Open the actor's input page, switch to JSON and paste this to collect every Grand Slam final of all three players, about 100 matches:
{"players": ["Roger Federer","Novak Djokovic","Serena Williams"],"levels": ["G"],"rounds": ["F"]}
Remove levels and rounds to take each whole career. Switch on includePointByPoint for shot-by-shot detail on the matches that carry it, charged at $19.99 per 1,000 of those matches.
Related actors
| Zen Studio Sports Data • Scores, stats and odds across every major source | |||
|
🎾 Tennis Abstract ➤ You are here |
Live scores and odds |
13 sports, live |
Lines, props, SGP |
Key Features
|
📋 112 fields per match Result, score, sets, surface, round, both players, stats and rates |
👤 ATP and WTA together One input, both tours, active and retired players alike |
|
📅 Three decades deep Serena Williams goes back to 1995, Federer to 1996 |
🎯 Head to head in one field Name an opponent and get only those meetings, with full stats |
|
📊 Rankings and Elo lists Around 2,000 ranked players per tour, plus the Elo leaderboard |
⚙ Filters that do the work Surface, level, round, opponent, date range, opponent ranking |
How to Scrape Tennis Abstract Player Data
Basic: one player's full career
{"players": ["Novak Djokovic"]}
Names work as you would write them. Short forms without spaces work too, and so does a pasted player page link.
Clay-court finals only
{"players": ["Rafael Nadal"],"surfaces": ["clay"],"rounds": ["F"]}
A head-to-head record
{"players": ["Iga Swiatek"],"opponent": "Aryna Sabalenka"}
Grand Slam results with point-by-point detail
{"players": ["Carlos Alcaraz"],"levels": ["G"],"includePointByPoint": true}
Today's rankings and Elo ratings, no player needed
{"rankings": "both","elo": "both"}
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
players | array | one of these is required | Player names, short forms, or player page links |
surfaces | array | all | hard, clay, grass, carpet |
levels | array | all | Tournament level: G Grand Slam, M Masters, A ATP Tour, F Tour Finals, O Olympics, D Davis Cup or Billie Jean King Cup, C Challenger, S Futures, Q Qualifying, J Juniors, P WTA Premier, PM WTA Premier Mandatory, I WTA International, W WTA Tour, T1 to T4 WTA Tiers |
rounds | array | all | Round codes such as F, SF, QF, R16 |
results | array | both | win or loss |
opponent | string | none | Keep only matches against this player |
maxOpponentRank | integer | none | Keep only matches against opponents ranked this high or better |
fromDate | string | none | Earliest match date, YYYY-MM-DD |
toDate | string | none | Latest match date, YYYY-MM-DD |
includePointByPoint | boolean | false | Add shot-by-shot detail for matches that have it |
rankings | string | none | atp, wta or both |
elo | string | none | atp, wta or both |
maxResults | integer | none | Stop after this many records |
At least one of players, rankings or elo must be set. Filters are optional and combine freely.
What Data Can You Extract from Tennis Abstract?
Every match record carries:
- The match: date, tournament, level and its name, surface, round and its name, best of, score, set-by-set games and tiebreak points, duration in minutes, winner, loser, retirement and walkover flags.
- Both players: name, ranking, seed, entry route, country, handedness, backhand, height, birthdate and age at the match.
- Serve and return counts: aces, double faults, serve points, first serves in, first and second serve points won, service games, break points saved and faced, mirrored for the opponent.
- Derived rates: ace rate, double fault rate, first serve in, first and second serve points won, serve and return points won, total points won, dominance ratio, hold, break, break point conversion.
- The player's profile: current rank, peak rank and the dates it was held, Elo rating and Elo rank, doubles rank, and identifiers for cross-referencing.
Output Example
{"record_type": "match","match_id": "2026-540-601","date": "2026-06-29","tournament": "Wimbledon","level": "G","level_name": "Grand Slam","surface": "Grass","round": "SF","round_name": "Semifinal","best_of": 5,"score": "6-4 6-4 6-4","result": "loss","winner": "Jannik Sinner","loser": "Novak Djokovic","duration_minutes": 140,"player_name": "Novak Djokovic","player_slug": "NovakDjokovic","player_tour": "atp","player_rank": 8,"player_seed": 7,"opponent_name": "Jannik Sinner","opponent_slug": "JannikSinner","opponent_id": "206173","opponent_rank": 1,"opponent_seed": 1,"opponent_country": "ITA","opponent_hand": "R","opponent_hand_name": "Right","opponent_backhand": "2","opponent_backhand_name": "Two-handed","opponent_height_cm": 191,"opponent_birthdate": "2001-08-16","opponent_age": 24.9,"sets": [{ "player_games": 4, "opponent_games": 6, "tiebreak_loser_points": null, "is_tiebreak": false, "is_match_tiebreak": false, "is_complete": true },{ "player_games": 4, "opponent_games": 6, "tiebreak_loser_points": null, "is_tiebreak": false, "is_match_tiebreak": false, "is_complete": true },{ "player_games": 4, "opponent_games": 6, "tiebreak_loser_points": null, "is_tiebreak": false, "is_match_tiebreak": false, "is_complete": true }],"sets_won": 0,"sets_lost": 3,"games_won": 12,"games_lost": 18,"tiebreaks_played": 0,"tiebreaks_won": 0,"is_retirement": false,"is_walkover": false,"is_default": false,"is_completed": true,"aces": 8,"double_faults": 3,"serve_points": 105,"first_serves_in": 67,"first_serve_points_won": 51,"second_serve_points_won": 13,"service_games": 15,"break_points_saved": 10,"break_points_faced": 13,"opponent_aces": 16,"opponent_double_faults": 0,"opponent_serve_points": 79,"opponent_first_serves_in": 51,"opponent_first_serve_points_won": 45,"opponent_second_serve_points_won": 17,"opponent_service_games": 15,"opponent_break_points_saved": 1,"opponent_break_points_faced": 1,"break_points_converted": 0,"service_games_held": 12,"ace_rate": 0.0762,"double_fault_rate": 0.0286,"first_serve_in_pct": 0.6381,"first_serve_points_won_pct": 0.7612,"second_serve_points_won_pct": 0.3421,"serve_points_won_pct": 0.6095,"return_points_won_pct": 0.2152,"total_points_won_pct": 0.4402,"dominance_ratio": 0.5511,"hold_pct": 0.8,"break_pct": 0.0,"break_points_conversion_pct": 0.0,"has_statistics": true,"has_point_by_point": true,"player_country": "SRB","player_birthdate": "1987-05-22","player_height_cm": 188,"player_hand": "R","player_hand_name": "Right","player_backhand": "2","player_backhand_name": "Two-handed","player_current_rank": 5,"player_peak_rank": 1,"player_peak_rank_first": "2011-07-04","player_peak_rank_last": "2024-05-27","player_elo_rating": 2061,"player_elo_rank": 4,"player_is_active": true,"points": [{"point_number": 1,"server": "Novak Djokovic","sets_score": "0-0","games_score": "0-0","points_score": "0-0","description": "1st serve down the T; backhand slice return crosscourt (very deep); forehand down the middle; backhand crosscourt; forehand down the line (net), unforced error. (7-shot rally)","rally_length": 7,"outcome": "unforced error"}],"shot_statistics": {"serve_basics": [{ "category": "1st serve", "Pts": "67", "Won---%": "51 (76%)", "Aces---%": "8 (12%)" }],"rally_outcomes": [{ "category": "1-3 shots", "Pts": "104", "Wnrs----%": "22 (21%)", "UFE-----%": "14 (13%)" }]},"source_url": "https://www.tennisabstract.com/cgi-bin/player-classic.cgi?p=NovakDjokovic"}
points and shot_statistics appear when includePointByPoint is on and the match has that detail. The shot_statistics object holds 15 tables covering serve placement, return outcomes, key points, rally outcomes, shot types, shot direction and net play.
An Elo record looks like this:
{"record_type": "elo","tour": "atp","elo_rank": 1,"player_name": "Jannik Sinner","player_slug": "JannikSinner","age": 24.8,"elo_rating": 2321.9,"hard_elo_rank": 1,"hard_elo_rating": 2259.3,"clay_elo_rank": 1,"clay_elo_rating": 2211.8,"grass_elo_rank": 1,"grass_elo_rating": 2125.5,"peak_elo_rating": 2339.8,"peak_elo_month": "2026-05","tour_rank": 1,"log_diff": 0}
Advanced Usage
Ready-made configurations for tennis betting models, surface-specific form analysis, head-to-head previews, historical research and machine-learning datasets.
Surface form for a betting model
{"players": ["Carlos Alcaraz", "Jannik Sinner", "Alexander Zverev"],"surfaces": ["clay"],"fromDate": "2023-01-01"}
Every row carries the serve and return counts, so hold and break rates on the surface come straight out of the dataset.
Results against top-10 opposition
{"players": ["Coco Gauff"],"maxOpponentRank": 10}
A training set with the ratings attached
{"players": ["Novak Djokovic", "Rafael Nadal", "Roger Federer"],"elo": "atp"}
One rivalry, every meeting, shot by shot
{"players": ["Novak Djokovic"],"opponent": "Rafael Nadal","includePointByPoint": true}
Grand Slam finals across a career
{"players": ["Serena Williams"],"levels": ["G"],"rounds": ["F"]}
Pricing: Pay Per Event
$1.99 per 1,000 matches at the base rate, with volume discounts on higher Apify plans.
| Event | Per 1,000 |
|---|---|
| Match | $1.99 |
| Player loaded | $4.99 |
| Ranking or Elo entry | $0.49 |
| Point-by-point match | $19.99 |
A player's complete career is billed per match, so a deep career costs a few dollars and a filtered slice costs cents. Point-by-point is charged only for matches that actually carry it, never for the ones that do not.
FAQ
What is Tennis Abstract? Tennis Abstract is a long-running tennis analytics site built around a match database that reaches back to the 1990s. It publishes career logs for ATP and WTA players with the serve and return counts behind each result, Elo ratings including surface-specific ones, and shot-by-shot charting contributed by volunteers. This Actor turns any player's page into structured rows.
How far back does the data go? It depends on the player and the tier they played. Serena Williams reaches 1995 and Roger Federer 1996. Depth is deeper for main-tour players than for lower tiers, so the honest answer is that the Actor returns everything on record for the player you ask for.
Does it cover WTA as well as ATP? Yes, both, in the same run and the same output shape. You do not need to say which tour a player is on.
Can I get a head-to-head record?
Yes. Set opponent to the other player and you get only those meetings, each with full statistics, which is a head-to-head with the numbers attached rather than just a win count.
How complete are the match statistics? Around 90% of a main-tour career carries serve and return counts. Older matches and lower-tier events often do not, and those fields come back as null rather than zero so you can tell the difference between an unrecorded match and a genuine nil.
What is dominance ratio? The share of return points won divided by the share of serve points lost. Above 1.0 means a player was doing more damage on return than they conceded on serve. It is calculated here with the same formula the source itself displays.
Which matches have point-by-point detail?
A large share of main-tour matches from recent decades, because the charting is volunteer work rather than an automated feed. Every record tells you up front with has_point_by_point, so you can filter before switching the option on.
Do I need an account or cookies? No. Enter player names and run it.
How do I export the data?
JSON, CSV, Excel, XML or HTML from the run's Storage tab, or through the Apify API. JSON keeps the nested sets, points and shot_statistics fields intact; CSV flattens them.
Can I get live scores and odds too? Not here, this Actor is historical. Flashscore Tennis covers live scores, fixtures, bookmaker odds and today's matches, and joins to this one on player name.
Is it legal to scrape Tennis Abstract data? The Actor collects publicly available pages only. You are responsible for complying with the source's terms and with data protection law, including GDPR and CCPA. Player names and birthdates are personal data; treat them accordingly.
Why did my run return no players?
The name did not match. Use the player's name as it appears on their page, for example Novak Djokovic. The run log names any player it could not resolve.
More Zen Studio scrapers for sports betting
🏟️ Sportsbook odds
Action Network
FanDuel
DraftKings
BetMGM
Bet365
🎯 Daily fantasy & player props
Player Props Aggregator
PrizePicks
Underdog Fantasy
Sleeper
DraftKings Pick6
Bet365
🎾 Live scores & match data
Flashscore
Support
- Bugs: Issues tab
- Features: Issues tab
Legal Compliance
Extracts publicly available data. Users must comply with the source's terms and data protection regulations (GDPR, CCPA).
Complete ATP and WTA career match logs with serve and return statistics, Elo ratings by surface, and shot-by-shot point-by-point detail.

