GUIDE

World Cup 2026 Player Stats API: Golden Boot, Assists & Minutes

World Cup 2026 player stats API. Live goals, assists, xG, shots, minutes, and cards for every player. Track the Golden Boot race in real time.

6 min read

Player stats are what fans actually care about during the World Cup — the Golden Boot race, who's racking up assists, who's getting cards, who's playing 90 minutes every match. If you're building a fantasy app, a leaderboard widget, or a player-comparison tool, you need fast access to live per-player stats.

This guide covers what the player stats endpoint returns, how to fetch the Golden Boot leaderboard, and how to surface useful player-level views in your app.

What player stats are available

For every player who features in a World Cup match:

  • Per-match stats — goals, assists, shots, shots on target, xG, xA, minutes, yellow cards, red cards, pass accuracy, tackles, interceptions, fouls, passes, key passes
  • Per-tournament aggregates — totals across all matches in the World Cup
  • Per-90 metrics — goals per 90, xG per 90, etc.
  • Position-specific — clean sheets and saves for goalkeepers
  • Substitution data — minute on, minute off

Plus player metadata: name, age, position, shirt number, club, height, foot, captaincy status.

Build the Golden Boot leaderboard

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

Start by fetching the finished World Cup matches. For each finished match, call the per-match player stats endpoint:

curl 'https://api.thestatsapi.com/api/football/matches/{MATCH_ID}/player-stats' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Each row has the player, team, minutes, passing, shooting, defending, goalkeeping, and discipline fields. A real player row looks like this:

{
  "player_id": "pl_57255528",
  "player_name": "Kylian Mbappé",
  "team_id": "tm_28952",
  "position": "F",
  "started": true,
  "played": true,
  "minutes_played": 120,
  "shooting": {
    "goals": 3,
    "total_shots": 8,
    "shots_on_target": 5,
    "expected_goals": 2.25
  },
  "passing": {
    "assists": 0,
    "key_passes": 2
  },
  "general": {
    "yellow_cards": 0,
    "red_cards": 0
  }
}

Aggregate those rows by player_id, then sort by goals, assists, and minutes played for a Golden Boot table.

Golden Boot tiebreakers

If two players are tied on goals, FIFA applies tiebreakers in order:

  1. Most assists (assist credit follows FIFA's strict definition)
  2. Fewest minutes played (rewards efficiency)
  3. Drawing of lots if still tied

Your code should apply those tiebreakers after aggregating the per-match rows.

Build a live leaderboard widget

import useSWR from 'swr';

function GoldenBootLeaderboard() {
  const { data } = useSWR(
    '/api/wc-top-scorers',
    (url) => fetch(url).then((r) => r.json()),
    { refreshInterval: 30000 }
  );

  if (!data) return <div>Loading...</div>;

  return (
    <ol>
      {data.map((p, i) => (
        <li key={p.player.id}>
          <span className="rank">{i + 1}.</span>
          <span className="name">{p.player.name}</span>
          <span className="team">({p.player.team})</span>
          <span className="goals">{p.goals} goals, {p.assists} assists</span>
        </li>
      ))}
    </ol>
  );
}

Polling every 30 seconds is plenty — Golden Boot positions don't change between goals.

Aggregate per-match rows in JavaScript

function addStat(total, row) {
  const current = total.get(row.player_id) ?? {
    player_id: row.player_id,
    player_name: row.player_name,
    team_id: row.team_id,
    minutes: 0,
    goals: 0,
    assists: 0,
    shots: 0,
    shots_on_target: 0,
    xg: 0,
    yellow_cards: 0,
    red_cards: 0,
  };

  current.minutes += row.minutes_played ?? 0;
  current.goals += row.shooting?.goals ?? 0;
  current.assists += row.passing?.assists ?? 0;
  current.shots += row.shooting?.total_shots ?? 0;
  current.shots_on_target += row.shooting?.shots_on_target ?? 0;
  current.xg += row.shooting?.expected_goals ?? 0;
  current.yellow_cards += row.general?.yellow_cards ?? 0;
  current.red_cards += row.general?.red_cards ?? 0;

  total.set(row.player_id, current);
}

function sortGoldenBoot(rows) {
  return [...rows].sort((a, b) => (
    b.goals - a.goals ||
    b.assists - a.assists ||
    a.minutes - b.minutes ||
    a.player_name.localeCompare(b.player_name)
  ));
}

Compare two players

const COMPETITION_ID = 'YOUR_COMPETITION_ID'; // look up via /football/competitions?search=world%20cup
const SEASON_ID = 'YOUR_SEASON_ID'; // look up via /football/competitions/{id}/seasons

async function comparePlayers(playerA, playerB) {
  const [a, b] = await Promise.all([
    fetch(`/api/football/players/${playerA}/stats?competition_id=${COMPETITION_ID}&season_id=${SEASON_ID}`).then((r) => r.json()),
    fetch(`/api/football/players/${playerB}/stats?competition_id=${COMPETITION_ID}&season_id=${SEASON_ID}`).then((r) => r.json()),
  ]);

  return {
    [playerA]: a.data,
    [playerB]: b.data,
  };
}

// Use player IDs from /football/players?search=Mbappe
const comparison = await comparePlayers('pl_57255528', 'pl_1954708');

Render side by side for a player-comparison widget.

Position-specific stats

Goalkeepers have additional fields:

  • saves — total saves
  • clean_sheets — matches without conceding
  • penalties_saved — penalty saves in regulation or shootouts
  • save_percentage — saves / shots on target faced

Get goalkeeper rows from /football/matches/{match_id}/player-stats, aggregate goalkeeping.saves, and sort by saves or clean-sheet logic in your own table.

Player metadata: ages, clubs, heights

Useful for narrative-driven cards:

curl 'https://api.thestatsapi.com/api/football/players/pl_57255528' \
  -H 'Authorization: Bearer YOUR_KEY'

Returns player metadata: full name, date of birth, position, nationality, height, current team, market value where available, and identifiers you can reuse in stats calls.

Common UI patterns

  • Player card — photo + key stats (goals/assists/minutes) + comparison to tournament average
  • Hot players widget — sorted by xG (under-performers are bets to score next match)
  • All-star XI — top scorer + top assister + top defender by position
  • Daily MVP — best individual performance on a given match-day
  • Per-team leaderboard — top scorers within a single team

Caching strategy

  • Outside match-days: cache 1 hour
  • Match-day, no live matches: cache 5 minutes
  • During a match: cache 30-60 seconds
  • Live in a high-stakes match: poll directly

Free alternatives

For just basic per-player stats during the World Cup, API-Football on their free tier covers it (100 requests/day). It's enough for a hobby project but the daily cap will hurt during a busy match-day. For production use, TheStatsAPI Starter at $50/month covers the full tournament without rate-limit anxiety.

Frequently Asked Questions

How fast do player stats update during a match?

Within seconds of an event in our source feed. Player goals, assists, and cards appear in the stats endpoint immediately after they happen on the pitch.

What is xG per 90?

Expected goals normalised to a full 90-minute match. Useful for comparing players with different minutes played. A striker with 0.7 xG per 90 is generating high-quality chances at a regular rate.

How is the Golden Boot decided?

Most goals wins. Tiebreakers: most assists, then fewest minutes played, then drawing of lots.

Can I get per-match player stats (not just tournament totals)?

Yes — /football/matches/{match_id}/player-stats returns every player's per-match line. Useful for "best 11 of match-day" widgets.

Does the API include player photos?

Player metadata includes a photo_url field where the right has been licensed. For unlicensed players, you'll need to source images separately (Wikimedia Commons is a common fallback).

How do I detect the tournament MVP?

There's no single "MVP" metric — FIFA awards the Golden Ball based on a media vote. Proxy with weighted goals + assists + minutes + xG and you'll be close.

Can I get historical player stats?

Yes — every World Cup back to 1930 has player-level stats at varying depth. Modern editions (post-1990) have detailed per-match data; older editions have tournament-level summaries.

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