Open data
The verified match log behind this site, free to reuse under CC BY 4.0.
Licence
You may copy, share and build on this data, commercially too, as long as you credit The Viking Striker (https://thevikingstriker.com) and link to the licence. Every download also says so in its Link and X-Licence headers.
Downloads
- /api/v1/matches.json (add
?season=2025-26for one season) - /api/v1/matches.csv (add
?season=2025-26for one season) - /api/v1/seasons.json
- /api/v1/corrections (optional:
page,per_page,match) - /api/v1/schema
Hand-verified numbers only. A row checked by nobody is left out (the X-Unverified-Rows-Omitted header counts them); a number only a web search found is withheld and named in withheld_fields. Unknown is null in JSON and an empty cell in CSV, never 0.
Every response has an ETag and a Last-Modified date and is cached for an hour; send If-None-Match or If-Modified-Since for a 304. Please fetch at most once an hour.
Matches: columns
date(date, YYYY-MM-DD): Match date (UK). Empty: Never null.season(string, YYYY-YY): Football season, August to May. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.competition(string): Competition as stored. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.round(string): Round or matchday. Empty: None recorded.home_team(string): Home team. Empty: Never null.away_team(string): Away team. Empty: Never null.home_score(integer, goals): Goals scored by the home team. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.away_score(integer, goals): Goals scored by the away team. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.venue(string): Stadium. Empty: None recorded.started(boolean): true when the player started, false when they came off the bench. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.minutes(integer, minutes): Minutes the player was on the pitch. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.goals(integer, goals): The player's goals. Empty: Never null.assists(integer, assists): The player's assists. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.goal_minutes(string[], minute): Minute of each goal, "45+2" for added time. Semicolon-separated in the CSV. Empty: No goal, or no minute recorded.verified_by(string): "seed" (the hand-checked history) or "owner" (entered or checked by hand). Empty: Never null.source_url(string, URL): The report the row was checked against. Empty: None recorded.checked_at(datetime, ISO 8601 UTC): When a source last agreed with the row. Empty: None recorded.changed_at(datetime, ISO 8601 UTC): When the stored row last changed. Empty: None recorded.corrected(boolean): true when a hand correction (see /corrections) changed the row. Empty: Never null.corrected_at(datetime, ISO 8601 UTC): Time of the latest correction. Empty: Never corrected.corrected_fields(string[]): Columns a correction set. Semicolon-separated in the CSV. Empty: Never corrected.corrected_sources(string[], column=URL): The provenance of each corrected cell: the column and the source of its latest correction. The whole record is at /api/v1/corrections?match=<date>. Semicolon-separated in the CSV. Empty: Never corrected, or corrected without a source.withheld_fields(string[]): Columns left empty because only a web search had a value for them: web-search numbers are not published. Semicolon-separated in the CSV. Empty: Nothing withheld.unknown_fields(string[]): The unknown flag of each cell: every data column of this row that is null because it is not known. Semicolon-separated in the CSV. Empty: Every cell known.
Seasons: columns
season(string, YYYY-YY): Football season, August to May. Empty: Never null.team(string): Club. Empty: Never null.matches(integer, matches): Appearances, all competitions, from the hand-verified baseline. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.goals(integer, goals): Goals, all competitions, from the hand-verified baseline. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.baseline_checked_on(date, YYYY-MM-DD): When the baseline was last checked by hand. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.log_matches(integer, matches): Club matches in the hand-verified log for this season (matches.json), including any the player missed: compare with matches. Empty: This team has no match log.log_matches_with_minutes(integer, matches): Of those, rows with minutes recorded: the denominator of any per-90. Empty: This team has no match log.log_minutes(integer, minutes): Minutes summed over those rows. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.quality_grade(string, A to D): Data-quality grade computed from the log (see quality_summary). Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.quality_summary(string): Every part of the grade as N of M. Empty: Not recorded by a hand-verified source. Unknown, never 0 or false.unknown_fields(string[]): The unknown flag of each cell, as in matches. Empty: Every cell known.
corrections: columns
id(integer): The correction, numbered in the order it was made from 1. A correction of several cells gives each the same id; ids never change. Empty: Never null.match(date, YYYY-MM-DD): The corrected match, by its date (matches.date). Empty: Never null.field(string): The corrected column of matches. Empty: Never null.old(any, as the column): The stored value before the correction, read from the row by the server. Empty: Not recorded before the correction.new(any, as the column): The value the correction set. Empty: Never null.reason(string): Why, in plain words. Empty: None recorded.source_url(string, URL): The report the new value comes from. Empty: None recorded.by(string): Who made the correction. Empty: Never null.at(datetime, ISO 8601 UTC): When the correction was made. Empty: Never null.
Corrections
Every hand correction is listed on Corrections and flagged on its row (corrected, corrected_at, corrected_fields), and each corrected cell names its own source in corrected_sources. The whole ledger is open too, one row per corrected cell with the old and new value, the reason, the source, who and when: /api/v1/corrections, newest first, in pages. Only the site's maintainers can add to it. Spotted a wrong number? The corrections page says how to report it.