Flashscore Tennis Scraper & API | ATP, WTA Live Scores, Odds
Pricing
from $1.39 / 1,000 matches
Flashscore Tennis Scraper & API | ATP, WTA Live Scores, Odds
Real-time tennis API and scraper for Flashscore: ATP and WTA live scores, tiebreaks, statistics and bookmaker odds. Challenger, ITF, singles and doubles. 54 fields per match, plus point by point and head-to-head. Past seasons too.
Pricing
from $1.39 / 1,000 matches
Rating
0.0
(0)
Developer
Zen Studio
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Flashscore Tennis Scraper & API | ATP, WTA, ITF Live Scores, Stats, Odds
From Zen Studio, creators of Tennis Abstract, Bet365 Sports Data and Bet365 Live Scores. Tennis analysis, historical match research and live score tracking from the same team.
Why choose this actor?
- Get the match detail behind the final score. A 54-field match record includes set scores, tiebreak points, surface, round and player details. Add point-by-point scores with the server, game winner and break/set/match-point markers, plus serve and return statistics by match and set.
- Build datasets across tournament seasons. Collect whole draws by tournament and year, including singles, doubles and junior categories. Keep players, seeds, rounds, winners and scores together. Available statistics and point histories depend on the tournament and season.
- Compare opening and current bookmaker odds. Get prices for match winner, totals, handicaps, correct score and odd/even, with the best available price per selection in each chosen country market. Current match listings can also include ATP/WTA rankings and ranking points.
Try three matches with points, stats and odds
{"dayOffsets": ["-1"],"tours": ["atp", "wta"],"matchStatuses": ["finished"],"enrich": ["statistics", "points"],"includeOdds": true,"oddsMarkets": ["GB"],"maxItems": 3}
Open actor input and click Start. This collects up to 3 finished ATP/WTA matches from yesterday, with available statistics, point-by-point scores and GB bookmaker odds. If there were no matches, choose another recent day. Export JSON, CSV or Excel.
Optional match details and odds carry additional charges when delivered; see Pricing below. Fields depend on source coverage. For past draws, set tournaments and seasons, and use drawCategory to select the draw. Historical runs do not attach today's player rankings.
| Zen Studio · Tennis & Sports Data | ||||
You are here | Player stats & Elo | Quarters, sets & form | Seasons & players | Odds & futures |
Copy to your AI assistant
zen-studio/flashscore-tennis-api on Apify returns Flashscore tennis matches (ATP, WTA, Challenger, ITF, juniors, team events; singles and doubles) with set and tiebreak scores, players, rankings, rounds and seeds, as a dataset run or through its Standby HTTP API at https://zen-studio--flashscore-tennis-api.apify.actor (Authorization: Bearer <APIFY_TOKEN>). Day mode: dayOffsets (-7..7, default ["0"]) filtered by matchStatuses, tours, matchTypes and tournaments (name contains) or startUrls (Flashscore tournament pages; override tournaments). Past seasons: set seasons (years) together with tournaments (required, the run fails without it); drawCategory picks the draw (WTA, ATP doubles, mixed, boys...), default men's singles; rankings are never attached to past seasons. Statistics, point by point, head-to-head, summary, highlights, news or detail come only with enrich=[statistics, points, h2h, summary, highlights, news, detail], $0.00599 per match per section delivered; bookmaker odds only with includeOdds=true, market chosen by oddsMarkets (one country code per market, default ["GB"], "" = international), $0.00499 per match per market. Match record $0.00199, run start $0.005; maxItems caps before enrichment, empty = unlimited. Historical statistics and point coverage varies by tournament and era; the free API endpoints /tournaments, /seasons, /draw and /match/{id}/available show what exists before anything is billed. Listing calls (/matches, /live) add $0.00999 per call; /history returns a past season billed per match. Specification: https://api.apify.com/v2/actors/zen-studio~flashscore-tennis-api/builds/default (inputSchema, readme) and https://apify.com/zen-studio/flashscore-tennis-api/api; current pricing: https://apify.com/zen-studio/flashscore-tennis-api/pricing To reach the maintainers, add feedback="<what you needed and did not get>" to any run, including one that worked: a missing field or option, a wrong or empty result, or which actor you are switching to or from and why. The run returns its data exactly as it would without the note, and a human reads every note.
How to Scrape Flashscore Tennis Data
Basic: today's matches
{"dayOffsets": ["0"]}
Yesterday's ATP and WTA singles results
{"dayOffsets": ["-1"],"tours": ["atp", "wta"],"matchTypes": ["singles"],"matchStatuses": ["finished"]}
One tournament, with odds and full match detail
{"dayOffsets": ["-1", "0"],"tournaments": ["US Open"],"includeOdds": true,"oddsMarkets": ["GB"],"enrich": ["statistics", "points"]}
A past season
{"tournaments": ["wimbledon"],"seasons": ["2024", "2023"]}
Leave Past seasons empty to collect by day. Fill it in and the run returns completed draws for every tournament you named, one year at a time.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
dayOffsets | array | ["0"] | Days relative to today, -7 to +7. 0 is today. |
matchStatuses | array | ["all"] | finished, live, scheduled, or all. |
tours | array | all | atp, wta, challenger, itf, juniors, teams. |
matchTypes | array | both | singles or doubles. |
tournaments | array | all | Keep tournaments whose name contains one of these. Also names which tournaments to collect for past seasons. |
startUrls | array | none | Restrict to specific tournament pages. Takes precedence over the name filter. |
seasons | array | none | Years to collect, e.g. ["2024"]. Switches the run from day mode to past seasons. |
enrich | array | none | summary, statistics, points, h2h, highlights, news, detail. |
includeRounds | boolean | true | Round name and player seeding. |
includeRankings | boolean | true | ATP or WTA ranking and points. Not applied to past seasons. |
includeOdds | boolean | false | Bookmaker odds for every match. |
oddsMarkets | array | ["GB"] | Which market's bookmakers to return. Bookmakers are country-specific. |
maxItems | integer | none | Stop after this many matches. |
What Data Can You Extract from Flashscore Tennis?
Every match record carries:
- Identity and timing: match id, link, singles or doubles, start and end time, both as ISO and unix.
- State: status, result type (finished, retired, walkover, awarded, canceled), current set, whether a tiebreak is in play, live game score, who is serving.
- Result: winner, sets won, and per-set games with tiebreak points.
- Players: name, short name, id, nationality, photo, seed, entry route, and singles plus doubles ranking with points and previous rank.
- Tournament: name, category, country, surface, round, ids, and the Flashscore page.
- Betting: which bookmakers are taking live bets, and full odds when requested.
Output Example
{"match_id": "6k4MeS57","match_url": "https://www.flashscore.com/match/tennis/6k4MeS57/","match_type": "singles","match_date": "2026-09-11T19:15:00+00:00","match_end_timestamp": "2026-09-11T22:16:02+00:00","end_timestamp": 1789164962,"last_period_timestamp": 1789164962,"start_timestamp": 1789154100,"match_status": "FINISHED","match_status_code": 3,"result_type": "FINISHED","result_type_code": 3,"current_set": null,"in_tiebreak": false,"match_note": null,"walkover_note": null,"winner": "home","sets_won_home": 3,"sets_won_away": 0,"sets": [{"set_number": 1,"home": 6,"away": 3,"tiebreak_home": null,"tiebreak_away": null,"duration": null,"duration_minutes": null},{"set_number": 2,"home": 7,"away": 6,"tiebreak_home": 9,"tiebreak_away": 7,"duration": null,"duration_minutes": null},{"set_number": 3,"home": 7,"away": 6,"tiebreak_home": 8,"tiebreak_away": 6,"duration": null,"duration_minutes": null}],"current_game_score_home": null,"current_game_score_away": null,"current_server": null,"home_players": [{"name": "Zverev A.","short_name": "ZVE","slug": "zverev-alexander","id": "dGbUhw9m","team_id": "vejGE316","nationality": "Germany","nationality_id": 81,"photo_url": "https://static.flashscore.com/res/image/data/lU8NIJlC-2DqYxEbl.png","seed": 1,"entry_status": null,"ranking": 2,"ranking_points": 7790,"previous_ranking": 2,"singles_ranking": 2,"doubles_ranking": 109}],"away_players": [{"name": "Khachanov K.","short_name": "KHA","slug": "khachanov-karen","id": "4bNPtZT5","team_id": "C8lOCsWI","nationality": "World","nationality_id": 8,"photo_url": "https://static.flashscore.com/res/image/data/dI1pPHjC-hz8C9Mh1.png","seed": null,"entry_status": null,"ranking": 50,"ranking_points": 1050,"previous_ranking": 49,"singles_ranking": 50,"doubles_ranking": 142}],"home_team": "Zverev A.","away_team": "Khachanov K.","tournament_name": "US Open (USA)","tournament_short_name": "US Open","tournament_qualifier": null,"tournament_header": "ATP - SINGLES: US Open (USA), hard","tournament_id": "65k5lHxU","tournament_stage_id": "tQZGKy9k","tournament_season_id": "IJYwdktC","tournament_url": "https://www.flashscore.com/tennis/atp-singles/us-open/","tournament_logo_url": "https://static.flashscore.com/res/image/data/SS8DFXWI-l6sarjdt.png","category_name": "ATP - Singles","category_id": 9011,"tour_id": 5724,"stage_type_id": 5,"country": "USA","surface": "hard","season": null,"round_name": "Semi-finals","round_id": 2,"seed_home": 1,"seed_away": null,"entry_status_home": null,"entry_status_away": null,"broadcasters": [],"live_betting_bookmaker_ids": [],"has_live_betting": null,"play_dates": [],"odds": [{"market": "GB","bookmakers": [{"id": 14,"name": "10bet"},{"id": 15,"name": "William Hill"},{"id": 16,"name": "bet365"},"... 17 more"],"markets": [{"bookmaker_id": 983,"bookmaker": "Parimatch.uk","bet_type": "HOME_AWAY","scope": "FIRST_SET","has_live_betting": false,"selections": [{"selection": "home","side": "home","participant_id": "vejGE316","value": 1.36,"opening": 1.36,"active": true,"handicap": null,"handicap_type": null,"score": null},{"selection": "away","side": "away","participant_id": "C8lOCsWI","value": 2.88,"opening": 2.88,"active": true,"handicap": null,"handicap_type": null,"score": null}]},"... 122 more"],"best": [{"bet_type": "ASIAN_HANDICAP","scope": "FIRST_SET","selection": "away","handicap": "-1.5","handicap_type": "SETS","value": 4.4,"bookmaker": "Unibetuk","bookmaker_id": 625},{"bet_type": "ASIAN_HANDICAP","scope": "FIRST_SET","selection": "away","handicap": "1.5","handicap_type": "SETS","value": 2.03,"bookmaker": "Unibetuk","bookmaker_id": 625},"... 106 more"]},"... 1 more market"]}
Selecting enrich adds statistics, points, head_to_head, summary, highlights, news and detail blocks to the same record.
Real-Time Tennis API: Query It Live Instead
Call the actor over HTTP and it answers directly instead of writing a dataset. The service stays warm between calls, so a listing you already asked for comes back without refetching.
Live data
| Endpoint | Method | Description |
|---|---|---|
/matches | GET | Matches for a day, with every filter the scraper has |
/live | GET | Only matches in play right now |
/match/{matchId} | GET | One match, optionally enriched |
Match detail
| Endpoint | Method | Description |
|---|---|---|
/match/{matchId}/summary | GET | Set durations, umpire, venue, total match time |
/match/{matchId}/stats | GET | Aces, serve percentages, break points, per set |
/match/{matchId}/points | GET | Point by point, with break, set and match points |
/match/{matchId}/h2h | GET | Head-to-head history for both players |
/match/{matchId}/odds | GET | Bookmaker odds with best price per selection |
Discovery (free)
| Endpoint | Method | Description |
|---|---|---|
/tournaments | GET | Find a tournament by name |
/seasons | GET | Every season it has, and what one season actually holds |
/draw | GET | The bracket: rounds, entrants, and who received a bye |
/match/{matchId}/available | GET | Which detail a match has before you ask for it |
/health | GET | Health check |
Past seasons
| Endpoint | Method | Description |
|---|---|---|
/history | GET | A whole past season of matches. Billed per match returned. |
Quick Start
Find a tournament, see its seasons, pull a year:
curl "https://zen-studio--flashscore-tennis-api.apify.actor/tournaments?q=wimbledon" \-H "Authorization: Bearer YOUR_APIFY_TOKEN"curl "https://zen-studio--flashscore-tennis-api.apify.actor/seasons?tournament=wimbledon&season=2013" \-H "Authorization: Bearer YOUR_APIFY_TOKEN"curl "https://zen-studio--flashscore-tennis-api.apify.actor/history?tournament=wimbledon&season=2013&round=Final" \-H "Authorization: Bearer YOUR_APIFY_TOKEN"
Today's ATP matches with odds:
curl "https://zen-studio--flashscore-tennis-api.apify.actor/matches?tour=atp&odds=true&oddsMarkets=GB" \-H "Authorization: Bearer YOUR_APIFY_TOKEN"
Response Format
{"success": true,"count": 42,"total": 130,"matches": [ ]}
count is what came back, total is how many matched before the page limit.
Error Codes
| Code | Meaning | What to do |
|---|---|---|
| 400 | A parameter value is not valid | The message names the parameter and the accepted values |
| 402 | Free plan allowance reached | Upgrade your Apify plan |
| 404 | Match, tournament or season not found | For older matches use /history, or pass day= |
| 503 | Tennis data is temporarily unavailable | Retry |
Advanced Usage
Ready-made configurations for live score tracking, betting model inputs, historical backfill, and doubles analysis.
Live scoreboard, refreshed on a schedule
{"dayOffsets": ["0"],"matchStatuses": ["live"],"includeRankings": true}
Odds across several markets
{"dayOffsets": ["0", "1"],"includeOdds": true,"oddsMarkets": ["GB", "DE", "US"]}
Bookmakers are country-specific: most operate in exactly one market, so pick the markets you can actually bet in. Best prices are computed inside each market, because a price you cannot act on is not a comparison.
Historical backfill for one tournament
{"tournaments": ["french open"],"seasons": ["2024", "2023", "2022", "2021", "2020"]}
Doubles only, with head-to-head
{"dayOffsets": ["-1"],"matchTypes": ["doubles"],"enrich": ["h2h"]}
Run it on a schedule to keep a dataset current: hourly during a Grand Slam, daily otherwise. Results flow into Google Sheets, Make, Zapier or your own webhook through Apify's integrations.
How to run the scraper and put it on a schedule (official Apify videos):
Pricing: Pay Per Event
You pay for what a run produces, not for time. Prices below are the standard rate; higher Apify plans get an automatic volume discount on every event.
Running it as a scraper
| Event | Per unit | Per 1,000 |
|---|---|---|
| Match in the dataset | $0.00199 | $1.99 |
| Bookmaker odds, per match per market | $0.00499 | $4.99 |
| Extra match detail, per match per section | $0.00599 | $5.99 |
| Run start | $0.005 | one per run |
A day of ATP and WTA singles, about 20 matches, costs around $0.05. The same day with odds is about $0.15.
Querying it as an API
| Event | Per unit | Per 1,000 |
|---|---|---|
Listing call (/matches, /live) | $0.00999 | one per call |
| Match returned by a listing | $0.00199 | $1.99 |
Match returned from a past season (/history) | $0.00199 | $1.99 |
| Bookmaker odds, per match per market | $0.00499 | $4.99 |
One match section (/match/{id}/...) | $0.00599 | $5.99 |
A match costs the same whether you scrape it or request it, so neither mode is the cheap way to get the same data. The listing call fee applies to every call, including one that matches nothing, so filter server-side rather than polling speculatively.
Free: /tournaments, /seasons, /draw, /match/{id}/available and
/health. Find what exists and what a season holds before you pay for any of it.
API usage also consumes Apify platform credit for the time the server is running, billed by Apify at your plan's rate and separate from the events above. It shuts down after a few idle minutes, so you pay for the time you actually use. If you query it only occasionally, running it as a scraper on a schedule is cheaper.
FAQ
What is Flashscore? Flashscore is a live-score service covering tennis alongside dozens of other sports, publishing scores, draws, statistics and bookmaker odds. This actor covers its tennis side: ATP, WTA, Challenger, ITF, juniors and team events, singles and doubles.
Does this include ATP and WTA?
Yes, plus ATP Challenger, ITF men's and women's, junior events (boys and girls) and team competitions. Filter with tours.
Can I get live tennis scores in real time? Yes. A live match returns the current set, the game score, who is serving, and whether a tiebreak is in play. Note that during a tiebreak the game score holds tiebreak points rather than 0/15/30/40.
Does it return set-by-set scores and tiebreaks? Yes, both. Every set returns games for each player and the tiebreak points where one was played, so a 7-6 set shows the breaker as 9-7 rather than leaving it blank.
Can I get bookmaker odds for tennis matches?
Yes, with includeOdds. You get match winner, over/under, handicap, correct score and odd/even, with opening and current prices, plus the best available price for every selection. Choose the market with oddsMarkets.
How far back does the historical tennis data go?
It depends on the tournament and on which data you want, so the actor reports it rather than promising a single year. Grand Slams reach much further back than Challengers, and statistics and point-by-point start much later than results do. Ask /seasons?tournament=X&season=Y and it tells you exactly what that season holds before you commit to it.
Can I get a player's whole career with serve and return statistics? Not by player here: this actor collects by day and by tournament. Tennis Abstract Scraper returns every match of an ATP or WTA player's career with serve and return counts, Elo ratings by surface and shot-by-shot point by point, and joins to this one on player name.
Does it cover doubles as well as singles? Yes. A doubles record carries both players per side with their own ids, nationalities and doubles rankings, and the pair's shared seed at match level.
Can I get point-by-point data?
Yes, via enrich: ["points"] or the /match/{id}/points endpoint. Break points, set points and match points are marked on the points where they occurred.
How do I get tennis data as an API instead of a dataset? Call the endpoints above. The actor runs as an HTTP server with 10 endpoints and answers requests directly; the base URL is in the examples.
Do I need to start the actor before calling it? No. The service answers each request directly and scales with demand; there is nothing to start, schedule or keep alive. You pay the per-request events and nothing else.
Do I need a proxy? No. There is no proxy option because none is needed, and adding one would only slow your runs down.
How do I export the data? JSON, CSV, Excel, XML or HTML from the run's Storage tab, or through the Apify API. JSON preserves the nested players, sets and odds structures; CSV flattens them.
Is it legal to scrape Flashscore tennis data? This actor extracts publicly available data only, nothing behind a login. You are responsible for complying with Flashscore's terms and with data protection law (GDPR, CCPA). Player names are personal data, so handle them accordingly.
Can I get football or basketball scores here? Not in this actor; it is tennis only. For other sports use Bet365 Live Scores for 13 sports, or Bet365 Sports Data for fixtures and history.
More Zen Studio scrapers for sports betting
🏟️ Sportsbook odds
Action Network
FanDuel
DraftKings
BetMGM
Bet365
🎯 Daily fantasy & player props
Player Props Aggregator
PrizePicks
Underdog Fantasy
Sleeper
DraftKings Pick6
Bet365
🎾 Live scores & match data
Tennis Abstract
Bet365
Support
- Bugs: Issues tab
- Features: Issues tab
Legal Compliance
Extracts publicly available data. Users must comply with Flashscore terms and data protection regulations (GDPR, CCPA).
Tennis match data from Flashscore: ATP, WTA, Challenger and ITF scores, statistics, point by point, rankings and bookmaker odds, as a dataset or a live API.
