Tennis Abstract Player Match History Scraper
Pricing
Pay per event
Tennis Abstract Player Match History Scraper
Export public Tennis Abstract player match histories with opponents, rankings, surfaces, rounds, scores, match statistics, and source links.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Stas Persiianenko
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
a day ago
Last modified
Categories
Share
Export public Tennis Abstract match histories for one or many tennis players. Get clean dataset rows with dates, tournaments, surfaces, rounds, rankings, opponents, outcomes, scores, match statistics, duration, and source links.
The Actor accepts familiar player slugs such as NovakDjokovic and public Tennis Abstract player URLs.
It works for ATP and WTA player pages and applies the same filters to both input methods.
What does this Tennis Abstract scraper do?
Tennis Abstract publishes unusually rich player-centric match histories. This Actor turns those public pages into integration-ready JSON, CSV, Excel, XML, or RSS output in an Apify dataset.
For each player, it:
- opens the lightweight public player data surface;
- identifies the correct ATP or WTA history endpoint;
- extracts recent or full historical match rows as needed;
- applies date and court-surface filters;
- deduplicates matches with stable IDs;
- charges only for accepted rows and saves them to the default dataset.
Small recent-result requests avoid downloading the full career history. Older backfills automatically use the complete history surface.
Who is it for?
- Tennis analysts comparing performance by opponent, surface, or round.
- Betting researchers building their own historical features and models.
- Scouts and coaches reviewing player schedules and recent outcomes.
- Sports journalists checking tournament paths and prior meetings.
- Fantasy sports teams enriching player profiles with recent form.
- Data engineers scheduling repeatable player-history refreshes.
- Academic researchers assembling bounded public sports datasets.
This Actor exports source facts; it does not predict match winners or provide betting advice.
Why use this Actor?
- Supports both player slugs and complete Tennis Abstract player URLs.
- Handles ATP and WTA history endpoint differences automatically.
- Returns one typed record per match, not raw HTML.
- Includes source URLs and stable player-match IDs for audit and deduplication.
- Supports inclusive date filtering and surface filtering.
- Stops at a user-controlled global
maxItemslimit. - Uses a lightweight HTTP-first extraction path rather than an expensive browser by default.
- Supports optional Apify or custom proxies when the source blocks a network.
- Produces the standard Apify default dataset for API and integration compatibility.
What data can you extract?
| Field | Meaning |
|---|---|
matchId | Stable hash identifying this player's match row |
playerSlug | Tennis Abstract player identifier |
playerName | Readable name derived from the player slug |
playerUrl | Public Tennis Abstract player URL |
date | Match date in YYYY-MM-DD format |
tournament | Tournament name |
tournamentUrl | Tournament source URL when safely available |
surface | Hard, Clay, Grass, Carpet, or another published value |
round | Tournament round such as F, SF, QF, R16, or R32 |
playerRank | Player ranking at the tournament, or null |
opponent | Opponent name |
opponentSlug | Opponent player identifier when available or inferred |
opponentUrl | Public opponent page URL when available |
opponentRank | Opponent ranking at the tournament, or null |
opponentCountry | Published three-letter country code, or null |
outcome | win, loss, or null when the source is ambiguous |
score | Published match score, including RET or W/O markers |
dominanceRatio | Tennis Abstract dominance ratio, or a value derived from published points |
aceRate | Aces divided by serve points, expressed from 0 to 1 |
doubleFaultRate | Double faults divided by serve points, from 0 to 1 |
firstServeIn | First serves in, from 0 to 1 |
firstServeWon | First-serve points won, from 0 to 1 |
secondServeWon | Second-serve points won, from 0 to 1 |
breakPointsSaved | Saved/opportunities text such as 10/13 |
duration | Match duration such as 2:20, or null |
sourceUrl | Exact fragment or history surface used |
scrapedAt | UTC extraction timestamp |
Older matches may not have point-level statistics.
Those values are returned as null rather than guessed.
How to scrape Tennis Abstract player matches
- Open the Actor in Apify Console.
- Add one or more player slugs, such as
NovakDjokovicorIgaSwiatek. - Alternatively, paste public Tennis Abstract player URLs into Player URLs.
- Set Maximum matches to bound the dataset and run cost.
- Optionally select court surfaces and an inclusive date range.
- Leave proxy disabled unless your network is challenged by Tennis Abstract.
- Click Start.
- Open the default dataset and export JSON, CSV, Excel, XML, or RSS.
A small first run with 10–50 rows is useful for confirming your downstream mapping.
Input parameters
| Input | Type | Default | Description |
|---|---|---|---|
playerSlugs | string array | none | Player identifiers from the page p= parameter |
startUrls | request list | none | Public Tennis Abstract player or classic-player URLs |
maxItems | integer | 100 | Global row limit from 1 to 10,000 |
surfaces | string array | all | Any of Hard, Clay, Grass, or Carpet |
fromDate | string | none | Inclusive earliest match date, YYYY-MM-DD |
toDate | string | none | Inclusive latest match date, YYYY-MM-DD |
proxyConfiguration | object | direct | Optional Apify or custom proxy settings |
At least one slug or URL is required. Duplicate slugs across inputs are processed once. Malformed dates, unsupported domains, and invalid slugs fail clearly instead of producing an empty successful run.
Basic input example
{"playerSlugs": ["NovakDjokovic"],"maxItems": 10}
Surface and date backfill
{"playerSlugs": ["IgaSwiatek", "ArynaSabalenka"],"surfaces": ["Clay"],"fromDate": "2024-01-01","toDate": "2026-12-31","maxItems": 200}
Output example
The default dataset contains one object per accepted match:
{"matchId": "4e70c8b270707463c75d46d64383e95caf96c5cd","playerSlug": "NovakDjokovic","playerName": "Novak Djokovic","playerUrl": "https://www.tennisabstract.com/cgi-bin/player.cgi?p=NovakDjokovic","date": "2026-06-29","tournament": "Wimbledon","tournamentUrl": "https://www.tennisabstract.com/cgi-bin/tourney.cgi?t=2026-540/Wimbledon","surface": "Grass","round": "SF","playerRank": 8,"opponent": "Jannik Sinner","opponentSlug": "JannikSinner","opponentUrl": "https://www.tennisabstract.com/cgi-bin/player.cgi?p=JannikSinner","opponentRank": 1,"opponentCountry": "ITA","outcome": "loss","score": "6-4 6-4 6-4","dominanceRatio": 0.55,"aceRate": 0.076,"doubleFaultRate": 0.029,"firstServeIn": 0.638,"firstServeWon": 0.761,"secondServeWon": 0.342,"breakPointsSaved": "10/13","duration": "2:20","sourceUrl": "https://www.tennisabstract.com/jsfrags/NovakDjokovic.js","scrapedAt": "2026-07-28T06:00:00.000Z"}
Percentages are represented as decimal ratios so they are immediately usable in calculations.
For example, 0.076 means 7.6%.
How much does it cost to scrape Tennis Abstract player matches?
The Actor uses pay-per-event pricing:
- Start: $0.005 once per run.
- Match item: tiered pricing starting at $0.000041071 per accepted row on the FREE tier.
- Higher usage tiers receive lower per-row prices, down to $0.00001 on DIAMOND.
At the FREE-tier item price, illustrative Actor charges are:
| Accepted matches | Actor charge |
|---|---|
| 10 | start fee + 10 × FREE-tier item price |
| 100 | start fee + 100 × FREE-tier item price |
| 1,000 | start fee + 1,000 × FREE-tier item price |
The actual Console total can also include Apify platform compute, storage, and optional proxy usage according to your plan.
Rows rejected by filters, duplicates, and failed records are not item-charged.
Use maxItems to keep each run predictable.
Scheduling and integration workflows
Scheduled form tracker
Run daily or weekly for a shortlist of players.
Use matchId in your database to upsert rows without duplicates.
This works well for dashboards and newsroom alerts.
Surface comparison dataset
Run separate tasks for Hard, Clay, and Grass.
Join the datasets by playerSlug and compare outcomes, rankings, serve rates, or dominance ratio.
Tournament preview research
Backfill recent histories for an event's entrants. Filter downstream by common opponents, surface, date, and round.
Data warehouse pipeline
Schedule the Actor, connect a webhook or integration, and load the default dataset into BigQuery, Snowflake, PostgreSQL, Google Sheets, or an S3-compatible store.
Run with the Apify API
Replace YOUR_APIFY_TOKEN with your token.
The Actor identifier is automation-lab/tennis-abstract-player-match-history-scraper.
cURL
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~tennis-abstract-player-match-history-scraper/runs?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"playerSlugs":["NovakDjokovic"],"maxItems":25}'
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/tennis-abstract-player-match-history-scraper').call({playerSlugs: ['NovakDjokovic', 'CarlosAlcaraz'],surfaces: ['Grass'],maxItems: 100,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("automation-lab/tennis-abstract-player-match-history-scraper").call(run_input={"playerSlugs": ["IgaSwiatek"], "maxItems": 25})items = client.dataset(run["defaultDatasetId"]).list_items().itemsprint(items)
For asynchronous pipelines, start a run and poll its status or use an Apify webhook instead of waiting synchronously.
Use with Apify MCP
Claude Code
Add this Actor to Claude Code and ask your MCP client to run player-history workflows:
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/tennis-abstract-player-match-history-scraper"
Claude Desktop, Cursor, and VS Code
Claude Desktop, Cursor, and VS Code can use this MCP server configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/tennis-abstract-player-match-history-scraper"}}}
Example prompts
After setup, ask your MCP client prompts such as:
- “Use the Tennis Abstract MCP Actor to export Novak Djokovic's latest 25 matches.”
- “Get Iga Swiatek clay matches since 2024 and summarize opponents by round.”
- “Build a CSV of grass matches for Djokovic, Alcaraz, and Sinner.”
Reliability, limits, and proxies
Tennis Abstract is a third-party public source and can change without notice. The Actor validates recognizable match data so a challenge page is not mistaken for an empty result. Transient network failures and rate limits receive bounded retries with backoff.
Processing is deliberately conservative and sequential by player. This reduces source load and avoids unnecessary session churn. The global limit is 10,000 rows per run.
Direct access is the default and cheapest mode.
If your runs receive source access errors, enable Apify Proxy in proxyConfiguration.
Proxy availability, geography, and transfer costs depend on your Apify plan.
The Actor does not require a Tennis Abstract login or private cookie.
Tips for accurate analysis
- Use
matchIdplusplayerSlugas your upsert key. - Treat ranking fields as rankings at the tournament, not necessarily today's rank.
- Keep outcome and score together; retired and walkover matches can have unusual scores.
- Expect
nullstatistics for matches where the source lacks point totals. - Filter by ISO date after export if you need rolling windows not known at run time.
- Start with one player before running a large multi-player backfill.
- Store
sourceUrlandscrapedAtfor lineage and refresh decisions.
Responsible use and legality
Tennis Abstract match statistics are publicly viewable, but public access does not remove all obligations. Review Tennis Abstract's terms and applicable database, copyright, privacy, and sports-data rules for your jurisdiction and use case.
Use reasonable limits and schedules. Do not use the Actor to disrupt the source, circumvent access controls, republish protected databases wholesale, or misrepresent the data as official live scoring. You are responsible for your inputs, downstream processing, and compliance.
Troubleshooting
Why did the run say the player slug is invalid?
Use the exact value from the Tennis Abstract page's p= query parameter without spaces.
For example, use NovakDjokovic, not Novak Djokovic.
You can paste the full player URL instead.
Why did the run fail with an HTTP or challenge error?
The source may be rate-limiting the current network. Wait before retrying, reduce repeated requests, or enable an appropriate proxy configuration. Do not launch many concurrent retries.
Why are there no rows?
Confirm that the player slug exists and loosen date or surface filters. A valid no-result filter returns an empty dataset; an unrecognized page shape fails with an explicit error.
Why are some statistics null?
Older, lower-level, retired, or walkover matches may not have complete point statistics on the source. The Actor preserves those gaps rather than inventing values.
Why did I receive fewer rows than maxItems?
maxItems is an upper bound, not a guaranteed count.
The player may have fewer published matches satisfying your filters.
Related Automation Lab Actor
- Livesport Scores & Fixtures Scraper — use it for date-based live/recent scoreboards and fixtures across sports. Use this Tennis Abstract Actor when the job is player-centric historical tennis analysis.
FAQ
Does this Actor support ATP and WTA players?
Yes. It identifies the correct men's or women's complete-history endpoint from the player's public data fragment.
Can I provide multiple players?
Yes.
Combine multiple slugs and URLs in one run; duplicate slugs are removed.
The global maxItems limit applies across all players.
Does it scrape head-to-head summaries?
No. The primary product is one row per published player match. You can calculate head-to-head records downstream by grouping on opponent.
Is the data live?
The Actor returns what Tennis Abstract publishes at run time. It is not a point-by-point live score feed, and source updates may lag completed matches.
Can I export to CSV or Excel?
Yes. Open the default dataset after a run and choose JSON, CSV, Excel, XML, or RSS.
Can I run it on a schedule?
Yes. Use Apify schedules and webhooks for recurring refreshes and downstream notifications.
Is a proxy required?
No for the normal working public route. Proxy settings are optional recovery for networks challenged by the source.
Are filtered-out matches charged?
No item event is emitted for filtered, duplicate, malformed, or failed rows. The one-time start event still applies to a valid started run.