# Football-Data.co.uk Scraper - Results, Stats & Odds (`parseforge/football-data-couk-scraper`) Actor

Scrape 240,000+ football matches from Football-Data.co.uk: 38 competitions, results, half-time scores, shots, cards, corners, referees, xG, and 1X2 / over-under / Asian handicap odds from 22 bookmakers.

- **URL**: https://apify.com/parseforge/football-data-couk-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** Developer tools, Other
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.67 / 1,000 matches

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

[![ParseForge](https://raw.githubusercontent.com/ParseForge/apify-assets/main/banner.jpg)](https://apify.com/parseforge?fpr=vmoqkp)

### Football-Data.co.uk Scraper - Results, Stats & Odds

**Every match Football-Data.co.uk publishes, normalised into one schema.** 304,000+ played matches across 38 competitions and 34 seasons, with full-time and half-time scores, shots, corners, cards, referees, expected goals, and 1X2, over/under and Asian handicap prices from 22 bookmakers. No API key, no login, no proxy. Export to CSV, JSON, Excel, or XML.

It is the football API alternative for anyone who needs history rather than live scores: one soccer dataset covering three decades, queryable by league, season, team, referee, scoreline, or price. Football-Data.co.uk is the reference free archive for football betting research, but it ships as 726 separate CSV files across which 233 distinct column names have appeared: `HomeTeam` is `HT` in the old Greek files, `FTHG` is `HG` in the extra leagues, 15 files are Windows-1252 rather than UTF-8, and a bookmaker that quoted every match in 2007 has no column at all in 2021. This Actor reads all of it, resolves every alias, and returns one stable row per match.

| Who uses it | What they pull |
|---|---|
| Bettors and traders | Closing lines, market margin, and pre-match to closing drift |
| Quants and modellers | Decades of results plus odds, ready to back-test |
| Data scientists | A labelled corpus with the market's own probability attached |
| Sports journalists | Head-to-head records, streaks, and league tables on demand |
| App and site builders | Fixtures with opening prices, refreshed on a schedule |

### What it does

The Actor downloads the season files you select, parses them, and writes one row per match. A row can carry:

- ⚽ **The match:** competition, country, tier, season, date, kick-off time, both teams, full-time and half-time score.
- 📊 **Every result flag already computed:** total goals, goal difference, both-teams-scored, over 0.5/1.5/2.5/3.5, clean sheets, second-half goals, comeback detection, and league points for each side.
- 🥅 **Match statistics** (opt-in): referee, shots, shots on target, corners, fouls, free kicks conceded, offsides, woodwork, yellows, reds, booking points, attendance, expected goals, plus shot accuracy and conversion rate.
- 💷 **Bookmaker odds** (opt-in): 1X2, over/under 2.5 and Asian handicap, pre-match and closing, from up to 22 books including Bet365, Pinnacle, William Hill, bwin, BetVictor, Ladbrokes, Betfred, BetMGM, Coral, Paddy Power, Sky Bet, 1XBet and the Betfair Exchange.
- 📈 **Market consensus** (opt-in): best and average price across the whole market for each market, and how many books that average was built from.
- 🧮 **Betting analytics** (opt-in): implied and margin-free probabilities, overround, fair odds, favourite and underdog, best available price, expected-value edge, Kelly fraction, steamer/drifter flags, closing line value, and the settled profit or loss of a one-unit bet on each outcome.
- 🔁 **Head-to-head and form** (opt-in): the two sides' entire meeting history in that competition, and both teams' rolling record going into the match.
- 🏆 **League tables** (opt-in): a full table per competition-season, with split home and away records.

### What you can do with football data

**📉 Back-test a betting model.**

Pull twenty seasons with closing odds and betting analytics on. Every row already carries the fair probability, the margin, and the P/L of a one-unit bet, so a strategy test is a `groupby` away.

**🎯 Measure closing line value.**

Turn on closing odds and analytics, and read `clvWinnerPercent` per match to see whether the price you would have taken beat the close.

**🧠 Train a match-outcome model.**

Combine results, shots, expected goals and team form into a feature table without joining four sources by hand — the form block is computed as of kick-off, so there is no leakage from the future.

**🔎 Find market inefficiencies.**

Filter on bookmaker margin, favourite side, or steamers over a threshold, and look at how often the drift was right.

**📅 Track this week's fixtures.**

Switch to the fixtures dataset and schedule it: upcoming matches with the current opening prices from every book that has quoted them.

### Why choose this scraper

| | What you get |
|---|---|
| **Nothing to authenticate** | No API key, no account, no cookie. The source is public static hosting. |
| **No proxy cost** | Measured HTTP 200 on every surface with a bare request. There is no proxy line on your bill. |
| **38 competitions in one run** | 22 European divisions, the biggest back to 1993/94, plus 16 more from Argentina to Japan. |
| **Every legacy column resolved** | Old alias names, retired bookmakers, and the 15 Windows-1252 files all land in the same schema. |
| **Opt-in extras, off by default** | Ten separate blocks, each its own checkbox. Leave them off and you are never billed for them. |
| **Filters cut before billing** | Filters run on the complete match, so you can filter on shots or margin without buying those columns. |
| **Pick by country** | One checkbox brings in every tier that country has, and a per-competition cap keeps one league from eating the run. |
| **Signals already computed** | Fair probabilities, margin, CLV, form and head-to-head, ready to sort. |
| **Odds in your format** | Decimal, fractional on the traditional UK ladder, or American. |

### How it compares

Be clear about the trade-off before you pick this one.

**The source CSVs are free.** Football-Data.co.uk hands anyone 726 files at no cost, and if you want one season of one league you should just download it. What you are paying for here is the other 725 files: the alias resolution, the encoding fallback, the filters, the computed analytics, the head-to-head and form indexes, and a scheduled run that keeps a warehouse table current without you maintaining a parser.

The only other Actor on this source takes four inputs — one league, one season, an odds on/off switch, and a row cap.

| Feature | ParseForge | crawlerbros/football-data-uk-scraper | Downloading the CSVs yourself |
|---|---|---|---|
| Leagues per run | 38, any number at once | One | Any, by hand |
| Seasons per run | Any range, 1993/94 onward | One | Any, by hand |
| Per-bookmaker odds resolved by name | 22 books | One on/off switch | Raw column names |
| Closing odds and pre-match drift | Yes | No | Raw columns only |
| Computed probabilities, margin, CLV | Yes | No | No |
| Head-to-head and pre-match form | Yes | No | No |
| League tables | Yes | No | No |
| Legacy alias columns resolved | Yes | No | No |
| Upcoming fixtures with prices | Yes | No | Yes, separate file |
| Filters | 42 | None | None |
| Price per 1,000 matches | $3.00 | Per dataset item | Free |

If your job is "download E0 for 2024/25 once", the free CSV wins and you should take it.

### What a match looks like

Every match returns as one JSON row: 52 base columns plus one nested object per block you enabled. Here is a real record from a run with every block on, trimmed to four bookmakers:

```json
{
  "matchId": "300fd497fd08e094",
  "recordType": "match",
  "status": "played",
  "source": "football-data.co.uk",
  "sourceUrl": "https://www.football-data.co.uk/mmz4281/2526/E0.csv",
  "competitionId": "E0",
  "competitionName": "Premier League",
  "country": "England",
  "countryCode": "GB-ENG",
  "tier": 1,
  "leagueType": "main",
  "season": "2526",
  "seasonLabel": "2025/26",
  "seasonStartYear": 2025,
  "date": "2025-08-15",
  "dateRaw": "15/08/2025",
  "time": "20:00",
  "dayOfWeek": "Friday",
  "isWeekend": false,
  "homeTeam": "Liverpool",
  "awayTeam": "Bournemouth",
  "fullTimeHomeGoals": 4,
  "fullTimeAwayGoals": 2,
  "fullTimeResult": "H",
  "resultLabel": "Home win",
  "scoreline": "4-2",
  "winner": "Liverpool",
  "loser": "Bournemouth",
  "isDraw": false,
  "halfTimeHomeGoals": 1,
  "halfTimeAwayGoals": 0,
  "halfTimeResult": "H",
  "secondHalfHomeGoals": 3,
  "secondHalfAwayGoals": 2,
  "totalGoals": 6,
  "goalDifference": 2,
  "absGoalDifference": 2,
  "bothTeamsScored": true,
  "over05": true, "over15": true, "over25": true, "over35": true, "under25": false,
  "homeCleanSheet": false,
  "awayCleanSheet": false,
  "homeFailedToScore": false,
  "awayFailedToScore": false,
  "isComeback": false,
  "comebackTeam": null,
  "homePoints": 3,
  "awayPoints": 0,
  "stats": {
    "referee": "A Taylor",
    "attendance": null,
    "homeShots": 19,
    "awayShots": 10,
    "homeShotsOnTarget": 10,
    "awayShotsOnTarget": 3,
    "homeShotAccuracy": 0.5263,
    "awayShotAccuracy": 0.3,
    "homeConversionRate": 0.2105,
    "awayConversionRate": 0.2,
    "totalShots": 29,
    "totalShotsOnTarget": 13,
    "homeCorners": 6,
    "awayCorners": 7,
    "totalCorners": 13,
    "homeFouls": 7,
    "awayFouls": 10,
    "homeYellowCards": 1,
    "awayYellowCards": 2,
    "homeRedCards": 0,
    "awayRedCards": 0,
    "totalCards": 3,
    "homeExpectedGoals": null,
    "awayExpectedGoals": null
  },
  "odds1x2": {
    "bet365": {
      "home": 1.3,
      "draw": 6,
      "away": 8.5
    },
    "pinnacle": {
      "home": 1.28,
      "draw": 6.56,
      "away": 9.07
    },
    "betfairExchange": {
      "home": 1.34,
      "draw": 6.6,
      "away": 9.4
    },
    "bookmakerCount": 9
  },
  "closingOdds": {
    "bet365": {
      "home": 1.29,
      "draw": 6.25,
      "away": 9
    },
    "pinnacle": {
      "home": 1.29,
      "draw": 6.55,
      "away": 9.75
    },
    "bookmakerCount": 9,
    "marketMax": {
      "home": 1.31,
      "draw": 6.6,
      "away": 9.5
    },
    "marketAverage": {
      "home": 1.29,
      "draw": 6.02,
      "away": 8.68
    }
  },
  "overUnder": {
    "prematch": {
      "bet365": {
        "over": 1.36,
        "under": 3.2
      },
      "line": 2.5,
      "marketAverage": {
        "over": 1.35,
        "under": 3.13
      },
      "bookmakerCount": 3
    },
    "closing": {
      "bet365": {
        "over": 1.36,
        "under": 3.2
      },
      "line": 2.5,
      "marketAverage": {
        "over": 1.36,
        "under": 3.05
      },
      "bookmakerCount": 3
    }
  },
  "asianHandicap": {
    "prematch": {
      "bet365": {
        "home": 1.83,
        "away": 2.03,
        "line": null
      },
      "line": -1.5,
      "lineLabel": "Home -1.5",
      "marketAverage": {
        "home": 1.78,
        "away": 1.99
      },
      "bookmakerCount": 3
    },
    "closing": {
      "line": -1.75,
      "lineLabel": "Home -1.75",
      "marketAverage": {
        "home": 1.94,
        "away": 1.76
      },
      "bookmakerCount": 3
    }
  },
  "marketConsensus": {
    "maxHome": 1.34,
    "maxDraw": 6.5,
    "maxAway": 9.5,
    "avgHome": 1.31,
    "avgDraw": 5.96,
    "avgAway": 8.31,
    "maxClosingHome": 1.31,
    "avgClosingHome": 1.29,
    "bookmakersUsed1x2": null
  },
  "analytics": {
    "referenceSource": "market average",
    "referenceIsClosingPrice": false,
    "bookmakersPricing": 9,
    "referenceHomeOdds": 1.31,
    "referenceDrawOdds": 5.96,
    "referenceAwayOdds": 8.31,
    "closingHomeOdds": 1.29,
    "closingDrawOdds": 6.02,
    "closingAwayOdds": 8.68,
    "impliedProbabilityHome": 0.7634,
    "overround": 0.0515,
    "overroundPercent": 5.15,
    "fairProbabilityHome": 0.726,
    "fairProbabilityDraw": 0.1596,
    "fairProbabilityAway": 0.1144,
    "fairOddsHome": 1.377,
    "favourite": "home",
    "favouriteOdds": 1.31,
    "favouriteProbability": 0.726,
    "underdog": "away",
    "underdogOdds": 8.31,
    "favouriteWon": true,
    "underdogWon": false,
    "isUpset": false,
    "winnerOdds": 1.31,
    "profitHome": 0.31,
    "profitDraw": -1,
    "profitAway": -1,
    "profitFavourite": 0.31,
    "bestPriceHome": 1.34,
    "bestValueSide": "away",
    "bestValueEdgePercent": 8.72,
    "bestValueKellyFraction": 0.0103,
    "oddsMovementHomePercent": -1.53,
    "steamerSide": "home",
    "drifterSide": "away",
    "closingOverround": 0.0565,
    "clvWinnerPercent": 1.55
  },
  "headToHead": {
    "meetings": 16,
    "homeTeamWins": 13,
    "draws": 1,
    "awayTeamWins": 2,
    "homeTeamWinRate": 0.8125,
    "averageTotalGoals": 3.63,
    "bothTeamsScoredRate": 0.3125,
    "over25Rate": 0.8125,
    "lastMeetingDate": "2025-02-01",
    "lastMeetingScore": "0-2",
    "lastMeetingWinner": "Liverpool",
    "last5Results": [
      "2024-09-21 Liverpool 3-0 Bournemouth",
      "2025-02-01 Bournemouth 0-2 Liverpool"
    ],
    "homeVenueMeetings": 8,
    "homeVenueWins": 7
  },
  "form": {
    "window": 6,
    "home": {
      "matchesPlayed": 6,
      "wins": 2,
      "draws": 2,
      "losses": 2,
      "points": 8,
      "pointsPerGame": 1.33,
      "goalsFor": 12,
      "goalsAgainst": 10,
      "goalDifference": 2,
      "formString": "WWLDLD",
      "currentStreak": "1D",
      "unbeatenRun": 1,
      "cleanSheets": 1
    },
    "away": {
      "matchesPlayed": 6,
      "wins": 2,
      "draws": 2,
      "losses": 2,
      "points": 8,
      "pointsPerGame": 1.33,
      "goalsFor": 6,
      "goalsAgainst": 6,
      "goalDifference": 0,
      "formString": "DDWLLW",
      "currentStreak": "1W",
      "unbeatenRun": 1,
      "cleanSheets": 2
    }
  },
  "scrapedAt": "2026-08-25T17:23:30.191Z"
}
```

Field counts with everything on: 52 base columns, 38 statistics, up to 22 bookmakers × 3 prices per market, 15 market-consensus columns, 56 analytics columns, 14 head-to-head columns and 27 form columns.

With **League tables** on, the run also writes `recordType: "standing"` rows: team, position, played, W/D/L, goals for and against, goal difference, points, points per game, split home and away records, clean sheets, both-teams-scored and over-2.5 counts, and recent form.

### What the source actually carries

Coverage is not uniform, and the Actor does not invent columns. Measured across all 726 files:

| Data | Available from | Where |
|---|---|---|
| Result, half-time score | 1993/94 | Every main league |
| Shots, corners, fouls, cards, referee | 2000/01 | Main leagues |
| Attendance, woodwork, offsides, booking points | 2000/01 - 2001/02 only | England, Scotland, Germany |
| Bet365 1X2 and over/under 2.5 | 2002/03 | Main leagues |
| BetBrain market aggregates | 2005/06 - 2018/19 | Main leagues (retired since) |
| Pinnacle | 2012/13 | Main leagues |
| Extra leagues (closing odds only) | 2012 | Argentina, Brazil, MLS and 13 more |
| Free kicks conceded instead of fouls | 2017/18 - 2018/19 | France 2, Belgium, Greece |
| Kick-off time, closing odds, market max/average, Asian handicap line | 2019/20 | Main leagues |
| Betfair Exchange prices | 2024/25 | Main leagues |
| Expected goals (xG) | 2026/27 | 17 of 22 main leagues |

Bookmakers come and go: Bet365 prices appear in 544 of the 710 season files, Pinnacle in 308, BetMGM in only 22. The `bookmakerCount` on each odds block tells you how many actually priced that match.

### Configure the run

Pick leagues, pick a season range, tick the blocks you want. The Input tab lists all 64 parameters, 42 of them filters.

One Premier League season, results only:

```json
{ "leagues": ["E0"], "seasonFrom": "2025/26", "seasonTo": "2025/26" }
```

Twenty seasons of the big five, with odds and analytics, for a back-test:

```json
{
  "leagues": ["E0", "SP1", "I1", "D1", "F1"],
  "seasonFrom": "2005/06", "seasonTo": "2025/26",
  "includeOdds1x2": true,
  "includeClosingOdds": true,
  "includeMarketConsensus": true,
  "includeBettingAnalytics": true
}
```

Every upset at 6.00 or longer, last two seasons:

```json
{
  "leagues": ["E0", "E1", "E2", "E3"],
  "upsetsOnly": true,
  "upsetMinOdds": 6.0,
  "includeBettingAnalytics": true
}
```

Matches with a sending off, filtered without buying the statistics columns:

```json
{ "leagues": ["SP1"], "seasonFrom": "2015/16", "minRedCards": 1 }
```

The 2025/26 Premier League table, plus the matches it was built from:

```json
{ "leagues": ["E0"], "seasonFrom": "2025/26", "seasonTo": "2025/26", "includeStandings": true }
```

This week's fixtures with the current prices:

```json
{ "leagues": ["E0", "SP1", "I1"], "dataset": "fixtures", "includeOdds1x2": true }
```

Every Scottish tier, three matches each, only where at least seven books priced the game:

```json
{
  "countries": ["Scotland"],
  "seasonFrom": "2024/25", "seasonTo": "2024/25",
  "matchesPerLeague": 3,
  "minBookmakerCount": 7,
  "includeOdds1x2": true
}
```

Argentina and MLS, with head-to-head history:

```json
{ "extraLeagues": ["ARG", "USA"], "seasonFrom": "2023", "includeHeadToHead": true }
```

### Pricing

Pay-per-event. You are billed per match row written, plus a small fee for each season file downloaded and a $0.054 run-start fee. Filtered-out matches cost nothing.

| Event | Price | When it fires |
|---|---|---|
| Run start | $0.054 | Once per run |
| Season file | $0.02 | Each CSV downloaded for your selection |
| Match | $0.003 | Each match row written |
| Match statistics | $0.001 | Only with **Match statistics** on |
| Pre-match 1X2 odds | $0.0015 | Only with **Pre-match 1X2 odds** on |
| Closing 1X2 odds | $0.0015 | Only with **Closing 1X2 odds** on |
| Over / under odds | $0.001 | Only with **Over / under 2.5 goals** on |
| Asian handicap odds | $0.001 | Only with **Asian handicap odds** on |
| Market max and average | $0.001 | Only with **Market maximum and average** on |
| Betting analytics | $0.002 | Only with **Betting analytics** on |
| Head-to-head history | $0.003 | Only with **Head-to-head history** on |
| Team form | $0.002 | Only with **Team form** on |
| League table row | $0.01 | Only with **League tables** on |

| What you collect | Approximate cost |
|---|---|
| One Premier League season (380 matches) | $1.21 |
| The same season with closing odds and analytics | $2.54 |
| The same season with every block on | $6.53 |
| 10,000 matches, results only | $30.60 |

Turning on all nine per-match blocks adds $0.014 per match on top of the $0.003 base. Most runs need one or two of them.

Every block is off by default. A run that leaves them off pays the run-start fee, $0.02 per season file, and $0.003 per match. A block is billed only on the rows where it is actually returned: when the source file has no such column the block is omitted, so a 1996 match with no odds columns fires no odds event.

### Free users

Free-plan runs return up to 10 matches as a preview. [Upgrade your Apify plan](https://console.apify.com/sign-up?fpr=vmoqkp) to collect up to 1,000,000 matches per run.

### Run it

1. [Create a free Apify account with $5 in credit](https://console.apify.com/sign-up?fpr=vmoqkp).
2. Open the [Football-Data.co.uk Scraper](https://apify.com/parseforge/football-data-couk-scraper?fpr=vmoqkp).
3. Pick your leagues and season range, tick any extra blocks, and click **Start**.
4. Export the results as CSV, Excel, JSON, or XML from the **Dataset** tab.

Run it programmatically through the [Apify API](https://docs.apify.com/api/v2) or the [ApifyClient](https://docs.apify.com/api/client/js) for JavaScript and Python.

### Use with AI agents (MCP)

Give an AI agent live access to the football archive through the Model Context Protocol. Add the Actor to Claude, Cursor, or any MCP client:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=parseforge/football-data-couk-scraper"
```

Then prompt it in plain language:

- *"Pull every Premier League match since 2020 where the away side won at odds above 5.00."*
- *"Build me the 2025/26 Serie A table and the head-to-head record for the top two."*
- *"Get this weekend's La Liga fixtures with the current Bet365 and Pinnacle prices."*

Copy this into ChatGPT, Claude, or Cursor to start:

```
Use the Apify Actor "parseforge/football-data-couk-scraper" to collect football results and betting odds from Football-Data.co.uk. Input: { "leagues": ["E0"], "extraLeagues": [], "seasonFrom": "2020/21", "seasonTo": "2025/26", "includeOdds1x2": true, "includeBettingAnalytics": true, "maxItems": 500 }. League codes: E0-E3/EC England, SC0-SC3 Scotland, D1/D2 Germany, I1/I2 Italy, SP1/SP2 Spain, F1/F2 France, N1 Netherlands, B1 Belgium, P1 Portugal, T1 Turkey, G1 Greece. Extra league codes: ARG AUT BRA CHN DNK FIN IRL JPN MEX NOR POL ROU RUS SWE SWZ USA. Every extra block is off by default and billed separately. Call it with the ApifyClient and my APIFY_TOKEN.
```

### Troubleshooting

**Why are the odds columns empty?**

The season predates them. Bet365 prices start in 2002/03, Pinnacle in 2012/13, closing odds and market averages in 2019/20, and the extra leagues carry closing odds only. Check `bookmakerCount` — zero means the file had no book for that match.

**Why are there no shots or cards?**

Match statistics start in 2000/01 and the extra leagues never carry them. The block is simply absent on those rows rather than filled with nulls.

**Why did my filter return nothing?**

Most filters read a column that only exists in some seasons. `minAttendance` only matches 2000/01 and 2001/02 English, Scottish and German matches; `oddsMovement` needs closing odds, so 2019/20 onward; `minExpectedGoals` needs 2026/27.

**A league-season came back empty.**

Not every division ran in every season. The National League starts in 2005/06, Scottish League One and Two in 1997/98, and Football-Data sometimes publishes a division late — the German Bundesliga file for a new season can lag the others by weeks. The Actor logs the missing file and carries on.

**Why is a fixtures run returning old matches?**

The main `fixtures.csv` is refreshed with the week's games. The extra-league fixtures file is updated on Football-Data's own schedule and can sit stale for months; the Actor warns when it does.

**Head-to-head or form is slow.**

Both blocks index the entire archive of every competition you selected — that is up to 726 downloads before the first row is written. Narrow the leagues if you only need a few.

**Team names do not match my other source.**

Football-Data uses short forms: `Man United`, `Nott'm Forest`, `Ath Madrid`, `Paris SG`, `Bayern Munich`. They are stable across seasons, which makes them good join keys, but they are not the clubs' full names.

### FAQ

| Question | Answer |
|---|---|
| Do I need an API key or an account? | No. Football-Data.co.uk serves these files anonymously. |
| Do I need a proxy? | No. Measured HTTP 200 on every surface without one. A proxy option exists if your own network blocks the site. |
| How far back does it go? | 1993/94 for the biggest divisions, 2012 for the extra leagues. |
| How many matches are there in total? | 304,000+ played matches across 38 competitions. |
| Which bookmakers are included? | Up to 22, depending on the season. Bet365, Pinnacle, William Hill, bwin, Interwetten, BetVictor, VC Bet, Ladbrokes, Betfred, BetMGM, Coral, Paddy Power, Sky Bet, Betfair, Betfair Exchange, 1XBet, Gamebookers, Sportingbet, Stan James, Blue Square, Stanleybet and Sporting Odds. |
| Does it include expected goals? | Yes, where the source has it — Football-Data started publishing xG in 2026/27. |
| Can I get league tables? | Yes, with the **League tables** checkbox. They are built from every match in the files the run downloaded, so a filtered run still returns a real table. |
| Is the form block leak-free? | Yes. Form and head-to-head are computed only from matches played before that kick-off. |
| Can I get odds in American or fractional format? | Yes, with **Odds format**. Analytics stay decimal so the maths keeps working. |
| Why is this not free, when the CSVs are? | You are paying for the parsing, the alias resolution, the analytics, and a run you can schedule. If one file is all you need, take the free CSV. |
| How many matches per run? | Free plan: 10. Paid: up to 1,000,000. |
| Is this an official Football-Data.co.uk product? | No. It is unofficial and reads only public files. |

### Related actors

- [FBref Soccer Stats Scraper](https://apify.com/parseforge/fbref-scraper?fpr=vmoqkp): advanced per-player and per-team football statistics.
- [Soccerway Football Results Scraper](https://apify.com/parseforge/soccerway-scraper?fpr=vmoqkp): fixtures, results, and tables from Soccerway.
- [The Odds API Sports Scraper](https://apify.com/parseforge/the-odds-api-sports-scraper?fpr=vmoqkp): live sportsbook odds across many sports.
- [FanDuel Sportsbook Odds Scraper](https://apify.com/parseforge/fanduel-scraper?fpr=vmoqkp): current FanDuel lines and prices.
- [TheSportsDB Scraper](https://apify.com/parseforge/thesportsdb-scraper?fpr=vmoqkp): teams, players, and event metadata across sports.

Browse the full [ParseForge collection](https://apify.com/parseforge?fpr=vmoqkp) for more scrapers.

🆘 **Need help?** Email parseforge@protonmail.com with your run ID, your input, and what you expected.

⚠️ **Disclaimer.** This Actor is unofficial and is not affiliated with, endorsed by, or sponsored by Football-Data.co.uk or any bookmaker named in this page. It collects only publicly available files. You are responsible for using the data in compliance with the source's terms and applicable laws. Gambling carries risk — nothing here is betting advice.

# Actor input Schema

## `leagues` (type: `array`):

The 22 divisions Football-Data.co.uk publishes as one file per season, with match statistics and per-bookmaker odds. Coverage starts in 1993/94 for the biggest divisions; the National League starts in 2005/06 and the Scottish lower tiers in 1997/98.

## `extraLeagues` (type: `array`):

The 16 non-European-core competitions published as one all-seasons file each, from 2012 onward. These carry closing odds only — no shots, cards, corners or referee.

## `countries` (type: `array`):

Shortcut for picking every division a country has. Adds to whatever you selected above; England alone brings in all five English tiers.

## `dataset` (type: `string`):

Played matches from the season archives, the upcoming fixtures file with its opening odds, or both.

## `seasonFrom` (type: `string`):

Oldest season to include. Accepts 2020/21, 2020-21, 2020 or the site's own 2021 code. Leave this empty and it starts at the oldest season the league has; leave both season fields empty and the run returns the two most recent seasons.

## `seasonTo` (type: `string`):

Newest season to include, same formats as above. Leave it empty to run through to the current season.

## `dateFrom` (type: `string`):

Drop matches played before this date. Applied on top of the season range.

## `dateTo` (type: `string`):

Drop matches played after this date.

## `includeMatchStats` (type: `boolean`):

Referee, shots, shots on target, corners, fouls, free kicks conceded, offsides, woodwork, yellow and red cards, booking points, attendance, expected goals, and the shot-accuracy and conversion rates derived from them. Available from 2000/01 in the main leagues; the extra leagues never carry it.

## `includeOdds1x2` (type: `boolean`):

Home / draw / away prices from every bookmaker in the file — up to 22 books including Bet365, Pinnacle, William Hill, bwin, Interwetten, BetVictor, Ladbrokes, Betfred, BetMGM, Coral, Paddy Power, Sky Bet, 1XBet and the Betfair Exchange.

## `includeClosingOdds` (type: `boolean`):

The same books priced again just before kick-off. Published from 2019/20 onward. This is the column serious models score themselves against.

## `includeOverUnder` (type: `boolean`):

Over and under 2.5-goal prices, pre-match and closing, per bookmaker plus the market maximum and average.

## `includeAsianHandicap` (type: `boolean`):

The handicap line and its home / away prices, pre-match and closing, per bookmaker plus market maximum and average.

## `includeMarketConsensus` (type: `boolean`):

Best price and mean price across the whole market for 1X2, over/under and Asian handicap, pre-match and closing, plus how many books each average was built from. Includes the retired BetBrain aggregates for older seasons.

## `includeBettingAnalytics` (type: `boolean`):

Implied and margin-free probabilities, bookmaker overround, fair odds, favourite and underdog, best available price, expected-value edge and Kelly fraction, pre-match to closing drift with steamer / drifter flags, closing line value, and the settled profit or loss of a one-unit bet on each outcome.

## `includeHeadToHead` (type: `boolean`):

Every previous meeting between the two sides in that competition before this match: record, average goals, both-teams-scored and over-2.5 rates, the last meeting, and the last five scorelines. Downloads and indexes the division's full archive, so it is the most expensive block here.

## `includeTeamForm` (type: `boolean`):

Rolling record for both sides over their previous matches in that competition: points, points per game, goals for and against, clean sheets, W/D/L form string, current streak and unbeaten run. Also indexes the full archive.

## `includeStandings` (type: `boolean`):

Adds a league-table row per team per competition-season, built from the matches this run collected: position, played, W/D/L, goals, goal difference, points, points per game, split home and away records, clean sheets, both-teams-scored and over-2.5 counts, and recent form.

## `formWindow` (type: `integer`):

How many previous matches the team-form block looks back over. Only used when Team form is on.

## `teams` (type: `array`):

Keep only matches involving these clubs. Case- and punctuation-insensitive, so "man united" matches "Man United". Football-Data uses short forms — Man United, Tottenham, Ath Madrid, Bayern Munich, Paris SG.

## `teamMatchMode` (type: `string`):

Whether the team filter should match the home side, the away side, or either.

## `excludeTeams` (type: `array`):

Drop matches involving any of these clubs.

## `referees` (type: `array`):

Keep only matches with these referees. Football-Data writes them as initial plus surname, e.g. "M Oliver", "A Taylor".

## `fullTimeResults` (type: `array`):

Keep only these full-time outcomes.

## `halfTimeResults` (type: `array`):

Keep only these half-time outcomes.

## `minTotalGoals` (type: `integer`):

Matches with at least this many goals.

## `maxTotalGoals` (type: `integer`):

Matches with at most this many goals.

## `minHomeGoals` (type: `integer`):

Home side scored at least this many.

## `maxHomeGoals` (type: `integer`):

Home side scored at most this many.

## `minAwayGoals` (type: `integer`):

Away side scored at least this many.

## `maxAwayGoals` (type: `integer`):

Away side scored at most this many.

## `minGoalDifference` (type: `integer`):

Keep only matches won by at least this many goals.

## `bothTeamsScored` (type: `string`):

Filter on whether both sides got on the scoresheet.

## `comebacksOnly` (type: `boolean`):

Keep only matches where the side trailing at half time did not lose.

## `daysOfWeek` (type: `array`):

Keep only matches played on these days.

## `kickoffFrom` (type: `string`):

Earliest kick-off time to keep, as HH:MM in the time the site publishes. Kick-off times exist from 2019/20 onward.

## `kickoffTo` (type: `string`):

Latest kick-off time to keep, as HH:MM.

## `minShots` (type: `integer`):

Combined shots by both sides. Needs a season that carries match statistics.

## `minShotsOnTarget` (type: `integer`):

Combined shots on target by both sides.

## `minCorners` (type: `integer`):

Combined corners by both sides.

## `minFouls` (type: `integer`):

Combined fouls by both sides.

## `minYellowCards` (type: `integer`):

Combined yellow cards.

## `minRedCards` (type: `integer`):

Combined red cards. Set to 1 for matches with a sending off.

## `minAttendance` (type: `integer`):

Crowd size. Only the 2000/01 and 2001/02 English, Scottish and German files carry attendance.

## `minExpectedGoals` (type: `number`):

Combined expected goals. Football-Data started publishing xG in 2026/27. Decimal, e.g. 2.5.

## `minHomeOdds` (type: `number`):

Reference home price, read from the market average and falling back to Pinnacle, then Bet365, then whatever book the file carries. Decimal, e.g. 1.50.

## `maxHomeOdds` (type: `number`):

Upper bound on the reference home price. Decimal, e.g. 3.00.

## `minDrawOdds` (type: `number`):

Lower bound on the reference draw price. Decimal, e.g. 3.00.

## `maxDrawOdds` (type: `number`):

Upper bound on the reference draw price. Decimal, e.g. 5.00.

## `minAwayOdds` (type: `number`):

Lower bound on the reference away price. Decimal, e.g. 2.00.

## `maxAwayOdds` (type: `number`):

Upper bound on the reference away price. Decimal, e.g. 10.00.

## `minOverround` (type: `number`):

Lower bound on the overround of the reference 1X2 prices, as a fraction: 0.05 means a 5% margin. Decimal, e.g. 0.05.

## `maxOverround` (type: `number`):

Upper bound on the overround. Use it to keep only the sharpest-priced matches. Decimal, e.g. 0.03.

## `minBookmakerCount` (type: `integer`):

Keep only matches priced by at least this many bookmakers in the 1X2 market, counting whichever of the pre-match or closing lines the file carries. Useful for dropping thinly-quoted fixtures from a model.

## `favourite` (type: `string`):

Keep only matches where the shortest price belonged to this side.

## `upsetsOnly` (type: `boolean`):

Keep only matches the longest-priced outcome won.

## `upsetMinOdds` (type: `number`):

With Upsets only on, also require the winning price to be at least this long. Decimal, e.g. 4.00.

## `oddsMovement` (type: `string`):

Keep only matches whose price shortened (steamer) or lengthened (drifter) between the pre-match and closing lines. Needs a season with closing odds — 2019/20 onward.

## `minOddsMovementPct` (type: `number`):

How far the price must have moved, in percent, for the movement filter to keep the match.

## `maxItems` (type: `integer`):

Total rows to write in this run. Free Apify plans return a 10-row preview.

## `matchesPerLeague` (type: `integer`):

Cap the matches taken from each competition so one league cannot use up the whole run. Leave empty to let Maximum rows decide.

## `sortBy` (type: `string`):

Leave on "Source order" to stream results as they download, newest season first. Any other choice buffers the whole selection in memory before writing.

## `oddsFormat` (type: `string`):

How odds are printed in the odds blocks. Analytics always stay decimal so the maths keeps working.

## `proxyConfiguration` (type: `object`):

Not needed — Football-Data.co.uk serves these files anonymously with no rate limit measured. Turn it on only if your own network blocks the site.

## Actor input object example

```json
{
  "leagues": [
    "E0"
  ],
  "extraLeagues": [],
  "countries": [],
  "dataset": "results",
  "seasonFrom": "2025/26",
  "includeMatchStats": false,
  "includeOdds1x2": false,
  "includeClosingOdds": false,
  "includeOverUnder": false,
  "includeAsianHandicap": false,
  "includeMarketConsensus": false,
  "includeBettingAnalytics": false,
  "includeHeadToHead": false,
  "includeTeamForm": false,
  "includeStandings": false,
  "formWindow": 6,
  "teams": [],
  "teamMatchMode": "either",
  "excludeTeams": [],
  "referees": [],
  "fullTimeResults": [],
  "halfTimeResults": [],
  "bothTeamsScored": "any",
  "comebacksOnly": false,
  "daysOfWeek": [],
  "favourite": "any",
  "upsetsOnly": false,
  "oddsMovement": "any",
  "maxItems": 100,
  "sortBy": "none",
  "oddsFormat": "decimal",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Every collected match with scores, result flags, and any extra block you enabled

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "leagues": [
        "E0"
    ],
    "seasonFrom": "2025/26",
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/football-data-couk-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "leagues": ["E0"],
    "seasonFrom": "2025/26",
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/football-data-couk-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "leagues": [
    "E0"
  ],
  "seasonFrom": "2025/26",
  "maxItems": 100
}' |
apify call parseforge/football-data-couk-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parseforge/football-data-couk-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/IW6C3znYuiIstwbKE/builds/a1WDamJECYDJNzZcH/openapi.json
