Tennis Abstract Scraper avatar

Tennis Abstract Scraper

Pricing

from $2.40 / 1,000 matches

Go to Apify Store
Tennis Abstract Scraper

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

try mersianto

Maintained by Community

Actor 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

FieldTypeDescription
player_namestringPlayer name
datestringStart date of the tournament, YYYY-MM-DD
tournamentstringTournament name
surfacestring or nullHard, Clay, Grass or Carpet
levelstring or nullGrand Slam, Masters 1000, ATP Tour, Tour Finals, Davis Cup, Challenger or ITF
roundstring or nullRound, for example F, SF, QF, R16
resultstringwon or lost, from the player's side
scorestring or nullScore from the player's side
best_ofinteger or nullBest of 3 or 5 sets
player_rankinteger or nullPlayer's ranking when the tournament began
player_seedinteger or nullPlayer's seed
player_entrystring or nullEntry type, for example WC (wild card) or Q (qualifier)
opponent_namestringOpponent name
opponent_rankinteger or nullOpponent's ranking when the tournament began
opponent_seedinteger or nullOpponent's seed
opponent_entrystring or nullOpponent's entry type
opponent_handstring or nullOpponent's playing hand: right or left
opponent_countrystring or nullOpponent's country code
minutesinteger or nullMatch length in minutes
acesinteger or nullAces by the player
opponent_acesinteger or nullAces by the opponent
double_faultsinteger or nullDouble faults by the player
opponent_double_faultsinteger or nullDouble faults by the opponent
serve_pointsinteger or nullServe points played by the player
opponent_serve_pointsinteger or nullServe points played by the opponent
first_serves_ininteger or nullFirst serves in by the player
opponent_first_serves_ininteger or nullFirst serves in by the opponent
first_serve_points_woninteger or nullFirst serve points won by the player
opponent_first_serve_points_woninteger or nullFirst serve points won by the opponent
second_serve_points_woninteger or nullSecond serve points won by the player
opponent_second_serve_points_woninteger or nullSecond serve points won by the opponent
service_gamesinteger or nullService games by the player
opponent_service_gamesinteger or nullService games by the opponent
break_points_savedinteger or nullBreak points saved by the player
opponent_break_points_savedinteger or nullBreak points saved by the opponent
break_points_facedinteger or nullBreak points faced by the player
opponent_break_points_facedinteger or nullBreak points faced by the opponent
player_urlstringTennis Abstract page of the player
scraped_atstringUTC 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, as YYYY-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.