Tennis Abstract Player Match History Scraper avatar

Tennis Abstract Player Match History Scraper

Pricing

Pay per event

Go to Apify Store
Tennis Abstract Player Match History Scraper

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

Stas Persiianenko

Maintained by Community

Actor 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:

  1. opens the lightweight public player data surface;
  2. identifies the correct ATP or WTA history endpoint;
  3. extracts recent or full historical match rows as needed;
  4. applies date and court-surface filters;
  5. deduplicates matches with stable IDs;
  6. 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 maxItems limit.
  • 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?

FieldMeaning
matchIdStable hash identifying this player's match row
playerSlugTennis Abstract player identifier
playerNameReadable name derived from the player slug
playerUrlPublic Tennis Abstract player URL
dateMatch date in YYYY-MM-DD format
tournamentTournament name
tournamentUrlTournament source URL when safely available
surfaceHard, Clay, Grass, Carpet, or another published value
roundTournament round such as F, SF, QF, R16, or R32
playerRankPlayer ranking at the tournament, or null
opponentOpponent name
opponentSlugOpponent player identifier when available or inferred
opponentUrlPublic opponent page URL when available
opponentRankOpponent ranking at the tournament, or null
opponentCountryPublished three-letter country code, or null
outcomewin, loss, or null when the source is ambiguous
scorePublished match score, including RET or W/O markers
dominanceRatioTennis Abstract dominance ratio, or a value derived from published points
aceRateAces divided by serve points, expressed from 0 to 1
doubleFaultRateDouble faults divided by serve points, from 0 to 1
firstServeInFirst serves in, from 0 to 1
firstServeWonFirst-serve points won, from 0 to 1
secondServeWonSecond-serve points won, from 0 to 1
breakPointsSavedSaved/opportunities text such as 10/13
durationMatch duration such as 2:20, or null
sourceUrlExact fragment or history surface used
scrapedAtUTC 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

  1. Open the Actor in Apify Console.
  2. Add one or more player slugs, such as NovakDjokovic or IgaSwiatek.
  3. Alternatively, paste public Tennis Abstract player URLs into Player URLs.
  4. Set Maximum matches to bound the dataset and run cost.
  5. Optionally select court surfaces and an inclusive date range.
  6. Leave proxy disabled unless your network is challenged by Tennis Abstract.
  7. Click Start.
  8. 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

InputTypeDefaultDescription
playerSlugsstring arraynonePlayer identifiers from the page p= parameter
startUrlsrequest listnonePublic Tennis Abstract player or classic-player URLs
maxItemsinteger100Global row limit from 1 to 10,000
surfacesstring arrayallAny of Hard, Clay, Grass, or Carpet
fromDatestringnoneInclusive earliest match date, YYYY-MM-DD
toDatestringnoneInclusive latest match date, YYYY-MM-DD
proxyConfigurationobjectdirectOptional 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 matchesActor charge
10start fee + 10 × FREE-tier item price
100start fee + 100 × FREE-tier item price
1,000start 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 ApifyClient
client = 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().items
print(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 matchId plus playerSlug as 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 null statistics 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 sourceUrl and scrapedAt for 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.

  • 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.