Request a tool
All toolsAutomationsGuidesMCP serverRequest a toolPlatformsCategories
Tennis Results & Odds Scraper icon

Tennis Results & Odds Scraper

Tennis results and upcoming matches from TennisExplorer: set scores, winner, surface, round and average odds for ATP, WTA, Challenger and ITF.

170 runs on Apify $0.00095 per match ($0.95 / 1,000)
Run this in the cloudRun on Apify →

Developer & Research Tools

How it works

  1. 1
    Open it on Apify

    Hit Run on Apify — it opens the tool in the cloud, no install.

  2. 2
    Set the inputs

    Adjust lastDays, upcomingDays, dateFrom (sensible defaults are pre-filled).

  3. 3
    Click Run

    The tool runs on Apify’s cloud and collects the data for you.

  4. 4
    Export the results

    Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.

Pricing

$0.00095 per match = $0.95 per 1,000

You are charged forWhenPrice
Match returnedOne tennis match returned in the dataset.$0.00095

Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-09-14, and they are what you are actually charged.

Inputs

FieldWhat it doesType
lastDaysThe last N full days of results, ending yesterday. 1 is yesterday only, which suits a daily schedule. Used when From date is empty.integer
upcomingDaysToday's matches plus the schedule after it: 1 is today only, 2 adds tomorrow. TennisExplorer usually lists the next day or two, with odds. Used when From date is empty.integer
dateFromThe first day, as YYYY-MM-DD, for a fixed range instead of Last days. Past days go back as far as TennisExplorer has results.string
dateToThe last day. Leave it empty to stop at today. One run covers up to 366 days.string
matchTypesLeave it empty for all four. Men's matches come under ATP and women's under WTA, Challenger and ITF events included.array
levelsLeave it empty for every level. Challenger and ITF are known from the tournament's name, the rest from TennisExplorer's tour calendar.array
tournamentsPart of a tournament's name as TennisExplorer writes it, such as US Open or Genoa, or a link to the tournament's TennisExplorer page. A match is kept when its tournament matches any of them.array
playersA surname as TennisExplorer writes it, such as Sinner or Rybakina, or a link to the player's TennisExplorer page. A match is kept when either side matches, doubles partners included.array
surfacesLeave it empty for any surface. The surface comes from TennisExplorer's tour calendar. Men's ITF matches are listed without their tournament, so a surface filter leaves them out.array
includeOddsThe average of the bookmakers' prices for each player, as the list shows it. For a finished match these are the last prices before it started.boolean
addRoundsReads each tournament's page once to add the round: final, semifinal, 1. round and so on. Turn it off on long ranges to finish sooner.boolean
includeMatchDetailsOpens each match's own page for the players' full names, rankings, birth dates, height and playing hand, and every bookmaker's odds with the opening prices. That's one more page per match, so a run with details stops at 2,000 matches.boolean
addPlayerCountriesReads each player's page once for their country. That's one more page per player, so a busy day takes several minutes longer.boolean
maxMatchesThe most matches returned in one run. Each match returned is one charge.integer

What you get

A structured dataset — each result includes fields like:

datetimetourmatchTypeleveltournamentsurfaceroundplayer1player2winnerscoreoutcomeplayer1Oddsplayer2Oddsstatusurl

Export every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.

Related tools in Developer & Research Tools

Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.

GitHub Scraper iconDeveloper & Research Tools

GitHub Scraper

Search GitHub repos and users: stars, forks, language, topics, licence, plus user bio, company and followers. No token needed. $0.90 per 1,000 rows.

18 use cases

Stack Overflow / Stack Exchange Scraper iconDeveloper & Research Tools

Stack Overflow / Stack Exchange Scraper

Search Stack Overflow and Stack Exchange by keyword or tag. Score, answer count, views, reputation and body text. $2 per 1,000 questions.

2 use cases

Package Registry Scraper (npm + PyPI) iconDeveloper & Research Tools

Package Registry Scraper (npm + PyPI)

Get npm and PyPI package metadata as JSON. Version, license, author, repo, keywords and npm monthly downloads. $2 per 1,000 packages.

2 use cases

arXiv Scraper iconDeveloper & Research Tools

arXiv Scraper

Search arXiv papers by title, author, abstract or category. Get full abstracts, authors, categories, DOI, dates and PDF links. $2 per 1,000 papers.

2 use cases

OpenAlex Scholarly Works Scraper iconDeveloper & Research Tools

OpenAlex Scholarly Works Scraper

Search 250M+ OpenAlex papers with no API key. Get titles, authors, venue, year, citations, DOI, OA links and full abstracts. $2.00 per 1,000 papers.

2 use cases

Crossref Scholarly Works Scraper iconDeveloper & Research Tools

Crossref Scholarly Works Scraper

Search 150M+ papers on Crossref: DOI, title, authors, journal, publisher, date, citations and abstract. No API key. $1.00 per 1,000 works.

2 use cases

See all Developer & Research Tools →

Tennis Results and Odds Scraper: ATP, WTA, Challenger and ITF, day by day

Pick the days you want and you get one row per match: tour, level, tournament, surface, round, both players, the set scores with tiebreak points, the winner, and the average odds. Matches that have not been played yet come back too, with their odds and head to head.

Retirements are worked out from the score, because TennisExplorer never writes the word in its results. That is right almost always, and wrong in one shape: a best-of-five match abandoned between two completed sets reads as a finished win.

InputDays, as a rolling window or a fixed date range, plus optional filters
OutputOne row per match
Ceiling25,000 matches per run, or 2,000 with match details on
Account neededNone
Price$0.95 per 1,000 matches, flat on every plan

🔍 What Tennis Results and Odds Scraper does

It reads TennisExplorer's day pages one at a time and turns each listed match into a row. Yesterday only, a fixed range back to 1990, or today and tomorrow's schedule. Up to 366 days in one run.

Filters cut the list before anything is charged: match type, level, surface, a tournament name or link, or a player's surname or link. A player filter keeps the match when either side matches, doubles partners included.

Two optional passes add depth and cost time. Round reads each tournament's page once and is on. Match details opens every match's own page for full names, rankings, birth dates, height, playing hand and each bookmaker's opening and closing prices.

The run also writes a RUN_REPORT to the key-value store: which days were read, how many matches each day listed against how many came back, and why the run stopped.

📥 What you give it

{
  "lastDays": 1,
  "upcomingDays": 1,
  "matchTypes": ["atp-single", "wta-single"],
  "levels": ["tour"],
  "maxMatches": 500
}
FieldDefaultWhat it is
lastDays0, and the box starts at 1The last N full days of results, ending yesterday. 1 is yesterday only, which suits a daily schedule.
upcomingDays0Today plus the schedule after it. 1 is today, 2 adds tomorrow.
dateFromnoneYYYY-MM-DD, for a fixed range instead. Back to 1990-01-01. Wins over the two fields above.
dateTononeThe last day. Empty stops at today. One run covers up to 366 days.
matchTypesall fouratp-single, atp-double, wta-single, wta-double. Men's matches sit under ATP and women's under WTA, Challenger and ITF included.
levelsevery leveltour, challenger, itf, other-lower, exhibition.
surfacesanyhard, clay, grass, indoors.
tournamentsnonePart of a tournament's name as TennisExplorer writes it, like US Open or Genoa, or a link to its page.
playersnoneA surname as TennisExplorer writes it, like Sinner or Rybakina, or a link to the player's page.
includeOddsonThe average of the bookmakers' prices for each player. On a finished match, the last prices before it started.
addRoundsonReads each tournament's page once for the round. Turn it off on long ranges to finish sooner.
includeMatchDetailsoffOne more page per match. Caps the run at 2,000 matches.
addPlayerCountriesoffOne more page per player, so a busy day takes several minutes longer.
maxMatches1000 when you leave it out, and the box starts at 20Up to 25,000. Each match returned is one charge.

Give no days at all and you get one labelled sample row, not an error and not an empty dataset.

Dates are Prague dates. A final starting at 23:40 in Barranquilla sits on the next day's page. startTimeUtc on every row gives you the real instant.

📤 What you get back

A real row from a recent run:

{
  "matchId": "3321413",
  "date": "2026-09-13",
  "time": "20:20",
  "startTimeUtc": "2026-09-13T18:20:00Z",
  "status": "finished",
  "outcome": "completed",
  "tour": "ATP",
  "matchType": "singles",
  "level": "tour",
  "tournament": "US Open",
  "tournamentCountryCode": "US",
  "surface": "hard",
  "round": "final",
  "player1": "Zverev A.",
  "player1Seed": "1",
  "player2": "Shelton B.",
  "player2Seed": "8",
  "winner": "Zverev A.",
  "score": "6-3, 7-6(2), 5-7, 6-2",
  "player1Sets": 3,
  "player2Sets": 1,
  "sets": [
    { "player1": 6, "player2": 3, "tiebreak": null },
    { "player1": 7, "player2": 6, "tiebreak": 2 },
    { "player1": 5, "player2": 7, "tiebreak": null },
    { "player1": 6, "player2": 2, "tiebreak": null }
  ],
  "player1Odds": 1.66,
  "player2Odds": 2.24,
  "player1H2H": null,
  "player2H2H": null,
  "player1Url": "https://www.tennisexplorer.com/player/zverev-6f768/",
  "player2Url": "https://www.tennisexplorer.com/player/shelton-38989/",
  "tournamentUrl": "https://www.tennisexplorer.com/us-open/2026/atp-men/",
  "url": "https://www.tennisexplorer.com/match-detail/?id=3321413"
}
FieldWhat it is
matchIdStable. Use it as your dedupe key across runs.
status, outcomefinished or scheduled, then completed, retired, walkover, or null when the match has not been played.
score, setsscore is written from player 1's side in 7-6(3) style. sets breaks it out per set, with the tiebreak loser's points.
timeThe Prague clock, and null when TennisExplorer shows --:--. startTimeUtc is the same moment in UTC.
player1Odds, player2OddsThe average across bookmakers, when includeOdds is on.
player1H2H, player2H2HThe head to head, on matches that have not been played.
roundFrom the tournament page, so it needs addRounds. Men's ITF and UTR matches have none to read.
With details onplayer1FullName, ranks, birth dates, heights, playing hands, bookmakerOdds with each bookmaker's opening and closing prices, and detailsRead.
With countries onplayer1Country and player2Country.

On doubles with details on, the full names join both partners and the single-player facts stay null. The match page stacks one table per pair, so there is no single player to rank.

🧾 Reading the output

Two kinds of row can land in your dataset.

RowHow to spot itCharged
A matchIt has a matchId and no flagyes
The sample row_sample: trueno

There are no diagnostic rows here. Anything that went wrong is in the run's status message, and in full in RUN_REPORT: days that could not be read, matches left out, and rounds that were missing.

stoppedBecause in that report says why the run ended.

ValueWhat it means
stopIt reached your maxMatches.
deadlineIt ran out of time. Everything delivered is complete.
budgetThe run's charge limit was reached.
unreachableTennisExplorer stopped answering.

The run fails outright rather than half-delivering when the input cannot work: a bad date, a range over 366 days, or a charge budget too small for one match.

▶️ How to run it

1. Open Tennis Results and Odds Scraper and click Try for free. 2. Set Last days to 1 for yesterday, or Upcoming days to 1 for today's schedule. From date and To date give a fixed range instead. 3. Narrow it with Match types, Levels, Surfaces, Tournaments or Players. 4. Set Maximum matches. Start around 20 to see the output shape, then click Start. 5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

💰 How much does it cost?

$0.95 per 1,000 matches. Flat on every Apify plan, no volume tiers.

You pay per match row delivered. The sample row is free, and so is anything that never reaches your dataset: a match dropped by a filter, one still being played, a repeat, a day with no matches, and a row the parser could not read. A match whose detail page would not load is delivered without its details and not charged.

💡 What people use it for

  • Running it daily with Last days on 1, so each run picks up only yesterday's results.
  • Pulling a player's whole season by surname and checking the odds against the result.
  • Watching tomorrow's schedule with odds and head to head before the day starts.
  • Pulling a full Grand Slam by name, with set scores and tiebreak points per match.

🚧 What it does not do

  • No live scores. A match being played is left out rather than delivered with a partial score.
  • Retirements are read from the score. A best-of-five match abandoned between two completed sets

reads as a completed win.

  • Men's ITF matches come thin. TennisExplorer lists them under one Futures heading with no

link, so they have no tournament name, surface or round unless match details are on, and a surface filter drops them.

  • UTR events have no round, whatever you set.
  • The schedule runs a day or two ahead, no further. That is how far TennisExplorer publishes.
  • Finished days get edited afterwards. A match can leave a past day's list hours later, so two

runs over one day can differ.

  • Match details cap a run at 2,000 matches and add a page per match. Player countries add a page

per player.

  • Level is TennisExplorer's own split. Some WTA 125 events sit in its lower level rather than

under tour.

  • It reads one page a second, so a long range takes real time. Turn rounds off to speed it up.

🧭 Which sports data scraper do you need?

If you wantUse
Tennis results, schedules and average oddsThis one
Pre-game odds and player props across sportsSports Odds Scraper
Event contract prices and volumeKalshi Markets Scraper

❓ Questions people ask

How far back can I go? To 1990-01-01. One run covers up to 366 days, so split a longer history into several.

Can I get just one player? Put the surname as TennisExplorer writes it into Players, or paste their page link. The match is kept when either side matches.

Do I get odds on finished matches? Yes, the last average prices before it started. With match details on you also get each bookmaker's opening and closing prices.

Why is round empty on some rows? Men's ITF and UTR matches have no tournament page to read it from.

Why is my date off by a day? The date is TennisExplorer's, on Prague time. Use startTimeUtc when the exact moment matters.

Is scraping match results legal? These are public sports results, and a score is a fact nobody owns. TennisExplorer's own site terms still apply to its pages, so read them and decide what suits your use. Apify's write-up on scraping and the law is a good starting point, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the dates and filters you used and the run ID. The RUN_REPORT in the run's key-value store usually explains it on its own.