GUIDE

Historical World Cup Data API: Every Match from 1930 to 2022

Get every historical FIFA World Cup match, winner, top scorer, and final score from 1930-2022 via REST API. Train ML models, build retrospectives.

6 min read

The 2026 FIFA World Cup will be the 23rd edition of the tournament. The first 22 — from 1930 in Uruguay to 2022 in Qatar — contain ~900 matches, 22 champions, 22 Golden Boot winners, and the data underpinning every "who's the GOAT?" debate.

If you're training a prediction model, building a tournament retrospective, writing a data-journalism piece, or feeding historical context into a live ticker app, you need fast access to this archive. This guide covers what's available and how to pull it.

What historical World Cup data is available

TheStatsAPI provides current API access to modern World Cup seasons, with deeper coverage for recent editions:

  • World Cup seasons including 1998, 2002, 2006, 2010, 2014, 2018, 2022, and 2026 from the current seasons endpoint
  • Match fixtures and results for available seasons with final scores
  • Knockout-stage results including extra time and penalty shootouts
  • Player season stats for modern editions where player-level coverage exists
  • Match stats, xG, shotmaps, lineups, and odds where those coverage flags are available
  • Editorial historical context such as winners, top scorers, hosts, and format changes, which you can store in your CMS or static content layer
  • Format changes documented (1934 single-elim, 1982 expansion to 24, 1998 expansion to 32, 2026 expansion to 48)

The depth varies by era. Modern World Cups have lineups, substitutions, detailed events, player stats, and xG where available. Early-edition facts are better treated as editorial/static data rather than pretending the live REST API has identical depth back to 1930.

Quick fetch: every edition's summary

curl 'https://api.thestatsapi.com/api/football/competitions/{COMPETITION_ID}/seasons' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Returns one season object per available World Cup edition, including IDs like sn_326766 for 2022 and sn_624440 for 2018. Use those IDs in match and standings calls.

Fetch all matches from a single tournament

curl 'https://api.thestatsapi.com/api/football/matches?competition_id={COMPETITION_ID}&season_id={SEASON_ID_2018}' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Returns the matches for the 2018 World Cup in Russia. Swap season_id for any season ID returned by /football/competitions/{COMPETITION_ID}/seasons.

Train a prediction model on historical data

A typical workflow for a World Cup 2026 prediction model:

import requests
import pandas as pd

# Pull every available modern World Cup season from the API
all_matches = []
season_ids = ["sn_29792", "sn_64936", "sn_6107", "sn_20655", "sn_844385", "sn_624440", "sn_326766"]

for season_id in season_ids:
    r = requests.get(
        'https://api.thestatsapi.com/api/football/matches',
        params={'competition_id': COMPETITION_ID, 'season_id': season_id, 'status': 'finished', 'per_page': 100},
        headers={'Authorization': 'Bearer YOUR_API_KEY'},
    )
    all_matches.extend(r.json()['data'])

df = pd.DataFrame([{
    'season_id': m['season_id'],
    'home': m['home_team']['name'],
    'away': m['away_team']['name'],
    'home_score': m['score']['home'],
    'away_score': m['score']['away'],
    'stage': m.get('stage_name'),
} for m in all_matches])

# Use this to train an Elo, Poisson, or Dixon-Coles model
print(f"Loaded {len(df)} historical World Cup matches")

That's ~500 matches between 1990 and 2022, enough to fit a basic Poisson model with team-strength priors.

Compute career World Cup stats per player

# All goals by Cristiano Ronaldo across his World Cups
goals = []
season_ids = ["sn_6107", "sn_20655", "sn_844385", "sn_624440", "sn_326766"]

for season_id in season_ids:
    r = requests.get(
        f'https://api.thestatsapi.com/api/football/players/{RONALDO_PLAYER_ID}/stats',
        params={'competition_id': COMPETITION_ID, 'season_id': season_id},
        headers=headers,
    )
    stats = r.json()['data']
    goals.append({
        'season_id': season_id,
        'goals': stats.get('scoring', {}).get('goals', 0),
        'apps': stats.get('appearances', 0),
    })

total = sum(g['goals'] for g in goals)
print(f"Ronaldo: {total} goals across {len(goals)} World Cups")

Top scorers (Golden Boot) by year

YearGolden BootGoals
2022Kylian Mbappé (France)8
2018Harry Kane (England)6
2014James Rodríguez (Colombia)6
2010Müller, Forlán, Sneijder, Villa5
2006Miroslav Klose (Germany)5
2002Ronaldo (Brazil)8
1998Davor Šuker (Croatia)6
1994Salenko & Stoichkov6
1990Salvatore Schillaci (Italy)6
1958Just Fontaine (France)13

Fontaine's 13 goals in 1958 remains the single-tournament record, set in six matches. Available via:

curl 'https://api.thestatsapi.com/api/football/players?search=Fontaine' \
  -H 'Authorization: Bearer YOUR_API_KEY'

curl 'https://api.thestatsapi.com/api/football/players/{PLAYER_ID}/stats?competition_id={COMPETITION_ID}&season_id={SEASON_ID_1958}' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Hosting history

Hosting history is best maintained as editorial/static data in your app. The current football API documents competitions, seasons, matches, teams, standings, players, stats, shotmaps, timelines, lineups, and odds; it does not document a /hosts endpoint. Store host facts in your CMS and join them to API matches where useful.

Use cases for historical World Cup data

  • Prediction models — Elo, Poisson, Dixon-Coles, neural-net training
  • Editorial / journalism — "all-time top scorers" listicles, head-to-head retrospectives
  • Match-page sidebars — "the last time these teams met at a World Cup..."
  • Anniversary content — "On this day in 1986, Maradona..."
  • Fantasy game scoring backtests — verify your rules against past tournaments
  • Wagering models — historical performance feeds into pre-tournament outright odds
  • Education — build datasets for sports analytics courses

Caching guidance

Historical data is fully static. Cache aggressively — daily or weekly is fine. Pull once at build time and bake into your static export if you're using Next.js.

Frequently Asked Questions

How far back does the World Cup data go?

To the inaugural 1930 World Cup in Uruguay. Every edition from 1930 to 2022 is covered. Depth varies — modern editions (post-1990) have detailed lineups and events; early editions have final scores and tournament summaries.

What was the highest-scoring World Cup?

The 1958 World Cup in Sweden featured 126 goals in 35 matches (3.6 goals per match). The 2022 World Cup had the most total goals (172) but across more matches.

Who is the all-time top scorer at the World Cup?

Miroslav Klose (Germany) with 16 goals across 4 tournaments (2002, 2006, 2010, 2014). Ronaldo Nazário (Brazil) is second with 15.

Can I get xG for historical World Cup matches?

xG was not tracked at most pre-2014 World Cups in any meaningful way. From 2018 onwards, expected goals are available. For earlier matches, you'll need to estimate from box-score events.

How do I build a "what happened on this day" widget?

Loop through the World Cup season IDs, request matches for each season, and filter by month/day in your own code:

const COMPETITION_ID = 'YOUR_COMPETITION_ID'; // look up via /football/competitions?search=world%20cup
const seasonIds = ['sn_29792', 'sn_64936', 'sn_6107', 'sn_20655', 'sn_844385', 'sn_624440', 'sn_326766'];
const today = '06-19';

const allMatches = [];
for (const seasonId of seasonIds) {
  const res = await fetch(
    `https://api.thestatsapi.com/api/football/matches?competition_id=${COMPETITION_ID}&season_id=${seasonId}&status=finished&per_page=100`,
    { headers }
  );
  const { data } = await res.json();
  allMatches.push(...data);
}

const matches = allMatches.filter((match) => match.utc_date.slice(5, 10) === today);

Then render "On June 19 at the World Cup..." with one match per year that matches.

Are penalty shootout results included?

Yes for every edition since 1982 (when the first shootout in a World Cup Final occurred — Spain 1982 SF actually). Each shootout returns shooter-by-shooter outcomes.

What data is available for the 2026 World Cup before it starts?

Full fixtures, venues, host cities, draw structure, and team metadata are available from the moment the draw is finalised. Live data (scores, lineups, xG) begins as matches kick off on June 11, 2026.

Start building today

Ready to Power Your Sports App?

Start your 7-day free trial. All endpoints included on every plan.

Cancel anytime
7-day free trial
Setup in 5 minutes