TennisExplorer Results
Pricing
from $5.00 / 1,000 results
TennisExplorer Results
Returns completed professional tennis match results by date from tennisexplorer.com, with tournament, players, score, sets, and closing odds.
Pricing
from $5.00 / 1,000 results
Rating
0.0
(0)
Developer
Sub Rosa
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
14 hours ago
Last modified
Categories
Share
Returns completed professional tennis match results from tennisexplorer.com, one item per match, for the days you name. Each item carries the tournament, the two competitors as the site lists them, the winner, the score in the site's notation, the games per set as numbers, and the decimal odds the site shows next to the result. The source covers ATP, WTA, Challenger, ITF, UTR and team events, singles and doubles, and the default run reads yesterday and the day before, which are complete days. Pages are fetched over plain HTTP, logged out, under the declared identity SubRosaBot/1.0, at 30 requests per minute at most. Pay per event: a fixed fee per run and a fee per match delivered.
Who uses it
- A betting model builder who pulls each morning's finished matches with the closing odds (
odds1,odds2) and the set-by-set games (sets) to grade yesterday's predictions and refit the model. - A tennis statistics site that stores results per tournament (
tournament,tournamentUrl,surface,round) and needs a stable key per match (id) to avoid double counting when the same day is fetched twice. - A sports newsletter that filters a single event (
tournament: "Chengdu") and lists the day's winners and scores (player1,player2,score) without reading a results page by hand.
Sample output
One item from a real run on 2026-09-25 (ten are in sample.json, including a doubles match, a Futures row with no tournament page, a row with no odds, and a walkover):
{"id": "3332228","date": "2026-09-25","tournament": "Chengdu","tournamentUrl": "https://www.tennisexplorer.com/chengdu/2026/atp-men/","tour": "ATP","isDoubles": false,"round": null,"surface": "Hard","player1": "Basilashvili N.","player2": "Van De Zandschulp B.","winner": 1,"score": "6-4, 7-5","sets": [{ "p1": 6, "p2": 4 },{ "p1": 7, "p2": 5 }],"odds1": 2.59,"odds2": 1.48,"matchUrl": "https://www.tennisexplorer.com/match-detail/?id=3332228","url": "https://www.tennisexplorer.com/match-detail/?id=3332228","sourceUrl": "https://www.tennisexplorer.com/results/?type=all&year=2026&month=09&day=25","scrapedAt": "2026-09-26T03:56:32.689Z"}
Data dictionary
| Field | Type | Meaning | Example |
|---|---|---|---|
id | string | The site's own match id, taken from the match-detail link. When a row has no link, a fallback built from the date, tournament and both competitors. | "3332228" |
date | string | Day the match is listed under, YYYY-MM-DD, as requested in the input. | "2026-09-25" |
tournament | string | Tournament name as shown in the results table header. | "Chengdu" |
tournamentUrl | string or null | Absolute URL of the tournament page. Doubles blocks carry ?type=double. Null for grouped blocks such as "Futures 2026" that have no page. | "https://www.tennisexplorer.com/chengdu/2026/atp-men/" |
tour | string or null | "ATP" for men's events or "WTA" for women's events, as the site classifies them. Null when the block carries no marker. | "ATP" |
isDoubles | boolean | True when the block is a doubles draw; then player1 and player2 are teams written as "A / B". | false |
round | string or null | Round code as shown on the tournament page: 1R, 2R, R16, QF, SF, F. Filled only when includeRounds is true and the match is on the tournament's main-draw page. | "R16" |
surface | string or null | Court surface as the site labels it: Hard, Clay, Grass, Indoors, Carpet. Null when the site does not show it. | "Hard" |
player1 | string | Competition name of the first-listed competitor, which on this site is the winner, as displayed. A doubles team is "Arribage T. / Olivetti A.". | "Basilashvili N." |
player2 | string | Competition name of the second-listed competitor, the loser, as displayed. | "Van De Zandschulp B." |
winner | integer or null | 1 when player1 won more sets, 2 when player2 did, null when the sets-won counts are missing or equal. | 1 |
score | string or null | Set scores in the site's notation, winner's games first, tiebreak loser's points in parentheses. Null when no games are shown (walkover). | "6-4, 7-5" |
sets | array | One { p1, p2 } object per completed set with games won. Empty when no games are shown. | [{ "p1": 6, "p2": 4 }] |
odds1 | number or null | Decimal odds shown for player1 on the results page, or null when the site shows none. | 2.59 |
odds2 | number or null | Decimal odds shown for player2, or null. | 1.48 |
matchUrl | string or null | Absolute URL of the site's match-detail page, or null when the row has no link. | "https://www.tennisexplorer.com/match-detail/?id=3332228" |
url | string | Canonical page for the record: the match-detail page, or the results page when there is none. | same as matchUrl |
sourceUrl | string | Results page the record was extracted from. | "https://www.tennisexplorer.com/results/?type=all&year=2026&month=09&day=25" |
scrapedAt | string | Extraction time, ISO 8601, UTC. | "2026-09-26T03:56:32.689Z" |
Input
| Field | Type | Default | Meaning |
|---|---|---|---|
dates | array of strings | [] | Days to fetch as YYYY-MM-DD, one results page per day. Empty means yesterday and the day before, in UTC. Malformed or impossible dates are skipped with a warning in the log. |
tournament | string | "" | Keep only matches whose tournament name contains this text, case-insensitive. "challenger" keeps every Challenger event; "Chengdu" keeps one. Empty keeps all. |
matchType | string | "all" | Which of the site's results tabs to read: all, atp-single, atp-double, wta-single, wta-double. |
includeRounds | boolean | false | Also fetch one page per tournament seen, to fill round and any surface the sidebar did not show. Adds one request per tournament block per run: two full days measured at 54 requests and 70 seconds on 2026-09-25. |
maxItems | integer | 200 | Stop after this many matches. A full day lists roughly 240 to 550 matches across all tours (measured at 241 to 549 over the eight days to 2026-09-25), so raise this to fetch whole days. The default keeps the default run short. |
proxyConfiguration | object | Apify datacenter proxy | Proxy settings. Datacenter proxies are enough; residential proxies are not needed. |
The results table lists the winner first on every row, so player1 is the winner and winner is 1 unless the site changes that convention; the field is derived from the sets-won counts rather than assumed.
Pricing
Pay per event, two events. actor-start: $0.02, once per run, covering the fixed overhead of starting the Actor and fetching the results pages. result: $0.002 per item ($2 per 1,000). A run never delivers more items than it charges for: items are pushed and charged in the same step, and the run stops cleanly when your maximum charge is reached. The prices on the Actor's page are the ones in force if they differ from this text.
Measured platform cost, from a default run on 2026-09-25: 2 requests, 0.98 MB transferred, 190 MB peak memory, 5 seconds locally. Allowing 10 seconds in a 512 MB container on the platform, at Apify's listed $0.20 per compute unit and $0.20 per GB of external transfer, that run costs about $0.0005, which is about $0.0024 per 1,000 items. The result price is about 800 times the measured platform cost per item. A run with includeRounds for two full days measured at 54 requests, 14.5 MB, 460 MB peak memory and 70 seconds for 676 items; in a 1 GB container that is about $0.007 a run, or $0.010 per 1,000 items, so the result price is about 200 times the platform cost on that path.
Free allowance: Apify's Free plan carries $5 of usage a month (checked 2026-09-25). A default run of 200 items costs $0.42 ($0.02 plus 200 times $0.002), so the allowance covers 11 default runs a month, or a single run of up to 2,490 items.
Limits and honesty
- The results page does not show the round.
roundis null unlessincludeRoundsis true, and even then qualifying matches and matches on tournament pages the site serves with an error stay null, because qualifying draws live on a separate tab that is not fetched. In the measured two-day run withincludeRounds, 364 of 676 items received a round. surfacecomes from the site's "this week's tournaments" sidebar, which lists the current week only. For older dates and for ITF or Futures blocks it is often null;includeRoundsfills it from the tournament page where one exists.- The site marks neither retirements nor walkovers on the results page. A retired match shows the games played so far and a sets-won count such as 1-0; a walkover shows no games, so
scoreis null andsetsis empty. - Odds are the odds the site displays next to the result, from whichever bookmaker it uses at the time. They are not a market average and are null for some lower-level matches (13 of 200 items in the default run on 2026-09-25).
- Competitor names are the site's short competition form (
"Basilashvili N."). The site truncates long doubles names in the visible cell; the full form is taken from the cell's tooltip when present. - Times, seedings, country flags, head-to-head links, player profile links, streams and news are on the page and are not collected.
- Only days that have finished are complete. Fetching today returns whatever has finished so far.
- A results page for a day with no matches yields zero items and a warning; a run with zero items over all dates fails with a clear error rather than finishing green.
- The source changes its markup a few times a year. When it does, the daily test fails, the house status page shows it, a fix ships, and the changelog records it.
Legal
robots.txt. tennisexplorer.com/robots.txt, checked 2026-09-25, has one block for every user agent and disallows three paths only: /redirect/, /terms-of-use/ and /contact/. The paths this Actor fetches are permitted: /results/ for the daily results pages, and the tournament pages such as /chengdu/2026/atp-men/ that includeRounds reads. The Actor reads robots.txt at the start of every run, under its own identity, and skips any path it disallows, so a change there stops a fetch without a code change. The Actor never fetches /terms-of-use/; the quotation below was taken by a person reading that page on 2026-09-25.
Terms. The site's Terms of Use (https://www.tennisexplorer.com/terms-of-use/), section 2.11, say: "You must not burden our server on which the Website is hosted with automated requests, nor assist any third party in such activity." and "Furthermore, you are not permitted to use our content available on the Website by embedding, aggregating, scraping or recreating it without our express consent, unless otherwise provided for by applicable laws and regulations." The house holds no account at tennisexplorer.com and has never logged in. This Actor fetches only logged-out public pages that robots.txt permits, at 30 requests a minute at most over two connections, under the declared identity SubRosaBot/1.0 (+https://subrosa.dev/bots), which is fixed and never rotated. No cookies are accepted or persisted, no headers are generated to imitate a browser, and no challenge is solved. If tennisexplorer.com asks the house to stop, in any form, the Actor is unpublished the same day and the changelog says why.
Public performers. player1 and player2 carry the name of a professional athlete as it appears in the public record of the event they are in, a match result. That name is the record, not the person's data. It is carried in a field that names the role (player1, player2), never in name. Nothing else about the person is collected: no profile URL, no photo, no biography, no ranking history, no birthdate. The results page also links each competitor's profile page and shows seedings and entry marks such as (5), (Q) or (WC); this Actor drops them at extraction and the live test asserts that no item carries a profile URL or an image.
Your side. A buyer with an account at tennisexplorer.com is bound by the terms they accepted there. You are responsible for how you use the data downstream. Odds are shown for record purposes and are not a recommendation.
Changelog
- 2026-09-26: house scrub module adopted. The live test reads the shared phone and email rules (phone detection by shape, never by digit count) and the schema's identifier keys;
sameDomainDelaySecswritten explicitly as 0 (tennisexplorer.com robots.txt states no Crawl-delay, checked 2026-09-26). No output field changed. - 2026-09-25: review fixes before publish. Fixed identity on the wire (
SubRosaBot/1.0on every request including robots.txt, session pool and cookie persistence off); delivery through the housecreateDeliverer; Legal section restated with robots.txt, the terms quotation and the public-performer ruling; item counts and free allowance corrected to measured figures; sample regenerated with doubles, Futures and no-odds rows. - 2026-09-25: first release.
Support
Open an issue on the Actor's Issues tab. Replies within one day.