Flashscore Tennis Scraper - Live Scores, Stats, H2H & Odds
Pricing
$1.00 / 1,000 tennis row delivereds
Flashscore Tennis Scraper - Live Scores, Stats, H2H & Odds
Scrape ATP, WTA, Challenger and ITF tennis from Flashscore: results, fixtures and live scores with set by set scores, tiebreaks and the current game score. Both doubles players are identified. Switch modes for statistics, head to head history or bookmaker odds. No proxy needed.
Pricing
$1.00 / 1,000 tennis row delivereds
Rating
0.0
(0)
Developer
Sourabh Kumar
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
3
Monthly active users
2 days ago
Last modified
Categories
Share
Flashscore tennis scraper: scores, statistics, head to head and odds
Pull tennis results and fixtures from Flashscore with set by set scores and tiebreaks. Switch modes to add match statistics, head to head history, or bookmaker odds with the opening price and how far it has moved.
$1 per 1,000 results. No per-run fee. Every mode, one flat price.
Covers ATP, WTA, Challenger, ITF men and women, juniors, and team events like the Davis Cup.
Why this scraper?
- ๐ต $1 per 1,000 rows with no per-run fee, so a run that returns nothing costs you nothing.
- ๐พ Four modes in one actor. Scores, statistics, head to head and odds usually mean four separate scrapers, each billing you separately.
- ๐ฅ Both doubles players, fully identified with their own ID, nationality and photo, so a mixed nationality pair is not flattened into one country.
- ๐ด Live game score and who is serving on in play matches, not just the set scores.
- โ ๏ธ Walkovers, withdrawals and retirements are flagged separately, so a 6-0 6-0 that never happened does not pollute your results.
- ๐ Odds carry the opening price and the movement, not just today's number, so you can see which way a line drifted.
- ๐ Read any country's bookmakers from one run. Great Britain returns up to 20, Brazil the widest Latin American set. No proxy setup, no VPN.
- โก Fast and cheap to run. Plain HTTP with no browser, so a 250 row pull finishes in about 13 seconds.
- ๐ฏ Filter before you pay. Narrow by tournament URL, tour, draw, surface, status or specific days, and matches with nothing published are skipped and never billed.
What data can you extract?
| ๐๏ธ Tournament and surface | ๐ Tournament URL | ๐ Start time (UTC) | ๐ Set by set scores |
| ๐ฅ Winner | ๐ข Tiebreak points | ๐ด Live game score | ๐พ Who is serving |
| ๐ Player nationality | ๐ Player IDs and slugs | ๐ฅ Both doubles players | ๐ผ๏ธ Player photos |
| โ ๏ธ Walkovers, withdrawals, retirements | ๐ฏ Aces and double faults | ๐พ Break points won and saved | ๐ฅ Winners and unforced errors |
| ๐ค Head to head record | ๐ Recent form both sides | ๐ฐ Bookmaker odds | ๐ Opening price and drift |
Scraping modes
๐พ Matches (default)
Fixtures and results for a date range, with set by set scores, tiebreaks, winner, nationality and tournament detail. Live matches also carry the current game score and the server.
{ "mode": "matches", "dateFrom": "2026-08-12", "dateTo": "2026-08-13", "tours": ["ATP", "WTA"], "drawType": "singles", "maxItems": 200 }
Point it at a tournament instead of a date range by pasting its Flashscore address:
{ "mode": "matches", "startUrls": ["https://www.flashscore.com/tennis/atp-singles/cincinnati/"], "maxItems": 200 }
Or pick individual days, which do not have to be next to each other:
{ "mode": "matches", "dayOffsets": ["0", "1"], "maxItems": 200 }
๐ Statistics
Twenty statistics per match and per set: aces, double faults, first serve percentage, break points saved and converted, winners, unforced errors, service and return points won.
{ "mode": "statistics", "tours": ["ATP", "WTA"], "statuses": ["finished"], "maxItems": 50 }
๐ค Head to head
Past meetings between the two players plus recent form for each side. Trim how much history you keep with h2hMaxPerSection.
{ "mode": "h2h", "tours": ["ATP"], "h2hMaxPerSection": 10, "maxItems": 25 }
๐ฐ Odds
Bookmaker prices for each match, with the opening price, the current price and the direction it moved. Pick the market with oddsCountry.
{ "mode": "odds", "oddsCountry": "GB", "oddsBetTypes": ["HOME_AWAY", "OVER_UNDER"], "oddsScopes": ["FULL_TIME"], "maxItems": 50 }
How to scrape Flashscore tennis: step by step
- Create a free Apify account. Takes 30 seconds, no card needed.
- Open Flashscore Tennis Scraper in the Apify Console.
- Pick a mode, then set a date range and any filters you want. Leave the dates empty for today.
- Click Start. Most runs finish in under 15 seconds.
- Export as JSON, CSV, or Excel, or fetch it from the API.
How much does Flashscore Tennis Scraper cost?
You pay $1.00 per 1,000 rows, and there is no per-run fee. The Apify Free plan gives you $5 in usage credits a month, which is roughly 5,000 rows. The $29/month Starter plan covers about 29,000 rows a month.
Rows are only charged when they are delivered. If a match has no statistics or no odds published, it is skipped and you are not billed for it.
Input
{"mode": "matches","dateFrom": "2026-08-12","dateTo": "2026-08-13","tours": ["ATP", "WTA"],"drawType": "singles","surfaces": ["hard"],"statuses": ["finished"],"tournamentQuery": ["Cincinnati", "Toronto"],"maxItems": 200}
| Field | Type | Default | Notes |
|---|---|---|---|
mode | string | matches | matches, statistics, h2h or odds |
startUrls | array | none | Flashscore tournament addresses. Keeps only matches from those tournaments |
dayOffsets | array | none | Individual days from -7 to 1. Replaces the date range, and they need not be consecutive |
dateFrom / dateTo | string | today | YYYY-MM-DD. Flashscore serves 7 days back through tomorrow |
tours | array | all | ATP, WTA, CHALLENGER, ITF_MEN, ITF_WOMEN, JUNIORS, TEAMS |
drawType | string | all | singles or doubles |
surfaces | array | all | hard, clay, grass, carpet |
statuses | array | all | scheduled, live, finished |
tournamentQuery | array | none | Keep tournaments whose name contains any one of these |
matchIds | array | none | Scrape exact match IDs and ignore every filter above |
maxItems | integer | 100 | Your cost ceiling, since you pay per row |
oddsCountry | string | GB | GB, BR, US, DE or IN. Odds mode only |
oddsBetTypes | array | HOME_AWAY | Also OVER_UNDER, ASIAN_HANDICAP, CORRECT_SCORE, ODD_OR_EVEN |
oddsScopes | array | FULL_TIME | Also FIRST_SET, SECOND_SET |
h2hMaxPerSection | integer | 10 | Past matches kept per section. H2H mode only |
How the filters combine. Entries inside one filter are an "any of" list, and separate filters all have to be satisfied. So two tournament URLs return matches from either one, but adding statuses: ["finished"] on top keeps only the finished ones. Note that Flashscore gives singles and doubles separate addresses, so a .../atp-singles/... URL returns no doubles.
Already have match IDs from an earlier run? Pass them straight in:
{ "mode": "odds", "matchIds": ["fqlRb8xp", "YT1HRITp"], "oddsCountry": "GB" }
Output
Matches
{"matchId": "fqlRb8xp","url": "https://www.flashscore.com/match/fqlRb8xp/","matchType": "singles","startTimestamp": 1786572600,"startTime": "2026-08-12T22:10:00.000Z","endTimestamp": 1786580150,"endTime": "2026-08-13T00:15:50.000Z","status": "finished","statusDetailCode": 3,"note": null,"isWalkover": false,"isWithdrawn": false,"isRetired": false,"endedEarly": false,"winner": "away","isInPlay": false,"currentGameScoreHome": null,"currentGameScoreAway": null,"server": null,"homePlayer": {"name": "Jodar R.","names": ["Jodar R."],"players": [{"name": "Jodar R.","participantId": "OdngshVK","playerId": "voyKqlqS","slug": "jodar-rafael","country": "Spain","countryId": 176,"imageUrl": "https://static.flashscore.com/res/image/data/zqkYjime-bJuw1oYE.png"}],"playerId": "voyKqlqS","participantId": "OdngshVK","participantId2": null,"slug": "jodar-rafael","abbreviation": "JOD","country": "Spain","countryId": 176,"imageUrl": "https://static.flashscore.com/res/image/data/zqkYjime-bJuw1oYE.png"},"awayPlayer": {"name": "Nakashima B.","names": ["Nakashima B."],"players": [{"name": "Nakashima B.","participantId": "ETGnbrpH","playerId": "80RkvS6k","slug": "nakashima-brandon","country": "USA","countryId": 200,"imageUrl": "https://static.flashscore.com/res/image/data/Ao55Oc7k-I3vxtblK.png"}],"playerId": "80RkvS6k","participantId": "ETGnbrpH","participantId2": null,"slug": "nakashima-brandon","abbreviation": "NAK","country": "USA","countryId": 200,"imageUrl": "https://static.flashscore.com/res/image/data/Ao55Oc7k-I3vxtblK.png"},"homeSetsWon": 0,"awaySetsWon": 2,"setsPlayed": 2,"sets": [{"set": 1,"home": 6,"away": 7,"homeTiebreak": 3,"awayTiebreak": 7},{"set": 2,"home": 4,"away": 6,"homeTiebreak": null,"awayTiebreak": null}],"scoreSummary": "6-7(3), 4-6","tournament": {"tournamentId": "IyRQC2vM","stageId": "jakzJP44","name": "Montreal","fullName": "ATP - SINGLES: Montreal (Canada), hard","tour": "ATP","tourLabel": "ATP - Singles","drawType": "singles","surface": "hard","country": "Canada","isQualification": false,"urlPath": "/tennis/atp-singles/montreal/","url": "https://www.flashscore.com/tennis/atp-singles/montreal/"},"scrapedAt": "2026-08-13T15:08:57.755Z"}
A doubles pair, with each player separated out. Marcelo Arevalo is Salvadoran and Mate Pavic is Croatian, so a single country on the row would be wrong for one of them:
{"matchId": "IarlCOB7","matchType": "doubles","homePlayer": {"name": "Arevalo M./Pavic M.","names": ["Arevalo M.", "Pavic M."],"players": [{ "name": "Arevalo M.", "participantId": "2Dnk4gai", "playerId": "8IxTwFIq", "slug": "arevalo-marcelo", "country": "El Salvador", "countryId": 70, "imageUrl": "https://static.flashscore.com/res/image/data/ClGancWH-jc6XgREf.png" },{ "name": "Pavic M.", "participantId": "zLNFemL9", "playerId": null, "slug": null, "country": "Croatia", "countryId": 59, "imageUrl": "https://static.flashscore.com/res/image/data/buhflOiT-OhNpdMM4.png" }],"participantId": "2Dnk4gai","participantId2": "zLNFemL9"}}
A live match, with the game score and the server:
{"matchId": "AN06zHRi","status": "live","isInPlay": true,"scoreSummary": "3-6, 7-6(5), 5-4","currentGameScoreHome": "0","currentGameScoreAway": "0","server": "away","endTime": null}
The game score is text, not a number: it is 0, 15, 30, 40 or A for advantage during a normal game, and a plain point count during a tiebreak.
Statistics
{"matchId": "fVjaLWSG","homePlayer": "Giron M.","awayPlayer": "Rocha H.","periods": ["Match", "Set 1", "Set 2"],"statisticsCount": 49,"statistics": [{ "period": "Match", "group": "Service", "stat": "Aces", "home": "2", "away": "5" },{ "period": "Match", "group": "Service", "stat": "1st serve percentage", "home": "52%", "away": "68%" },{ "period": "Match", "group": "Return", "stat": "Break Points Converted", "home": "2/8", "away": "3/9" }]}
Head to head
{"matchId": "C8MVcxVh","homePlayer": "Mejia N.","awayPlayer": "Fearnley J.","tournamentName": "Cincinnati","headToHeadCount": 1,"headToHead": [{"matchId": "C8MVcxVh","date": "2026-08-12T22:30:00.000Z","tournament": "Cincinnati","surface": "hard","homePlayer": "Mejia N.","awayPlayer": "Fearnley J.","score": "2:1","homeSetsWon": 2,"awaySetsWon": 1,"winner": "home"}],"homeRecentForm": [{ "date": "2026-08-12T22:30:00.000Z", "tournament": "Cincinnati", "score": "2:1", "winner": "home", "resultForSectionPlayer": "w" }],"awayRecentForm": [{ "date": "2026-08-12T22:30:00.000Z", "tournament": "Cincinnati", "score": "2:1", "winner": "home", "resultForSectionPlayer": "l" }]}
Odds
{"matchId": "YT1HRITp","homePlayer": "Siniakova K./Zhang S.","awayPlayer": "Mihalikova T./Nicholls O.","oddsCountry": "GB","bookmakerCount": 20,"offerCount": 74,"odds": [{"bookmakerId": 15,"bookmakerName": "William Hill","betType": "HOME_AWAY","betScope": "FULL_TIME","side": "home","playerName": "Siniakova K./Zhang S.","opening": "1.4","current": "1.22","movement": "down"}]}
Use cases
- ๐ Model building and backtesting. Pull results with set by set detail to train or check a match prediction model.
- ๐ Line movement tracking. Compare the opening price against the current one across 20 bookmakers to spot where money went.
- ๐ Bookmaker comparison. See which book is offering the best price on the same match in Britain, Brazil, Germany, the US or India.
- ๐ฐ Live scoreboards and content. Feed a site, newsletter or bot with fixtures and results across every tour.
- ๐พ Player form research. Combine head to head history with recent form to preview a matchup.
- ๐ Serve and return analysis. Use the per set statistics to break down where a match was won.
- ๐ค Fantasy and prediction games. Score entries against real results without maintaining a scraper yourself.
- ๐๏ธ Building a results archive. Run daily to accumulate history well past the nine day window Flashscore itself serves.
Limitations
- Nine day window. Flashscore publishes 7 days of past results plus today and tomorrow, so run daily if you want a longer archive.
- Three things Flashscore does not publish for tennis: player rankings, round name, and best of three or five. A "ranking" field on another scraper whose value repeats across unrelated players from the same country is the country ID, which this actor names
countryIdand never calls a rank. - No match duration, and it is not guessable. The only timestamps in the source are the scheduled start and a marker for the end of the last completed set, so a match that starts two hours late would look two hours longer than it was. This actor ships neither a duration nor a guess.
- End time only on finished matches. It is null while a match is in play, and absent on some finished lower tier matches where Flashscore never recorded it.
- Doubles pairs carry one player ID. Both players get a name, participant ID, nationality and photo; the longer
playerIdand profileslugare for the lead player only, and the three letter abbreviation is singles only. - Odds are pre-match, and statistics need a started match. Live in play pricing is not claimed, and scheduled matches have no statistics yet so they are skipped and never charged.
FAQ
How much does Flashscore Tennis Scraper cost?
It uses pay-per-result pricing. You pay $1.00 for 1,000 results and there is no per-run fee. The Apify Free plan gives you $5 in usage credits a month, enough for around 5,000 results. If you run regularly, the $29/month Starter plan covers about 29,000 results.
No subscription lock-in. Pause whenever.
Is it legal to scrape Flashscore?
Scraping public data is generally allowed in the US and most of the EU, as long as you don't collect personal data covered by GDPR or CCPA without a lawful basis. This actor only touches publicly accessible pages, but how you use the output is on you.
Apify's full breakdown: Is web scraping legal?.
Can I integrate it with other tools?
Push results into Make, Zapier, Slack, Airbyte, GitHub, Google Sheets, Google Drive, and more. Apify treats every actor as a webhook source, so anything that consumes webhooks or pulls from an API works.
Full list: Apify integrations.
Can I use it with the Apify API?
Yes. Every run is available via the Apify REST API:
curl -X POST "https://api.apify.com/v2/acts/sourabhbgp~flashscore-tennis-scraper/runs?token=APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"mode": "matches", "tours": ["ATP"], "maxItems": 50}'
Docs: Apify API reference.
Can I use it through an MCP Server?
Yes. Apify ships an MCP server that exposes every actor as a tool, so Claude Desktop, Cursor, and any other MCP-capable client can call this scraper. Setup: Apify MCP docs.
Your feedback
Bug, missing field, or odd behavior? Drop a note in the Issues tab. Reports go to a human and fixes usually ship the same week.