Tennis Abstract Scraper
Pricing
from $2.40 / 1,000 matches
Tennis Abstract Scraper
Scrape ATP match results from Tennis Abstract by player: date, tournament, surface, round, score, ranks and full serve statistics for both players. One result per match.
Pricing
from $2.40 / 1,000 matches
Rating
0.0
(0)
Developer
try mersianto
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
11 days ago
Last modified
Categories
Share
Scrape ATP match results from Tennis Abstract by player. One result per match: date, tournament, surface, level, round, score, both players' ranks and full serve statistics for the player and the opponent. A whole career in one request per player. $3 per 1,000 matches on the Free plan, less on paid plans. No browser.
What you get
| Field | Type | Description |
|---|---|---|
player_name | string | Player name |
date | string | Start date of the tournament, YYYY-MM-DD |
tournament | string | Tournament name |
surface | string or null | Hard, Clay, Grass or Carpet |
level | string or null | Grand Slam, Masters 1000, ATP Tour, Tour Finals, Davis Cup, Challenger or ITF |
round | string or null | Round, for example F, SF, QF, R16 |
result | string | won or lost, from the player's side |
score | string or null | Score from the player's side |
best_of | integer or null | Best of 3 or 5 sets |
player_rank | integer or null | Player's ranking when the tournament began |
player_seed | integer or null | Player's seed |
player_entry | string or null | Entry type, for example WC (wild card) or Q (qualifier) |
opponent_name | string | Opponent name |
opponent_rank | integer or null | Opponent's ranking when the tournament began |
opponent_seed | integer or null | Opponent's seed |
opponent_entry | string or null | Opponent's entry type |
opponent_hand | string or null | Opponent's playing hand: right or left |
opponent_country | string or null | Opponent's country code |
minutes | integer or null | Match length in minutes |
aces | integer or null | Aces by the player |
opponent_aces | integer or null | Aces by the opponent |
double_faults | integer or null | Double faults by the player |
opponent_double_faults | integer or null | Double faults by the opponent |
serve_points | integer or null | Serve points played by the player |
opponent_serve_points | integer or null | Serve points played by the opponent |
first_serves_in | integer or null | First serves in by the player |
opponent_first_serves_in | integer or null | First serves in by the opponent |
first_serve_points_won | integer or null | First serve points won by the player |
opponent_first_serve_points_won | integer or null | First serve points won by the opponent |
second_serve_points_won | integer or null | Second serve points won by the player |
opponent_second_serve_points_won | integer or null | Second serve points won by the opponent |
service_games | integer or null | Service games by the player |
opponent_service_games | integer or null | Service games by the opponent |
break_points_saved | integer or null | Break points saved by the player |
opponent_break_points_saved | integer or null | Break points saved by the opponent |
break_points_faced | integer or null | Break points faced by the player |
opponent_break_points_faced | integer or null | Break points faced by the opponent |
player_url | string | Tennis Abstract page of the player |
scraped_at | string | UTC time the match was scraped, ISO 8601 |
Serve statistics are counts, so you can compute any rate: for example first serve percentage is first_serves_in / serve_points. They are empty for matches where Tennis Abstract has no statistics, mostly lower-level events.
Input
players: ATP players by name (Jannik Sinner), by Tennis Abstract player code (JannikSinner), or by Tennis Abstract player URL.sinceDate: only matches from tournaments that started on or after this date, asYYYY-MM-DD. Empty means the whole career.maxItemsPerPlayer: stop a player after this many matches, newest first. Default 1,000.maxItems: stop after this many matches in total. Default 1,000.proxyConfiguration: fallback proxy, Apify datacenter by default. Each player is fetched directly first.
{"players": ["Jannik Sinner", "Carlos Alcaraz"],"sinceDate": "2025-01-01"}
Example output
{"player_name": "Jannik Sinner","date": "2026-06-29","tournament": "Wimbledon","surface": "Grass","level": "Grand Slam","round": "F","result": "won","score": "6-7(7) 7-6(2) 6-3 6-4","best_of": 5,"player_rank": 1,"player_seed": 1,"player_entry": null,"opponent_name": "Alexander Zverev","opponent_rank": 3,"opponent_seed": 2,"opponent_entry": null,"opponent_hand": "right","opponent_country": "GER","minutes": 226,"aces": 15,"opponent_aces": 17,"double_faults": 2,"opponent_double_faults": 2,"serve_points": 136,"opponent_serve_points": 139,"first_serves_in": 87,"opponent_first_serves_in": 105,"first_serve_points_won": 70,"opponent_first_serve_points_won": 76,"second_serve_points_won": 32,"opponent_second_serve_points_won": 20,"service_games": 22,"opponent_service_games": 21,"break_points_saved": 1,"opponent_break_points_saved": 3,"break_points_faced": 1,"opponent_break_points_faced": 5,"player_url": "https://www.tennisabstract.com/cgi-bin/player-classic.cgi?p=JannikSinner","scraped_at": "2026-10-14T07:00:00+00:00"}
Pricing
Pay per result: one match event per match saved. The run stops cleanly when your maximum charge per run is reached. A full career is several hundred matches, so use sinceDate or maxItemsPerPlayer when you only need recent form.
Limitations
- ATP (men's) players only. Tennis Abstract's WTA match lists are incomplete, so WTA players are not supported yet.
- A player name must match the name Tennis Abstract uses, without accents. If a player is not found, the log says so and nothing is charged.
- Data is as up to date as Tennis Abstract, usually within a day or two of a match.
- No birth dates, heights or other personal details are included, only match results and statistics.
For AI agents
Minimal input:
{ "players": ["Jannik Sinner"], "maxItemsPerPlayer": 20 }
Each dataset item is one match with the fields listed under "What you get", seen from the requested player's side.