Flashscore Matches Scraper: Scores, Timeline and Odds
Pricing
from $0.35 / 1,000 matches
Flashscore Matches Scraper: Scores, Timeline and Odds
Scrape Flashscore matches for football, tennis and basketball into one row per match: teams, score, half-time and period scores, status, start time and winner, for any day up to 7 days back or ahead. Add goals, cards and substitutions, and UK bookmaker odds. JSON, CSV or Excel. By MrBridge
Flashscore Matches Scraper
Flashscore Matches Scraper collects football, tennis and basketball matches from Flashscore (https://www.flashscore.com), one clean row per match, ready for JSON, CSV or Excel. It reads the public match feeds of the site, so no account and no API key are needed. Each row gives the teams or players, the tournament, the start time, the status, the score, the half-time score, the winner and a link to the match page. You can add the timeline of incidents of football matches and the betting odds of each match.
Pick football, keep today as the day and set maxItems to 20: the Actor returns 20 matches with their tournament, kick-off time, status and score. Turn on the timeline to get each goal, card and substitution with its minute and player, or turn on the odds to get the prices that operators listed in the United Kingdom show for the match.
What is Flashscore Matches Scraper?
Flashscore is a live-score website that lists the matches of thousands of tournaments, with scores updated during play. The Actor reads its day feeds for you. It selects sports and days, applies your league filter, removes duplicates and returns one structured row per match. The first 23 columns follow a fixed sports-matches layout, documented below, so the rows are easy to compare with other sources that use the same layout.
What data can I extract with it?
One row per match: source, match ID, match link, sport, country, tournament and its ID, season, round, start time, normalized status and status as Flashscore writes it, elapsed minute of a live match, home and away team with their IDs, score, half-time score, winner and scrape time. Then the Flashscore columns: tournament stage ID, tournament category, tournament link, country ID, score of each period, note, last update time, and the optional timeline and odds.
How can I use the results?
- Build a results archive of the leagues you follow, one day at a time.
- Feed a dashboard or a newsletter with today's fixtures and yesterday's scores.
- Study how often home teams win in a tournament, using the winner and half-time columns.
- Track the goals, cards and substitutions of finished football matches.
- Compare the odds shown by several operators for the same match, as information for your own analysis.
How to use it
- Open the Actor in Apify Console.
- Pick the sports and the days, and add leagues if you want to narrow the list.
- Set
maxItems, then start the run. Rows appear in the dataset as they are delivered.
Input
| Field | Meaning | Default |
|---|---|---|
sports | football, tennis, basketball. At least one | ["football"] |
dateOffsets | Days from today (UTC): 0 is today, -1 yesterday, 1 tomorrow. Integers from -7 to 7 | [0] |
dates | Calendar days as YYYY-MM-DD, within 7 days of today (UTC). Added to dateOffsets | empty |
leagues | Keep only these tournaments, up to 100. Empty keeps all (see the four forms below) | empty |
maxItems | Hard cap on match rows returned and billed, 1 to 10000 | 100 |
includeTimeline | Add the timeline of incidents of football matches | false |
includeOdds | Add the betting odds of each match | false |
oddsMarkets | Markets kept in odds. At least one. ALL keeps every market | HOME_DRAW_AWAY, HOME_AWAY, OVER_UNDER, BOTH_TEAMS_TO_SCORE, DOUBLE_CHANCE |
The Console form pre-fills sports with football, dateOffsets with 0 and maxItems with 20. Example input:
{"sports": ["football"],"dateOffsets": [0],"maxItems": 20}
leagues is a local filter on the matches read. Case is ignored and a match is kept when it fits any entry. Each entry takes one of four forms:
- the full header as Flashscore shows it, for example
ALGERIA: Ligue 2 - the tournament ID, for example
MJijSTCe - the tournament path, with or without the slashes, for example
/football/algeria/ligue-2/orfootball/algeria/ligue-2 - the tournament path without the sport, for example
algeria/ligue-2
oddsMarkets accepts HOME_DRAW_AWAY, HOME_AWAY, OVER_UNDER, BOTH_TEAMS_TO_SCORE, DOUBLE_CHANCE, DRAW_NO_BET, ODD_OR_EVEN, CORRECT_SCORE, HALF_FULL_TIME, ASIAN_HANDICAP, EUROPEAN_HANDICAP and ALL. It is used only when includeOdds is on. The default keeps the rows light, because one full answer can hold more than 1 700 odds and most of them are correct scores.
Invalid input ends the run successfully with one BAD_INPUT row in the errors dataset that lists every problem, and no match row.
Output
Matches go to the default dataset, one row per match. Problems go to a separate errors dataset and are never billed. The OUTPUT record of the key-value store summarizes the run. The dataset has three views: overview, timeline and odds.
The first 23 columns are the common layout, in this order:
| Field | Type | Meaning |
|---|---|---|
source | string | Always Flashscore |
matchId | string | Flashscore match ID, the key of the row |
url | string or null | Flashscore page of the match |
sport | string | football, tennis or basketball |
country | string or null | Country or region of the tournament |
tournament | string or null | Tournament name |
tournamentId | string or null | Flashscore tournament ID |
season | null | Null for rows of the day feed |
round | null | Null for rows of the day feed |
startTime | string or null | ISO 8601 in UTC |
status | string | scheduled, live, finished, postponed, cancelled, abandoned, interrupted or unknown |
statusRaw | string or null | The status as Flashscore writes it |
minute | null | Null for rows of the day feed |
homeTeam, awayTeam | string or null | Team, or player in tennis |
homeTeamId, awayTeamId | string or null | Flashscore IDs |
homeScore, awayScore | integer or null | Final or current score |
homeScoreHalfTime, awayScoreHalfTime | integer or null | Half-time score |
winner | string or null | home, away or draw for a finished match |
scrapedAt | string | Time the row was built, ISO 8601 in UTC |
Then the Flashscore columns:
| Field | Type | Meaning |
|---|---|---|
tournamentStageId | string or null | Flashscore ID of the tournament stage |
tournamentCategory | string or null | Category of the tournament, such as the tennis tour or the country group |
tournamentUrl | string or null | Flashscore page of the tournament |
countryId | string or null | Flashscore ID of the country or category group |
periodScores | array | Score of each period (half, set or quarter), objects { period, home, away }. [] when absent |
note | string or null | Note of Flashscore on the match, for example a disqualification |
updatedAt | string or null | Last update of the match on Flashscore, ISO 8601 in UTC |
timeline | array or null | Incidents of a football match, see below |
odds | array or null | Betting odds, see below |
Every field is always present, with null when Flashscore gives no value, and [] for periodScores when absent.
This is one real row from the example input above, built by the Actor from stored Flashscore responses:
{"source": "Flashscore","matchId": "K0CceoUN","url": "https://www.flashscore.com/match/K0CceoUN/","sport": "football","country": "Algeria","tournament": "Ligue 2","tournamentId": "MJijSTCe","season": null,"round": null,"startTime": "2026-11-06T14:00:00.000Z","status": "finished","statusRaw": "Finished","minute": null,"homeTeam": "Azazga","homeTeamId": "p8oVs3AG","awayTeam": "MSP Batna","awayTeamId": "21SPlgRt","homeScore": 3,"awayScore": 2,"homeScoreHalfTime": 1,"awayScoreHalfTime": 1,"winner": "home","scrapedAt": "2026-11-07T12:00:00.000Z","tournamentStageId": "dtbtP8nA","tournamentCategory": "Algeria","tournamentUrl": "https://www.flashscore.com/football/algeria/ligue-2/","countryId": "18","periodScores": [{"period": 1,"home": 1,"away": 1},{"period": 2,"home": 2,"away": 1}],"note": null,"updatedAt": "2026-11-06T15:57:32.000Z","timeline": null,"odds": null}
The example comes from a test fixture captured on 2026-11-06, so the scores and statuses are those of that day.
Timeline
Set includeTimeline to true to fill timeline for football matches that have started. Each element is one incident:
| Field | Meaning |
|---|---|
id | Incident ID |
period | Period name, for example 1st Half |
side | home or away |
minute, addedTime, minuteText | Minute, added time and the minute as Flashscore shows it |
type, typeCode | Incident type, such as Goal, Yellow Card or Substitution - Out, and its code |
player, playerId, playerUrl | The player concerned |
reason | Reason, when Flashscore gives one |
homeScore, awayScore | Score after the incident, when it applies |
related | Linked players, such as the assist of a goal or the player coming on |
{"id": "vBqDdB2c","period": "1st Half","side": "home","minute": 43,"addedTime": null,"minuteText": "43'","type": "Goal","typeCode": 3,"player": "Orsini N.","playerId": "UyqTS9An","playerUrl": "https://www.flashscore.com/player/orsini-nicolas/UyqTS9An/","reason": null,"homeScore": 1,"awayScore": 0,"related": [{"type": "Assistance","player": "Bogarin R.","playerId": "tpCGHIpe","playerUrl": "https://www.flashscore.com/player/bogarin-rodrigo/tpCGHIpe/"}]}
timelineis[]for a football match that is scheduled, postponed or cancelled, and no request is made for it.timelineisnullwhen you did not ask for it, for tennis and basketball rows, and when the summary of the match could not be read.
Odds
Set includeOdds to true to fill odds for every match that is not cancelled, postponed or abandoned. Each element is one price of one operator:
| Field | Meaning |
|---|---|
bookmakerId, bookmaker | Operator ID and name. The name is null when Flashscore does not list it |
market | Market, such as HOME_DRAW_AWAY or OVER_UNDER |
scope | Part of the match the price covers, such as FULL_TIME or FIRST_HALF |
outcome | home, draw or away for the result markets, home_or_draw, draw_or_away or home_or_away for double chance. Null for the other markets |
participant | home or away when the price belongs to one side |
selection | The selection of the market, for example OVER for an over/under price |
handicap | The line, as a number, for handicap and over/under markets |
winner | Raw text of the source for a half-time/full-time price, for example 1/1 |
score, bothTeamsToScore | Set for correct score and both-teams-to-score prices |
odds, openingOdds | Current and opening decimal odds. openingOdds is null when there is no opening price |
active | Whether the price is still open |
{"bookmakerId": 14,"bookmaker": "10bet","market": "HOME_DRAW_AWAY","scope": "FIRST_HALF","outcome": "home","participant": "home","selection": null,"handicap": null,"winner": null,"score": null,"bothTeamsToScore": null,"odds": 3.95,"openingOdds": 3.2,"active": false}
oddsis[]when no price was kept by youroddsMarketschoice, or when no operator shows a price.oddsisnullwhen you did not ask for it, for a cancelled, postponed or abandoned match, and when the odds could not be read.- Operators without prices give nothing and bonus offers are never returned.
Billing
One match event is billed per delivered row. One match-timeline event is billed on top for a row delivered with a non-empty timeline, and one match-odds event for a row delivered with at least one odds element. Errors, duplicates, filtered-out matches, empty timelines and empty odds are never billed. The Pricing tab of the Actor shows the current prices.
When the platform moves a run to another server or restarts it while it works, the run picks up where it was. A match already returned is neither returned nor billed again.
Limits
season,roundandminuteare null for the rows of the day feed.- The day is the day of Flashscore. The feed covers 7 days before to 7 days after today (UTC).
datesare added todateOffsets, so today is part of the selection only whendateOffsetsholds 0, which the Console form pre-fills. - A match close to midnight can appear in two day feeds. It is returned once.
- The timeline exists for football only. Tennis and basketball rows keep
timelinenull. - Odds are seen from the United Kingdom: the operators and markets are those shown there. Finished matches carry closing odds. Basketball matches often have no odds.
oddsMarketsneeds at least one market whenincludeOddsis on.- If the day feed answers 401, the run records a
TARGET_BLOCKEDrow withhttpStatus401, which means the feed signature was refused. - If the host of the odds or the summary host refuses three requests in a row, only that option stops. The rows already read are kept, the option stays null for the rest of the run, and
oddsStoppedByortimelineStoppedBysaysblockedin theOUTPUTrecord. - A run with both options sends about two more requests per match than a run without them, so it lasts longer. For large runs, raise the run timeout.
- Each run is a snapshot of Flashscore at that moment. Scores and odds move, so two runs a minute apart can differ.
Run summary and early stops
The OUTPUT record counts requests, pages, matches, errors and the add-ons: timelinesEmitted, timelinesCharged, timelineRequests, oddsEmitted, oddsCharged and oddsRequests. extraByEvent gives the emitted and charged count of each add-on event.
stoppedBy says why a run ended early. It keeps the first reason only.
null: all the requested work was done.maxItems: themaxItemscap was reached.chargeLimit: the maximum charge set for the run was reached.deadline: the run reached its internal time limit.circuitOpen: too many blocked responses in a row.pageBudget: the request budget of the run was spent.badInput: reserved value of the run summary. This Actor never sets it, because Flashscore answers are sorted into blocked, rate limited, not found or failed. An input the Actor cannot use is reported before any request, as a singleBAD_INPUTrow in theerrorsdataset, andstoppedBystaysnull.fetchFailed: the last walk ended on a page that could not be fetched.failedWalkslists the first 20 failed walks.
Every business error is written to the errors dataset with a kind: BAD_INPUT, TARGET_BLOCKED, RATE_LIMITED, FETCH_FAILED, UPSTREAM_ERROR, SCHEMA_CHANGED, LISTING_INVALID or NOT_FOUND. The OUTPUT record counts errors in errorsByKind.
Frequently asked questions
Why do I get fewer matches than maxItems?
The days and sports you chose hold fewer matches than the cap, or your leagues narrow the list. When Flashscore has no more matching matches, the run ends with stoppedBy set to null.
Why is odds empty on some rows?
Basketball matches often have no odds from the operators listed in the United Kingdom, and a cancelled, postponed or abandoned match gets no odds request. Check odds for null (not obtained) and [] (nothing kept).
Is there a similar Actor for another site?
Yes, SofaScore Sports Scraper returns the same 23 first columns, so rows from both sources fit in one table. SofaScore adds the venue, the referee, the managers and the line-ups, but no odds. Both return a football timeline, only this Actor returns odds.
Can I use Flashscore Matches Scraper via MCP?
Yes. Any Apify Actor can be called from an MCP client through the Apify MCP server. See the Apify MCP documentation for the setup.
Your feedback
We are always working on improving our Actors. If you have technical feedback for Flashscore Matches Scraper or found a bug, please create an issue on the Actor's Issues tab.
More free tools, scrapers, MCP servers and data studies from the same team: mr-bridge.com.
Legal and responsible use
The data comes from the public pages of Flashscore (https://www.flashscore.com) and belongs to its owners. Flashscore has its own terms of use, and it may restrict automated access or commercial reuse. Odds are given as information and are not betting advice. Before you rely on the output, in particular for commercial use, confirm that your use is permitted by the terms that apply. You remain responsible for how you use the results and for complying with the source's terms and with the laws that apply to you.