TennisExplorer Scraper - Tennis Results, Odds & H2H
Pricing
$1.50 / 1,000 tennis matches
TennisExplorer Scraper - Tennis Results, Odds & H2H
TennisExplorer scraper for tennis results, fixtures and bookmaker odds: by date, tournament, player or match URL. Players, rankings, set scores, surface, round, head-to-head and odds per bookmaker with opening odds. Plain HTTP, no login. $1.50 per 1,000 matches.
Pricing
$1.50 / 1,000 tennis matches
Rating
0.0
(0)
Developer
Data Gleaner
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 hours ago
Last modified
Categories
Share
TennisExplorer Scraper - Tennis Results, Fixtures, Odds & Head-to-Head
Scrape tennis matches from TennisExplorer: players and rankings, tournament, round, surface, score by set, head-to-head history and the odds every bookmaker offers, with the opening odds. Pull a whole day, a tournament, a player's season or single matches, as one clean JSON record per match.
It reads the public TennisExplorer pages over plain HTTP, with no browser, no login and no account, and costs $1.50 per 1,000 matches.
What does TennisExplorer Scraper do?
It returns what you see on a TennisExplorer match page, through the Apify dataset and API as JSON, CSV or Excel. Typical uses:
- Betting models and backtests: results with pre-match odds per bookmaker, opening odds and head-to-head, by player, tournament or day.
- Odds comparison and line movement: each bookmaker's current and opening price on the same match, so you can see who is out of line.
- Daily results and fixtures feeds: schedule it every morning for yesterday's results or tomorrow's fixtures with average odds.
- Player and surface research: a player's full season with surface, round, opponent ranking and set scores.
- Sports data products and AI agents: feed tennis results and odds into a dashboard, newsletter or an LLM agent.
Input
| Field | Meaning |
|---|---|
dates | Day mode. 2026-10-12, yesterday, today, tomorrow, an offset like -3 or +2, or a range 2026-10-01..2026-10-07 (at most 31 days). Past days return results, today returns results and fixtures, future days return fixtures. |
tour | Day mode filter: all (default), atp-single, wta-single, atp-double, wta-double. |
tournamentUrls | Tournament mode, e.g. https://www.tennisexplorer.com/shanghai/2026/atp-men/. All results and upcoming matches of that edition. |
playerUrls, playerYears | Player mode, e.g. https://www.tennisexplorer.com/player/alcaraz-5ab70/ with seasons such as ["2025", "2024"] (current season if empty). Singles only. |
matchUrls | Single matches by URL or ID: https://www.tennisexplorer.com/match-detail/?id=3344135 or 3344135. |
maxMatches | Per date, tournament and player. Default 100, max 20,000. A busy day lists 150 to 250 matches. |
includeDetails | Default on: read each match page for odds per bookmaker, head-to-head and player profile. Off (day mode only): one request per day, list fields and average odds, with one request instead of one per match. |
includeAllMarkets | Adds over/under, Asian handicap and correct-score odds from every bookmaker. Off by default because records get large (about 40 KB each). |
requestDelaySecs | Pacing between request starts, default 0.4. |
proxyConfiguration | Off by default; TennisExplorer answered Apify's datacenter IPs in testing. |
With no input at all, the Actor runs a built-in example of 5 matches from yesterday's results. If you already call another tennis Actor, these input names are also accepted: startUrls (a mixed list of date, tournament, player and match URLs), days, maxItems, maxResults.
{"dates": ["yesterday"],"tour": "atp-single","maxMatches": 50}
Output
{"matchId": "3345103","url": "https://www.tennisexplorer.com/match-detail/?id=3345103","status": "finished","startDate": "2026-10-12","startTime": "14:30","startsAt": "2026-10-12T14:30:00+02:00","timezone": "Europe/Berlin","tournament": "Shanghai","tournamentUrl": "https://www.tennisexplorer.com/shanghai/2026/atp-men/","round": "3. round","surface": "hard","player1Name": "Paul Tommy","player2Name": "Vacherot Valentin","player1Ranking": 17,"player2Ranking": 14,"player1": {"name": "Paul Tommy", "url": "https://www.tennisexplorer.com/player/paul-324c3", "ranking": 17, "birthDate": "17. 5. 1997", "heightCm": 185, "weightKg": 82, "plays": "right"},"player2": {"name": "Vacherot Valentin", "url": "https://www.tennisexplorer.com/player/vacherot", "ranking": 14, "birthDate": "16. 11. 1998", "heightCm": 193, "weightKg": null, "plays": "right"},"setsWon1": 2,"setsWon2": 0,"winner": "Paul Tommy","setScores": [{"games1": 6, "games2": 4, "tiebreak": null}, {"games1": 6, "games2": 2, "tiebreak": null}],"score": "6-4, 6-2","resultNote": null,"h2h": {"player1Wins": 1, "player2Wins": 0},"h2hMatches": [{"year": 2026, "tournament": "Shanghai", "surface": "hard", "round": "3R", "score": "6-4, 6-2", "player1Name": "Paul", "player2Name": "Vacherot", "player1Sets": 2, "player2Sets": 0, "matchId": "3345103"}],"oddsAverage1": 1.6,"oddsAverage2": 2.32,"bookmakerCount": 15,"oddsHomeAway": [{"bookmaker": "10Bet", "odds1": 1.57, "odds2": 2.3, "opening1": 1.57, "opening2": 2.3},{"bookmaker": "1xBet", "odds1": 1.6, "odds2": 2.39, "opening1": 1.44, "opening2": 2.5}],"source": "date","input": "2026-10-12","scrapedAt": "2026-10-12T23:49:44Z"}
player1 is the first-listed (home) player and odds1 is the price for player 1 to win. Odds are decimal. opening1 and opening2 are the first prices TennisExplorer recorded for that bookmaker. With includeAllMarkets the record also has oddsOverUnder, oddsAsianHandicap and oddsCorrectScore lists (one row per bookmaker and line, plus an average row marked isAverage; in correct score, value is the set score and odds1 its price). The dataset has a Matches view with the main columns.
Which fields are filled
In a platform test of 100 matches from one day:
- Always filled:
matchId,url,status,startDate,tournament,player1,player2,h2h,source,input,scrapedAt. - Usually filled (about 90%):
score,setScores,surface,round. Walkovers and abandoned matches have no score. - Often filled (about 70%):
startTimeandstartsAt(lower-level events show--:--for unknown times), rankings, and the odds fields, because lower-tier ITF and Futures matches have few or no bookmaker odds (bookmakerCountis then 0 and the odds fields are null or empty). - Sometimes filled:
weightKg,heightCm,birthDate,plays(TennisExplorer lacks them for many players),resultNote.
h2h counts earlier meetings, and for a finished match it includes that match itself, because TennisExplorer lists it in the head-to-head table.
Pricing
Pay per result: $1.50 per 1,000 matches ($0.0015 per match). You pay only for matches pushed to the dataset. A day with no matches, or a match page that cannot be read, costs nothing. The run stops at your maximum charge.
Worked example: yesterday's full ATP and WTA singles results, about 150 matches, cost $0.23. A player's season of 60 matches costs $0.09. Running the same day-list every morning for 30 days at 150 matches costs about $6.75. A 10-match test costs $0.015.
Use it from the API
Run it synchronously and get the matches back as JSON. Replace <YOUR_APIFY_TOKEN> with your token.
curl -X POST "https://api.apify.com/v2/acts/datagleaner~tennisexplorer-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"dates": ["yesterday"], "tour": "atp-single", "maxMatches": 20}'
It also works from n8n, Make or Zapier through the Apify integrations, since the output is a flat JSON record per match.
Use with Python
pip install apify-client, set the APIFY_TOKEN environment variable, and run. This input returns at most 10 matches, about $0.015.
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("datagleaner/tennisexplorer-scraper").call(run_input={"playerUrls": ["https://www.tennisexplorer.com/player/alcaraz-5ab70/"],"playerYears": ["2025"],"maxMatches": 10,})for m in client.dataset(run.default_dataset_id).iterate_items():print(m["startDate"], m["player1Name"], "-", m["player2Name"], m["score"], m["oddsAverage1"], m["oddsAverage2"])
Use with JavaScript / Node.js
npm install apify-client, set APIFY_TOKEN, and run it as an ES module (.mjs).
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('datagleaner/tennisexplorer-scraper').call({dates: ['yesterday'],maxMatches: 10,});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const m of items) console.log(m.startDate, m.player1Name, '-', m.player2Name, m.score);
Use it from n8n, Make, Zapier or an AI agent
Actor ID: datagleaner/tennisexplorer-scraper
Minimal input:
{"dates": ["yesterday"], "tour": "atp-single", "maxMatches": 10}
Each tool below runs this Actor with your own Apify API token.
-
n8n: add the Apify node (
@apify/n8n-nodes-apify). On n8n Cloud you install it from the community node registry. Choose Run an Actor and get dataset, set Actor todatagleaner/tennisexplorer-scraperand paste the input above. -
Make: use the Apify app's Run an Actor module, then Get Dataset Items to read the results. Watch Actor Runs can trigger a scenario when a run finishes.
-
Zapier: use the Apify action Run Actor, then the search Fetch dataset items. The trigger Finished Actor run starts a Zap when a run ends.
-
AI agents (MCP): connect to
https://mcp.apify.com?tools=datagleaner/tennisexplorer-scraper. In Claude Code:claude mcp add --transport http apify "https://mcp.apify.com?tools=datagleaner/tennisexplorer-scraper"Then run
/mcpto sign in to Apify in your browser. Then ask in plain language, for example: "Get yesterday's ATP results with the bookmaker odds and tell me which favourites lost." An agent without the Actor preloaded can find it with Apify'ssearch-actorstool by searching "tennis odds". -
LangChain (Python):
# pip install langchain-apify, then set APIFY_TOKEN in your environmentimport jsonfrom langchain_apify import ApifyActorsTooltool = ApifyActorsTool("datagleaner/tennisexplorer-scraper")result = tool.invoke({"run_input": json.loads('{"dates": ["yesterday"], "tour": "atp-single", "maxMatches": 10}')})
Limits
- TennisExplorer data only. Rankings, odds and results are what TennisExplorer shows. There are no point-by-point or live in-play statistics. A match that is in play can show a partial result and the status
finished. - Times are in TennisExplorer's default timezone (Europe/Berlin, with daylight saving).
startsAtcarries the matching UTC offset. Unknown start times (--:--on the site) leavestartTimeandstartsAtnull. - Odds exist only where bookmakers quote them. Main-tour matches have 9 to 15 bookmakers, many lower-level matches have none. Odds are the site's displayed decimal prices at the time of the scrape, and for finished matches they are the last prices before the match.
- Player mode reads singles only, one season page per year in
playerYears. - One tournament page lists the matches of one edition and phase. Qualifying and doubles draws have their own URLs; paste those too.
- A tournament page the site itself fails to serve (it sometimes answers 500) is skipped with a log line, not billed.
- TennisExplorer can slow or refuse heavy traffic. The Actor paces its requests, retries with backoff and switches connection after repeated refusals. It never solves captchas or tries to get around them. If it is blocked it stops, keeps what it collected and says so in the status message. Lower the volume or raise
requestDelaySecs.
FAQ
Is there a TennisExplorer API? TennisExplorer does not offer a public API. This Actor works as a simple one: you call the Apify API with a date, tournament or player and it returns JSON.
How is this different from a Flashscore tennis scraper? Flashscore Actors return scores and fixtures. This one adds the bookmaker odds on each match with opening odds, the head-to-head history, and results by tournament or player for any season, not only a 14-day window around today.
Can I get live scores? No. It returns results, fixtures and pre-match odds. Use it for models and research, not in-play feeds.
Why do some matches have no odds or no time? TennisExplorer has none for lower-tier events. The record then has bookmakerCount 0 and null odds.
How fast is it? Full details take about 0.8 second per match, so 100 matches take about 80 seconds. With includeDetails off, a whole day of 200 matches comes back in one request, in a few seconds, with average odds only.
Do I need a proxy? No. It worked from Apify datacenter IPs without one.
Responsible use
This Actor reads publicly visible TennisExplorer pages without logging in. Use the data in line with TennisExplorer's terms and your local betting and data laws. The records are sports data: player names, rankings and birth dates of professional players, as the site publishes them. If you combine them with anything else about individuals, the data-protection obligations are yours. Nothing here is betting advice.