Tennis Scraper — Matches, Odds History, Players, Rankings, H2H avatar

Tennis Scraper — Matches, Odds History, Players, Rankings, H2H

Pricing

from $3.00 / 1,000 results

Go to Apify Store
Tennis Scraper — Matches, Odds History, Players, Rankings, H2H

Tennis Scraper — Matches, Odds History, Players, Rankings, H2H

Scrape TennisExplorer: ATP/WTA/ITF/Challenger results and fixtures by date range with average and per-bookmaker odds (opening odds, movement history, O/U, handicap, correct score), player profiles with match history, rankings and head-to-head. No login, no browser.

Pricing

from $3.00 / 1,000 results

Rating

0.0

(0)

Developer

Banea Teodor

Banea Teodor

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Categories

Share

What does Tennis Scraper do?

Tennis Scraper extracts tennis data from TennisExplorer: match results and fixtures for any date range (ATP, WTA, Challenger, ITF, UTR — singles and doubles), bookmaker odds with opening odds and timestamped movement history from up to 15 bookmakers (match winner, Over/Under, Asian handicap, correct score), player profiles with their match history, ATP/WTA rankings (current or year-end) and head-to-head records. It reads the site's server-rendered pages — no login, no browser, no proxy needed.

Why use this Actor?

  • Odds depth nobody else sells: per-bookmaker quotes with opening odds and every price change (time + odds), plus the site's average odds on every match row.
  • Date ranges, not single days: results for past days, live/finished matches for today, fixtures for future days — up to 92 days per run.
  • Clean, typed rows: score text and set-by-set integer columns, ISO UTC start times, round and surface from the tournament page, status (finished / retired / walkover / live / scheduled), seeds, prize money.
  • Five data sets in one Actor: matches, odds, players, rankings, head-to-head — one dataset with a type column and a table view per type.
  • Honest output: a field the site does not show is null, never guessed (round is only filled when the tournament page lists that exact match).

How much does it cost?

You pay $3.00 per 1,000 rows (every row of any type is one result). Platform compute is tiny — pages are plain HTML.

RunRowsCost
One day of ATP singles results (incl. Challenger/ITF)~70–230 match rows$0.21–0.69
One week of ATP + WTA singles~1,500–2,500$4.50–7.50
One match with full bookmaker odds (includeOdds)1 match + ~250 odds rows~$0.75
Sinner, 2026 season (profile + matches)53$0.16
ATP top 100100$0.30
One head-to-head (Zverev v De Minaur)14$0.04

Odds multiply rows: a top-level match has 200–300 bookmaker lines. Use Maximum results and the tournament filter to keep odds runs to what you need.

Input

FieldModeDescriptionExample
modeallmatches, players, rankings or headToHeadmatches
dateFrom / dateTomatchesDay range (YYYY-MM-DD, London calendar day); max 92 days unless maxResults is set2026-10-10
toursmatchesatp-single, wta-single, atp-double, wta-double, all["atp-single"]
includeOddsmatchesFetch each match's detail page for per-bookmaker oddstrue
tournamentFiltermatchesKeep tournaments whose name contains this textShanghai
playersplayersSlug, profile URL or name["sinner-8b8e8", "Iga Swiatek"]
yearsplayersSeasons for the match list, or all["2026"]
includePlayerMatchesplayersAdd the player's matchestrue
rankingTour / rankingYear / maxRankrankingsATP or WTA, optional past season (year-end), depth (0 = all)atp-men, 2025, 100
pairsheadToHead"slugA vs slugB" or a /mutual/a/b/ URL["zverev-6f768 vs de-minaur"]
maxResultsallStop after this many rows (0 = no limit). The form prefills 100 so a first run costs about $0.30.100
maxConcurrency / maxRequestsPerMinuteallPoliteness (defaults 3 and 60)
{
"mode": "matches",
"dateFrom": "2026-10-10",
"dateTo": "2026-10-10",
"tours": ["atp-single"],
"includeOdds": true,
"tournamentFilter": "shanghai",
"maxResults": 100
}

Output

One dataset; the type column tells the row kind, and each type always carries the same fields. Views in the Console: Matches, Odds, Players, Rankings, Head-to-head.

match

{
"type": "match",
"matchId": "3344135",
"url": "https://www.tennisexplorer.com/match-detail/?id=3344135",
"source": "results:2026-10-10",
"tour": "atp-single",
"gender": "men",
"tournament": "Shanghai",
"tournamentUrl": "https://www.tennisexplorer.com/shanghai/2026/atp-men/",
"tournamentCountry": "China",
"tournamentCountryCode": "cn",
"tournamentYear": 2026,
"tournamentPrizeMoney": 9415725,
"tournamentPrizeCurrency": "USD",
"round": "2R",
"roundName": "2. round",
"surface": "hard",
"startTime": "2026-10-10T12:50:00.000Z",
"hasStartTime": true,
"status": "finished",
"homePlayer": "Vacherot V.",
"homePlayerSlug": "vacherot",
"homeSeed": 17,
"homeCountry": null,
"awayPlayer": "Baez S.",
"awayPlayerSlug": "baez-a8fb1",
"awaySeed": null,
"awayCountry": null,
"winner": "home",
"homeSets": 2,
"awaySets": 0,
"score": "6-4 7-6(5)",
"sets": ["6-4", "7-6(5)"],
"set1Home": 6, "set1Away": 4, "set2Home": 7, "set2Away": 6,
"set3Home": null, "set3Away": null, "set4Home": null, "set4Away": null, "set5Home": null, "set5Away": null,
"homeOdds": 1.31,
"awayOdds": 3.5,
"h2hBefore": null,
"scrapedAt": "2026-10-15T20:35:23.673Z",
"runId": "aBcD1234efGh5678"
}

odds

{
"type": "odds",
"matchId": "3344135",
"url": "https://www.tennisexplorer.com/match-detail/?id=3344135",
"homePlayer": "Vacherot V.",
"awayPlayer": "Baez S.",
"startTime": "2026-10-10T12:50:00.000Z",
"tournament": "Shanghai",
"bookmaker": "10Bet",
"market": "matchWinner",
"line": null,
"lineUnit": null,
"homeOdds": 1.3,
"awayOdds": 3.4,
"overOdds": null,
"underOdds": null,
"odds": null,
"homeOpeningOdds": 1.29,
"awayOpeningOdds": 3.5,
"homeOddsHistory": [{ "time": "2026-10-10T13:35:00.000Z", "odds": 1.3 }, { "time": "2026-10-10T03:50:00.000Z", "odds": 1.29 }],
"awayOddsHistory": [{ "time": "2026-10-10T12:36:00.000Z", "odds": 3.4 }, { "time": "2026-10-10T12:21:00.000Z", "odds": 3.5 }],
"oddsUpdatedAt": "2026-10-10T13:35:00.000Z",
"isAverage": false,
"isActive": true,
"scrapedAt": "2026-10-15T20:35:27.519Z",
"runId": "aBcD1234efGh5678"
}

For Over/Under rows the prices are in overOdds/underOdds and the line in line + lineUnit ("22.5", "games"); for correct score the price is in odds and the score in line ("2-0"). Opening odds and history always follow the page's two price columns: home/over/score first, away/under second. An odds row is unique on matchId + bookmaker + market + line + lineUnit (handicap -1.5 exists in both sets and games). Some bookmakers (bet365, Betfair, Betsson, Unibet) publish only the current price, so their opening odds and history are null. When maxResults stops the run mid-match, the last match's bookmaker table is cut at the cap.

player

{
"type": "player",
"playerSlug": "sinner-8b8e8",
"url": "https://www.tennisexplorer.com/player/sinner-8b8e8/",
"name": "Sinner Jannik",
"country": "Italy",
"sex": "man",
"birthDate": "2001-08-16",
"age": 25,
"heightCm": 188,
"weightKg": 76,
"plays": "right",
"currentRank": 1,
"highestRank": 1,
"highestRankDate": null,
"currentDoublesRank": null,
"highestDoublesRank": 34,
"careerWins": 465,
"careerLosses": 138,
"winsBySurface": { "hard": 183, "clay": 119, "grass": 40, "indoors": 111, "notSet": 12 },
"lossesBySurface": { "hard": 51, "clay": 46, "grass": 13, "indoors": 27, "notSet": 1 },
"titles": 38,
"titlesList": [{ "year": 2026, "tournament": "Wimbledon", "tournamentUrl": "https://www.tennisexplorer.com/wimbledon/2026/atp-men/", "surface": "grass", "level": "main", "prizeMoney": 74292561, "prizeCurrency": "EUR" }],
"nextMatch": null,
"injuries": [{ "dateFrom": "2025-10-05", "dateTo": "2025-10-15", "tournament": "Shanghai", "tournamentUrl": "https://www.tennisexplorer.com/shanghai/2025/atp-men/", "reason": "retired", "scoreAtRetirement": "7-6(3) 5-7 2-3" }],
"yearsAvailable": [2026, 2025, 2024],
"photoUrl": "https://www.tennisexplorer.com/res/img/player/OK7tW3bR-0zrsJ4N3.jpeg",
"scrapedAt": "2026-10-15T20:39:41.347Z",
"runId": "aBcD1234efGh5678"
}

ranking

{
"type": "ranking",
"tour": "atp-men",
"rankingDate": "2026-10-05",
"year": 2026,
"rank": 31,
"movement": -1,
"name": "Etcheverry Tomas Martin",
"playerSlug": "etcheverry-7101a",
"url": "https://www.tennisexplorer.com/player/etcheverry-7101a/",
"country": "Argentina",
"points": 1590,
"scrapedAt": "2026-10-15T20:40:08.157Z",
"runId": "aBcD1234efGh5678"
}

h2h

{
"type": "h2h",
"url": "https://www.tennisexplorer.com/mutual/zverev-6f768/de-minaur/",
"playerA": "Zverev Alexander",
"playerASlug": "zverev-6f768",
"playerB": "De Minaur Alex",
"playerBSlug": "de-minaur",
"winsA": 9,
"winsB": 4,
"meetings": 13,
"winsBySurfaceA": { "hard": 5, "clay": 2, "grass": 0, "indoors": 1, "notSet": 1 },
"winsBySurfaceB": { "hard": 2, "clay": 0, "grass": 0, "indoors": 2, "notSet": 0 },
"lastMeeting": null,
"lastMeetingYear": 2026,
"includesExhibitions": true,
"scrapedAt": "2026-10-15T20:40:20.995Z",
"runId": "aBcD1234efGh5678"
}

Each meeting is also a match row (source: "h2h:zverev-6f768-de-minaur").

Tips and tricks

  • Round and surface come from tournament pages. Day lists do not show them, so the Actor fetches each tournament page once per run (cached) and fills round only when that page lists the exact match id. Qualifying matches are looked up on the tournament's qualification page. Aggregated "Futures" lists have no tournament page — their rows keep round/surface null unless you turn on odds (the match-detail header has both).
  • Times are UTC. The site prints local times (London with daylight saving); the Actor converts them. Day boundaries follow the site's London calendar day.
  • Head-to-head includes exhibitions and team events (Laver Cup, United Cup …) — the site counts them, so winsA/winsB do too (includesExhibitions: true). Meetings carry the season only, no date or match id.
  • Retirements and walkovers are detected from the score: a decided match with an unfinished last set is retired; a decided match with no games is a walkover.
  • Players by name: a name with a space ("Jannik Sinner") is searched and the top-ranked match is used; ambiguous names are recorded in the run's ERRORS record with the candidates. Slugs (sinner-8b8e8) are exact.
  • Odds runs are big: ~600 KB per match page and 200–300 rows per top match. Combine includeOdds with tournamentFilter and maxResults.
  • No proxy needed. Keep the default pace (60 pages/minute, spread evenly) — the site is a shared resource.

Integrations

Export the dataset as JSON, CSV or Excel, or fetch it by API (/v2/datasets/{id}/items?view=matches). Connect the Actor to Google Sheets, Zapier, Make or a webhook from the Integrations tab, or schedule a daily run (e.g. dateFrom: "yesterday") to keep a results table up to date.

Disclaimer

Data belongs to TennisExplorer / Livesport s.r.o. Check the site's terms before reusing it commercially.