Data sources and provenance — Football
Everything published here traces to a committed snapshot in data/snapshots/, each carrying a
manifest with the source URL, fetch timestamp, row count, column-schema hash and a SHA-256 of the
raw bytes. Reports render from those snapshots offline, so any past result can be reproduced
exactly, and a silent upstream revision shows up as a hash change.
Primary — football-data.co.uk
Match-level results, shots, shots on target, corners, fouls, cards, and a large betting-odds block for eleven European top divisions.
robots.txtis fully open; no rate limit is imposed; files are plain CSV.- We identify ourselves with a descriptive User-Agent and fetch politely.
- The site's published disclaimer covers gambling liability only. We found no explicit data-reuse or redistribution clause. We therefore claim no licence over the underlying data, attribute the source on every page that uses it, and commit only the fields this project analyses. If the operator objects, we will comply.
What we measured, versus what is documented
notes.txt describes a file that no longer exists. Verified 2026-08-29 by auditing 363
competition-seasons:
Match statistics were never backfilled. They arrived league by league over seventeen years. Only 177 of 286 league-seasons since 2000 carry fouls and cards.
| First usable season (fouls + cards) | Leagues |
|---|---|
| 2000-01 | England, Scotland |
| 2003-04 | Germany |
| 2005-06 | Italy, Spain |
| 2007-08 | France |
| 2017-18 | Netherlands, Portugal, Turkey |
| 2019-20 | Belgium, Greece |
Referee coverage narrowed over time. England is continuous 2000–2025. Scotland is continuous
except 2012-13. Germany carried it in 2000-01 only; Italy in 2005-06 only. Both lost it.
Documented columns that were dropped years ago — fossils, not documentation errors:
| Column | Last observed |
|---|---|
HO/AO (offsides), HHW/AHW (woodwork), HBP/ABP (bookings points) |
2000-01 |
HFKC/AFKC (free kicks conceded) |
2017-18 |
The files grew while the football shrank. Median column count: 61 (2018) → 105 (2019) → 131 (2025). Nearly all of that growth is betting odds.
Known quirks that affect interpretation
- Second yellows. In England and Scotland, the first yellow of a second-bookable offence is folded into the red and excluded from the yellow count; other countries count both. There is no dedicated second-yellow column anywhere. This is a classic silent discrepancy when comparing sources.
HY/AYare all yellows — dissent, time-wasting, celebration, bench cards — while the natural denominator for a card rate is fouls only. This is a systematic, team-varying bias and must be stated wherever a card rate appears.- Portugal has no files for 1997-98 through 1999-2000.
- Betting odds are used, if at all, only to derive a pre-match opponent-strength index. This project publishes no betting content and offers no betting advice.
Enrichment — Understat (Big-5 only)
xG, non-penalty xG, PPDA and deep completions for the five major leagues.
Status: not yet integrated. Its terms of service will be reviewed before any code depends on
it, and the finding recorded here either way. soccerdata removed its FotMob scraper in January
2026 specifically because scraping it breached that site's terms; that is a live governance
question, not a footnote.
Cross-check only — FBref / Sports Reference
Not used as a data source, and never committed.
- FBref lost its Opta licence on 20 January 2026. xG, possession, passing, progressive actions and defensive actions were removed site-wide, including historical archives. Pressures had already gone in the October 2022 provider switch. What remains is basic.
- Sports Reference's terms prohibit using site content "to create any database, archive, or other data store" that substitutes for their service, and separately prohibit use "for purposes of training, fine-tuning, prompting, or instructing artificial intelligence models."
- They enforce a limit of ten requests per minute by IP.
- The site is behind an interactive Cloudflare challenge, and cloud IP ranges are reported blocked, so it cannot run in CI regardless.
We respect all of that. If FBref is ever consulted locally for a goals/cards agreement check, the result is reported as a summary statistic and the underlying data is never committed. A CI test asserts no FBref-derived artifact exists in the tree.
Manager tenures — hand-assembled, and why not from Transfermarkt
Manager identity does not exist in any of the sources above, so it has to be assembled by hand.
That makes it the least reliable data here and the most in need of explicit handling: every row
cites a resolvable URL, date precision is recorded as day/month/season, and coverage is measured
and published rather than assumed. See src/tfa/managers.py.
Transfermarkt is not used. It is the most complete manager-tenure source in existence, and it was the obvious candidate. Its terms of use, clause 11.1, rule it out twice over:
"The User is not permitted to access or copy the Digital Content using bots, spiders, screen scraping or other automated processes. The user is also prohibited from using the digital content for the training or development of artificial intelligence (AI), including language models, machine learning, neural networks..."
Automated retrieval is prohibited, and use of the content by a language model is prohibited outright — which matters directly for a project that documents an AI-assisted workflow. These terms are near-identical to the Sports Reference terms that put FBref off this project's critical path, so using Transfermarkt anyway would contradict our own published policy. Convenience is not a reason to hold a second source to a lower standard than the first.
Used instead, in order of preference:
- Wikipedia (Portuguese and English) — CC BY-SA, explicitly reusable with attribution, and it carries dedicated club manager-history pages.
- zerozero.pt — Portuguese football database; permissive
robots.txtthat disallows a single endpoint and publishes a coaches sitemap. - Club official sites and Liga Portugal.
- Reputable news reports for a specific appointment or departure, which have the advantage of dating the event precisely.
Anything unverifiable is left out and reported as a gap. A missing row costs coverage; an invented one costs the project its premise.
Event data — open, licensed, and historical only
Foul location, foul timing and player-level cards were recorded here as unavailable. That was right about current seasons and wrong as a blanket claim, and the correction matters because it changes what the project can attempt.
Pappalardo et al. (2019) — CC BY 4.0
The best-licensed football data this project has found, better than the primary source.
- Licence: CC BY 4.0, confirmed through the figshare API on the Events, Matches and Referees files individually rather than inferred from the collection page. Attribution is the only condition; building a database, redistributing derived data and commercial use are all permitted.
- Coverage: complete 2017-18 seasons of the Italian, English, Spanish, French and German first divisions, plus Euro 2016 and the 2018 World Cup.
- Contents: spatio-temporal events with pitch coordinates. Cards are tagged
1701red,1702yellow and1703second yellow — the separate second-yellow tag resolves the counting problem study 01 documented, where English and Scottish totals fold the first yellow of a second-bookable offence into the red. - Referee identity is included, which is the confounder we had to assemble from zerozero.pt for Portugal.
- Documented in a peer-reviewed data paper, doi:10.1038/s41597-019-0247-7,
itself CC BY 4.0. Cited as
pappalardo2019events.
No Portugal, and a single season, so it cannot answer club-level questions: 85% of the spread in a one-season booking index is sampling noise. It can answer whether foul context drives card probability at all, on roughly 48,000 fouls.
StatsBomb Open Data — free, but read the coverage carefully
-
Terms: the repository README states that anyone publishing research based on the data should state StatsBomb as the source. A
LICENSE.pdfaccompanies it and is image-only with no extractable text, so it has not been read here and no claim is made about what it contains. Anyone relying on this source should read it first. -
Contents: fouls carry
location,minuteandsecond,player,position,card, foultype, plusplay_patternand acounterpressflag. The last two bear directly on tactical fouling. -
Coverage is narrower than the season counts imply. Measured from the repository:
Competition Seasons Matches per season La Liga 18 48 — one club's fixtures, not a league Champions League 18 1 — finals only Premier League 2 209 Serie A 2 190, all twenty clubs Ligue 1 3 145 A full domestic season is about 380 matches. Serie A, the Premier League and Ligue 1 are the parts with broad team coverage; the La Liga series is built around a single player's career and is not a sample of a league.
Neither source covers Portugal, so the question that started this project stays out of reach.
zerozero.pt is currently returning 403
Checked 2026-09-01. Every request returns HTTP 403: the homepage, the referee endpoints, and
robots.txt itself, under both this project's user agent and a browser one. This is site-wide
rather than a rate limit.
The committed referee data is unaffected and stays where it is: 2,737 rows through 2026-08-29, harvested when access was permitted, joined on scorelines and validated. Study 02 rests on it and remains reproducible.
What it costs going forward is the ability to extend that coverage. The pre-registered test in
preregistrations/2026-08-30-porto-booking-index.md specifies a secondary referee analysis over
matchweeks 4 to 10; unless access returns, that part cannot be run and the resolution will say so
rather than quietly dropping it.
There is a compliance point here that matters more than the access one. This project's position was
that zerozero's robots.txt permitted the endpoints we used. That file is now unreadable, so the
claim can no longer be checked, and an assertion about someone's crawl policy that cannot be
verified is not one to keep making. No further harvesting will be attempted until the terms can be
read again.
Not available at all
Published in the README as a permanent guard, so no future contributor builds on a column that does not exist: pressures, tackles, interceptions, possession %, pass completion, progressive passes or carries, aerial duels, touches by zone, offsides, woodwork and free kicks conceded.
Corrected. This list previously also claimed player-level fouls and cards, foul location and
foul timing were unavailable outright. They are unavailable from the sources this project ingests
and for current seasons and for Portugal, which is not the same statement. The open event data
described above carries all three for the five largest leagues in 2017-18. The original wording was
a claim about the world made from a search of a handful of sources, which is the error recorded in
METHODS.md §4: absence of evidence in your own search is not evidence of absence.
Attribution
Match data courtesy of football-data.co.uk. This project is independent of, and not endorsed by, any data provider, league or club.