Tennis Scores: ATP, WTA and Challenger Results
Pricing
from $1.00 / 1,000 matches
Tennis Scores: ATP, WTA and Challenger Results
Daily tennis results for analytics, dashboards, research and media apps. ATP, WTA and Challenger singles and doubles with set scores and tiebreaks, plus automatic failover to backup sources.
Pricing
from $1.00 / 1,000 matches
Rating
0.0
(0)
Developer
Quill Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Security
Limited permissionsShare
Tennis Scores: ATP, WTA and Challenger Results with Source Failover
Daily tennis scoreboards as clean dataset rows: one row per match, with set-by-set games, tiebreak points, status and winner. Built for sports analytics, dashboards, research projects and media apps that need a steady feed of public results.
The Actor reads one primary scoreboard and keeps going when it breaks. If the primary errors, is rate limited, times out, changes its format, or returns nothing for a date, the run switches to backup sources automatically and marks every row it filled that way.
What you get
- Tours: ATP, WTA and ATP Challenger. Singles and doubles.
- Match states: scheduled, live (with the current set), finished, retired, walkover, cancelled.
- Scores: games per set, tiebreak points, sets won, a score line such as
6-7 4-6, winner, match duration where published. - Players: public name, nationality and ranking when the source shows them. No other personal data.
- Optional match stats (aces, double faults, break points, serve points) when the primary source publishes them.
- Provenance on every row: which source served it and whether a backup was used.
Coverage by source
| Source | Tours | Doubles | Live | Tiebreaks | Round | Stats | Requests per date |
|---|---|---|---|---|---|---|---|
| 365scores (primary) | ATP, WTA, Challenger | yes | yes | yes | yes | yes, optional | 1 (+1 per match for stats) |
| livescore (backup 1) | ATP, WTA, Challenger | yes | yes | yes | no | no | 1 |
| espn (backup 2) | ATP, WTA | yes | yes | yes | yes | no | 2 |
| wta (backup 3) | WTA only | yes | partial | loser points only, winner side derived | yes | no | 1 + one per WTA event that week |
Challenger results come only from 365scores or livescore. If both are down, Challenger rows are missing for that date and the log says so. The WTA backup has no match stats, and stats in general exist only on 365scores rows.
How failover works
- Sources are tried in the order of
sources(default365scores, livescore, espn, wta). - When the primary serves a date, no backup is contacted at all (unless
crossCheckis on). - When it fails, backups fill the tours they cover, one after another, until every requested tour is covered or the list ends.
- Rows from a backup carry
fallback_used: trueand a shortfallback_reason, e.g.365scores: HTTP 429.
Triggers: HTTP errors and 5xx after retries, HTTP 429, timeouts, invalid JSON, a changed payload shape (parse errors or more than 20% of rows failing validation), and an empty scoreboard or no rows for the requested tours.
Input
| Field | Default | Notes |
|---|---|---|
| dates | today (UTC) | YYYY-MM-DD, at most 7 dates |
| circuits | ATP, WTA, Challenger | Doubles boards map onto the same tour |
| sources | 365scores, livescore, espn, wta | Order is priority. The first source is primary. Later sources are backups |
| includeDoubles | true | Set false to keep singles only |
| statuses | scheduled, live, finished | Walkovers and retirements count as finished |
| includeStats | false | 365scores only. One extra request per live or finished match that publishes stats |
| maxMatches | 200 | 1–2000, across all dates |
| playerNames | empty | Case-insensitive substring on either player |
| requestDelaySecs | 2 | Minimum 1 second from one request to the next |
| maxRequestsPerRun | 150 | 10–1000. Hard cap on HTTP requests in one run across all sources (stats requests included) |
| timezone | UTC | Sent as timezoneName on 365scores |
| crossCheck | false | Compare finished scores with the first backup that covers a selected tour |
| simulateFailure | empty | Testing only. Named sources fail before any request |
| healthCheck | false | Check sources and skip the dataset. No charge |
| healthCheckDate | yesterday UTC | YYYY-MM-DD used when healthCheck is true |
Input example
{"dates": ["2026-10-21"],"circuits": ["ATP", "WTA", "Challenger"],"statuses": ["finished"],"includeDoubles": true,"maxMatches": 200}
Output example
A real row from a cloud test run on 2026-10-22:
{"match_id": "4878233","source": "365scores","date_requested": "2026-10-21","start_time_utc": "2026-10-21T03:03:33Z","circuit": "Challenger","discipline": "singles","tournament": "Cali","tournament_id": 6943,"round": "Round of 32","status": "finished","status_text": "Ended","player1": {"name": "Federico Coria","id": 47314,"country": "Argentina","ranking": 746},"player2": {"name": "Nicolas Mejia","id": 51765,"country": "Colombia","ranking": 115},"sets_won_p1": 0,"sets_won_p2": 2,"set_scores": [{"set": 1,"p1": 6,"p2": 7,"tiebreak_p1": 4,"tiebreak_p2": 7,"duration": "01:11"},{"set": 2,"p1": 4,"p2": 6,"tiebreak_p1": null,"tiebreak_p2": null,"duration": "49'"}],"score_text": "6-7 4-6","winner": 2,"current_set": null,"match_duration": "02:00","stats": null,"match_url": "https://www.365scores.com/en/tennis/match/cali/federico-coria-nicolas-mejia/4878233","scraped_at": "2026-10-22T15:07:09Z","fallback_used": false,"fallback_reason": null,"verified_by": null,"crosscheck": null}
Extra fields:
source: the source that served the row.fallback_usedandfallback_reason: whether a backup supplied the row, and why the earlier sources were skipped.verified_byandcrosscheck: filled only whencrossCheckis on.crosscheckismatch,mismatchornot_found;verified_bylists the backup that agreed.
Fields a source does not publish are null. match_id, source, date_requested and scraped_at are always set.
Health check
Set "healthCheck": true to test every source on a recent finished date (healthCheckDate, default yesterday UTC). The run pushes no rows and charges nothing. It saves a report under the key HEALTH_REPORT in the default key-value store, and its status line reads like health: 365scores PASS, livescore PASS, espn PASS, wta PASS. The run fails if any checked source fails.
The same check runs outside Apify:
python scripts/health_check.py --date 2026-10-21
Exit code 0 means all sources passed. For monitoring, start the Actor once a day from an Apify schedule with {"healthCheck": true}, or call the script from cron.
Pricing
Pay per event: $0.001 per match row. Nothing is charged for health checks, for dates where every source failed, or for empty results. A failed stats request still returns the match, with stats set to null.
Request etiquette
Each source has its own queue: one request at a time, at least 1–2 seconds apart plus a random pause, and backups stay idle while the primary works. HTTP 429 honors Retry-After (one retry when it is 30 seconds or less), server errors get two retries with growing pauses, and 403 is never retried. maxRequestsPerRun caps the total requests of a run.
Data sources
Scores come from public JSON scoreboards published by 365Scores, LiveScore, ESPN and the WTA. No login, key or browser is used. Each publisher has its own terms of use, and some of them restrict automated access or commercial reuse; you are responsible for how you use the data. This Actor is not affiliated with or endorsed by 365Scores, LiveScore, ESPN, the WTA or the ATP.
Also from Quill Data
- Google Hotels Prices — nightly and total-stay hotel rates from public Google Hotels search.
- Google Flights Cheapest Fare Monitor — cheapest public Google Flights fare for a route and date; failed or empty runs are free.
Limits
- Live scores are a snapshot at run time. Schedule the Actor for regular updates.
- Up to 7 dates per run, UTC calendar days.
- Round names are not available from the livescore backup.