Football Results Scraper - Goals, Cards & Stats, All Leagues avatar

Football Results Scraper - Goals, Cards & Stats, All Leagues

Pricing

from $3.65 / 1,000 match returneds

Go to Apify Store
Football Results Scraper - Goals, Cards & Stats, All Leagues

Football Results Scraper - Goals, Cards & Stats, All Leagues

For football bettors, fantasy players and data teams: results from every league on Flashscore with goal scorers, assists, cards, substitutions, half-time score, round and stats incl. xG. 3,260 of 3,260 matches matched Flashscore's page in a 3-day check. Monitoring returns only matches that changed.

Pricing

from $3.65 / 1,000 match returneds

Rating

0.0

(0)

Developer

NeverEmpty

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

For football bettors, fantasy players and data teams: every match Flashscore lists, across all countries and leagues, with teams, league, round, score, half-time score, winner, red cards and status, plus goal scorers with assists and minute, cards, substitutions, referee, attendance and match statistics including xG. In a check on 2026-09-21, 3,260 of 3,260 matches over 3 days matched Flashscore's own page field by field. Ask by date, league name or team name - no match ids to look up - and turn on monitoring so a schedule receives only the matches that finished or whose score changed.

Export as JSON, CSV or Excel.

What you get

One row per match, for any day from 7 days back to 7 days ahead:

  • League: country or region, league name, Flashscore's header (ENGLAND: Premier League), league id and page, and the round (Round 5, Quarter-finals), read from the match page because Flashscore's daily feed does not carry it.
  • Teams: home and away as Flashscore shows them, with Flashscore team id, slug and short code.
  • Score: the score, half-time score, 90-minute score, score after extra time, penalty shoot-out score, winner (home, away or draw) and how it was decided (regular-time, extra-time, penalties), red cards per team.
  • Status: scheduled, live (with the period and the minute), finished, postponed, cancelled, interrupted, abandoned, awarded and more, with Flashscore's own status text.
  • Events (matches that have started): goals with scorer, assist, minute, penalty or own goal and the score after it; yellow, second-yellow and red cards with the reason; substitutions; missed penalties; half scores; referee, stadium, city, attendance and capacity.
  • Statistics (matches that have started): possession, shots, shots on target, corners, fouls, offsides, yellow cards and xG as columns, and every statistic Flashscore shows (passes, big chances, xGOT, tackles...) for the match and each half in statistics.

Between 2026-09-14 and 2026-09-20 Flashscore's daily football feed carried 171 to 1,780 matches a day (weekend days the most).

How it matches Flashscore's page

The rows come from the same feeds Flashscore's website reads, assembled the way the page assembles them:

  1. The daily feed can be minutes old. It is served from a cache, so the page applies Flashscore's recent-changes feed on top right after loading. This Actor does the same, and every row says whether that step worked in liveUpdatesApplied. When the cached copy that answered is older than two minutes the Actor asks again (up to twice) and keeps the freshest; feedAgeSeconds says how old it was.
  2. Each day's feed also carries matches that belong to the day before or after. Flashscore's page does not show them on that day, and neither does this Actor: a match is returned under the day it starts on in your time zone.
  3. After a penalty shoot-out Flashscore's feed adds one goal to the winner. The page shows the real score and the shoot-out in brackets, and so does this Actor: homeScore / awayScore are the goals after extra time, the shoot-out is in penaltiesHomeScore / penaltiesAwayScore.
  4. The half-time score is not in the daily feed; it is the 90-minute score minus the second-half score, which matched the half scores of Flashscore's match pages on every match checked.

The check behind the numbers above: Flashscore's football page was opened in a browser on 2026-09-21 for three days with every collapsed league expanded, and at the same moment the daily and recent-changes feeds were read. Every match on the page (3,260) was compared on team names, score, penalty shoot-out score, red cards, status text, the live minute, the start time and the day it is listed on: 3,260 of 3,260 matched.

Input

FieldWhat it does
daysDays to read: today, yesterday, tomorrow, a number from -7 to 7, or YYYY-MM-DD. Empty = today. Days outside Flashscore's 15-day window are refused before anything is requested.
utcOffsetHoursYour time zone as hours from UTC (0 = UTC). Decides where a day starts, as on Flashscore in that time zone. startTime is always UTC.
countriesKeep only these countries or regions as Flashscore names them (England, Spain, Europe, World). Whole name, case-insensitive.
leaguesKeep a match if its league matches one of these: Flashscore's header or part of it (england: premier league, champions league), the league path (england/premier-league) or a league URL. premier league alone also keeps other countries' Premier Leagues.
teamsKeep a match if one of these appears in the home or away team name or slug (partial, case-insensitive).
matchStatuseslive, finished, scheduled, other (postponed, cancelled, interrupted...). Empty = all.
includeEventsOn (default) = one extra request per returned match that has started, for goals, cards, substitutions, referee and attendance.
includeStatisticsOn (default) = one extra request per returned match that has started, for match statistics.
includeRoundOn (default) = one small extra request per returned match to read the round from its page (only the first 32 KB are read). Off = faster, round is null.
maxMatchesMaximum rows to return (default 200, up to 3,000). Not used in monitoring mode.
monitoringModeReturn only matches that changed since the row last returned for them. Needs at least one of countries, leagues or teams, unless monitorEveryLeague is on.
monitorEveryLeagueAllow monitoring with no country, league or team filter. Off (default) = such a run is refused with a free row, because its first run would return and charge every match of the day.
changeDetailIn monitoring mode: score (default: a goal, a red card, extra-time or shoot-out score, or a change of status such as kick-off or full time; half time and the minute do not count) or finished (each match once, when it reaches a final state: finished, walkover, awarded, cancelled or abandoned).
resetMonitoringStateForget the remembered rows for this filter set, so everything counts as new.
useProxyOn (default) = if Flashscore answers 401, 403, 429 or 503, retry through an Apify proxy.

Example: yesterday's and today's results from the Premier League and LaLiga, in London summer time.

{
"days": ["yesterday", "today"],
"utcOffsetHours": 1,
"leagues": ["england: premier league", "spain: laliga"],
"matchStatuses": ["finished"]
}

Output

A finished match returned by a monitoring run (change and the previous... fields appear only in monitoring mode; statistics is cut to 3 of its 101 entries here):

{
"source": "flashscore.com",
"status": "ok",
"matchId": "fZCq6HE7",
"matchUrl": "https://www.flashscore.com/match/fZCq6HE7/",
"date": "2026-09-20",
"utcOffsetHours": 0,
"startTime": "2026-09-20T13:00:00.000Z",
"country": "England",
"league": "Premier League",
"leagueHeader": "ENGLAND: Premier League",
"leagueId": "dYlOSQOD",
"leagueUrl": "https://www.flashscore.com/football/england/premier-league/",
"round": "Round 5",
"matchStatus": "finished",
"statusText": "Finished",
"statusCode": 3,
"isLive": false,
"isFinished": true,
"livePeriod": null,
"liveMinute": null,
"statusChangedAt": "2026-09-20T14:57:59.000Z",
"homeTeam": "Manchester City",
"homeTeamId": "Wtn9Stg0",
"homeTeamSlug": "manchester-city",
"homeTeamShort": "MCI",
"awayTeam": "Sunderland",
"awayTeamId": "WSzc94ws",
"awayTeamSlug": "sunderland",
"awayTeamShort": "SUN",
"homeScore": 5,
"awayScore": 3,
"scoreText": "5-3",
"winner": "home",
"winnerTeam": "Manchester City",
"decidedBy": "regular-time",
"halfTimeHomeScore": 3,
"halfTimeAwayScore": 2,
"regularTimeHomeScore": 5,
"regularTimeAwayScore": 3,
"extraTimeHomeScore": null,
"extraTimeAwayScore": null,
"penaltiesHomeScore": null,
"penaltiesAwayScore": null,
"homeRedCards": 0,
"awayRedCards": 0,
"info": null,
"scrapedAt": "2026-09-21T15:00:00.000Z",
"liveUpdatesApplied": true,
"feedAgeSeconds": null,
"change": "status-changed",
"previousMatchStatus": "live",
"previousScoreText": "4-3",
"previousHomeScore": 4,
"previousAwayScore": 3,
"previousReturnedAt": "2026-09-20T17:08:00.000Z",
"eventsStatus": "ok",
"goals": [
{
"period": "1st Half",
"minute": "9",
"minuteValue": 9,
"team": "home",
"player": "Fernandez E.",
"playerId": "nZnbEVWP",
"type": "goal",
"assist": null,
"assistId": null,
"homeScoreAfter": 1,
"awayScoreAfter": 0
},
{
"period": "1st Half",
"minute": "12",
"minuteValue": 12,
"team": "away",
"player": "Brobbey B.",
"playerId": "pfAvgQUT",
"type": "goal",
"assist": "Le Fee E.",
"assistId": "hC5yfF2A",
"homeScoreAfter": 1,
"awayScoreAfter": 1
},
{
"period": "1st Half",
"minute": "29",
"minuteValue": 29,
"team": "home",
"player": "Cherki R.",
"playerId": "vm0eu2V3",
"type": "goal",
"assist": "Semenyo A.",
"assistId": "r1Gz1yPk",
"homeScoreAfter": 2,
"awayScoreAfter": 1
},
{
"period": "1st Half",
"minute": "33",
"minuteValue": 33,
"team": "away",
"player": "Brobbey B.",
"playerId": "pfAvgQUT",
"type": "goal",
"assist": "Meunier T.",
"assistId": "WUyrShAL",
"homeScoreAfter": 2,
"awayScoreAfter": 2
},
{
"period": "1st Half",
"minute": "43",
"minuteValue": 43,
"team": "home",
"player": "Semenyo A.",
"playerId": "r1Gz1yPk",
"type": "goal",
"assist": "Guehi M.",
"assistId": "KEeklutO",
"homeScoreAfter": 3,
"awayScoreAfter": 2
},
{
"period": "2nd Half",
"minute": "57",
"minuteValue": 57,
"team": "home",
"player": "Semenyo A.",
"playerId": "r1Gz1yPk",
"type": "goal",
"assist": null,
"assistId": null,
"homeScoreAfter": 4,
"awayScoreAfter": 2
},
{
"period": "2nd Half",
"minute": "59",
"minuteValue": 59,
"team": "away",
"player": "Brobbey B.",
"playerId": "pfAvgQUT",
"type": "goal",
"assist": "Angulo N.",
"assistId": "GtWYwr5H",
"homeScoreAfter": 4,
"awayScoreAfter": 3
},
{
"period": "2nd Half",
"minute": "81",
"minuteValue": 81,
"team": "home",
"player": "Haaland E.",
"playerId": "UmV9iQmE",
"type": "goal",
"assist": "Gvardiol J.",
"assistId": "86K1f1fd",
"homeScoreAfter": 5,
"awayScoreAfter": 3
}
],
"goalsText": "9' Fernandez E. [home]; 12' Brobbey B. [away]; 29' Cherki R. [home]; 33' Brobbey B. [away]; 43' Semenyo A. [home]; 57' Semenyo A. [home]; 59' Brobbey B. [away]; 81' Haaland E. [home]",
"goalsListed": 8,
"goalsComplete": true,
"cards": [
{
"period": "1st Half",
"minute": "8",
"minuteValue": 8,
"team": "away",
"player": "Methalie D.",
"playerId": "v71VNtNg",
"card": "yellow",
"reason": "Roughing",
"onBench": false
}
],
"substitutions": [
{
"period": "2nd Half",
"minute": "60",
"minuteValue": 60,
"team": "away",
"playerIn": "Fofana M.",
"playerInId": "6N65iDOI",
"playerOut": "Angulo N.",
"playerOutId": "GtWYwr5H"
},
{
"period": "2nd Half",
"minute": "68",
"minuteValue": 68,
"team": "away",
"playerIn": "Isidor W.",
"playerInId": "veOg2tx3",
"playerOut": "Sadiki N.",
"playerOutId": "UJnCIUV6"
},
{
"period": "2nd Half",
"minute": "75",
"minuteValue": 75,
"team": "home",
"playerIn": "Doku J.",
"playerInId": "lMHcYK4f",
"playerOut": "Ndiaye I.",
"playerOutId": "Im0c6Oy7"
},
{
"period": "2nd Half",
"minute": "79",
"minuteValue": 79,
"team": "away",
"playerIn": "Hume T.",
"playerInId": "CfLIw4XG",
"playerOut": "Meunier T.",
"playerOutId": "WUyrShAL"
},
{
"period": "2nd Half",
"minute": "85",
"minuteValue": 85,
"team": "home",
"playerIn": "O'Reilly N.",
"playerInId": "xOrYaNWc",
"playerOut": "Cherki R.",
"playerOutId": "vm0eu2V3"
}
],
"missedPenalties": [],
"periods": [
{
"period": "1st Half",
"homeScore": 3,
"awayScore": 2
},
{
"period": "2nd Half",
"homeScore": 2,
"awayScore": 1
}
],
"referee": "Jones R.",
"venue": "Etihad Stadium",
"city": "Manchester",
"attendance": 60312,
"venueCapacity": 61038,
"statisticsStatus": "ok",
"statistics": [
{
"period": "Match",
"group": "Top stats",
"name": "Expected goals (xG)",
"home": "2.81",
"away": "3.57"
},
{
"period": "Match",
"group": "Top stats",
"name": "Ball possession",
"home": "55%",
"away": "45%"
},
{
"period": "Match",
"group": "Top stats",
"name": "Total shots",
"home": "16",
"away": "17"
}
],
"homePossession": 55,
"awayPossession": 45,
"homeShots": 16,
"awayShots": 17,
"homeShotsOnTarget": 6,
"awayShotsOnTarget": 9,
"homeCorners": 6,
"awayCorners": 5,
"homeXg": 2.81,
"awayXg": 3.57,
"homeFouls": 14,
"awayFouls": 14,
"homeYellowCards": 0,
"awayYellowCards": 1,
"homeOffsides": 0,
"awayOffsides": 0,
"roundStatus": "ok"
}

Notes on the columns:

  • homeScore / awayScore are null before kick-off. For a match decided on penalties they are the goals after extra time; the shoot-out is in penaltiesHomeScore / penaltiesAwayScore. regularTimeHomeScore is the score after 90 minutes, extraTimeHomeScore after extra time (null when there was none).
  • halfTimeHomeScore / halfTimeAwayScore are filled once the first half is over.
  • homeRedCards / awayRedCards count red cards (including second yellows) as Flashscore shows them on the list; null before kick-off.
  • livePeriod is first-half, half-time, second-half, extra-time, break or penalties. liveMinute is worked out the way Flashscore's page does it (minutes since the period started, 45+2 / 90+3 in added time) and can be a minute off the page.
  • statusCode is Flashscore's own status number; statusText is Flashscore's text for it; matchStatus is one of scheduled, live, finished, walkover, awarded, cancelled, postponed, interrupted, abandoned, delayed, awaiting-updates, to-finish (or ended / unknown for a status number Flashscore adds later).
  • goals[].team is the side the goal counts for; an own goal (type: "own-goal") is credited to the other team, so player plays for the opposite side. goals[].type is goal, penalty or own-goal. Penalty shoot-out kicks are not listed as goals.
  • cards[].card is yellow, second-yellow or red; onBench is true for a card shown to someone not on the pitch.
  • eventsStatus: ok, no-incidents-listed (Flashscore lists only the half scores for this match, common in lower leagues), not-available (Flashscore returned no events at all for this match), not-started, unreadable or not-requested. Lower leagues often list a goal without the scorer's name (player is null, shown as ? in goalsText). goalsListed is how many goals have a named scorer; goalsComplete is true only when every goal scored has a named scorer.
  • statisticsStatus: ok, not-available (Flashscore has no statistics for this match), not-started, unreadable or not-requested. The home... / away... statistic columns are numbers (possession in percent); statistics keeps Flashscore's text such as 85% (406/475). xG is only there for leagues where Flashscore shows it.
  • roundStatus: ok, not-shown (the match page shows no round), unreadable or not-requested.
  • info is Flashscore's note on the match, such as First leg result: 2-1. Aggregate: 3-1.
  • change (monitoring): "first-check" (not returned before for this filter set), "status-changed" or "score-changed".
  • Odds, TV listings, line-ups and commentary text are not included.

Rows that are not charged

When something is not returned, a row says why. These rows have no matchId and cost nothing:

statusMeaning
no-resultsFlashscore lists no matches for the day(s) asked for.
no-filter-matchMatches were read, none fit your filters.
no-changeMonitoring: no match changed since its last returned row.
not-returnedMore matches fit than maxMatches; the row says how many.
budget-reachedThe run hit its maximum total charge; the row says how many matches were not returned.
day-out-of-rangeFlashscore did not return the day (outside its 7-back / 7-ahead window).
blockedFlashscore refused the request even after retrying.
unreadableFlashscore's answer could not be read. Nothing is guessed.
invalid-inputThe input could not be used; nothing was requested.

Monitoring

Run the Actor on a schedule with monitoringMode on. The first run returns every match that fits your filters (with changeDetail: "finished", every match that has already ended). Later runs compare each match with the row last returned for it and return only the ones that changed, with the previous score and status next to the new ones, and with fresh goals, cards and statistics.

  • Every match compared is a check, also the first time a match is seen. A match that was already returned in a final state (finished, walkover, awarded, cancelled or abandoned) and has not changed is not charged a check.
  • A match is listed on the day it starts. For a schedule that runs across midnight, put ["yesterday", "today"] in days, or a late match that ends after midnight drops off the list before its result is returned.
  • With matchStatuses: ["live"] a match leaves your filter when it ends, so its final result is not returned. Keep finished in the filter to receive results.
  • A match that looks older than the row already returned for it (an older cached copy of Flashscore's feed, or a goal Flashscore took back) is not returned as a change.
  • Rows are remembered per filter set (countries, leagues, teams, matchStatuses, changeDetail) for 10 days after the match starts, so two schedules with different filters do not affect each other.
  • maxMatches is not used in monitoring mode, so no match is left out behind the limit. For the same reason monitoring needs at least one of countries, leagues or teams: with no filter, the first run would return every match of the day (up to about 1,800). Turn on monitorEveryLeague if that is what you want.
  • A row is remembered only after it was delivered and charged. If a run hits its maximum total charge, the matches it could not return are not remembered as returned, so they still count as changed when they are compared again.
  • Do not put the same filter set in two schedules that can run at the same time: the remembered rows live in a key-value store without atomic updates, so this cannot be fully prevented.

Pricing

Pay per event, no start fee:

  • $5.00 per 1,000 match rows, charged only for rows with status: "ok". Goals, cards, statistics and the round are included in the row price.
  • $0.30 per 1,000 match checks in monitoring mode.

Example: 20 matches you follow, checked every 5 minutes for 3 hours, is 720 checks, which is $0.22, plus $0.005 for each change row (a goal, a red card, kick-off or full time). Checking every match of a busy Saturday (about 1,800) every 5 minutes for 12 hours would be 259,200 checks, so use filters for frequent schedules.

Notes

  • Unofficial. Public data only. Not affiliated with Flashscore or Livesport. Data is what Flashscore shows publicly and can change or be corrected by Flashscore.
  • Only Flashscore's football feeds and match pages that its robots.txt allows are read; standings, draws and news are not.
  • Requests are spaced out: a 0.4 s pause before each request, and at most 3 matches' details in flight at once. With goals, statistics and the round on, a run takes about 0.75 s per match row (1,329 rows took 16 minutes on 2026-09-21); the log reports progress every 100 rows.