World Cup 2026 xG API: Expected Goals for Every Match
World Cup 2026 xG (expected goals) API: match-level and shot-level xG for all 104 fixtures via REST. Use for prediction models, analysis, and visualisation.
Expected goals (xG) has become the defining football analytic of the last decade. At the 2022 World Cup, xG narratives drove half the post-match discourse — Argentina's underperformance against Saudi Arabia, Morocco's heroic out-xG runs, Mbappé's clinical conversion above expected. For 2026, xG will be central to every serious analysis app.
This guide covers what xG data is available for the 2026 World Cup, how to fetch it, and a worked example using xG to predict score lines.
What xG data the API returns
For every match at the 2026 World Cup, you can get:
- Match-level xG totals — home xG, away xG, and the difference
- Shot-level xG — every shot with
xg,x,ycoordinates,body_part,assisted_by,is_on_target,result - Player-aggregated xG — career xG, xG per 90, xG conversion rate
- Team-aggregated xG — per-tournament rolling totals
- xG-based metrics — xPoints (expected points), xG difference
Match-level xG
curl 'https://api.thestatsapi.com/api/football/matches/{match_id}/xg' \
-H 'Authorization: Bearer YOUR_API_KEY'
{
"match_id": "mt_010249745",
"home": { "team": "Mexico", "xg": 1.34, "shots": 12 },
"away": { "team": "Cameroon", "xg": 0.87, "shots": 9 },
"xg_difference": 0.47
}
For most use cases (model training, post-match summaries) this is enough.
Shot-level xG
For shot maps, conversion analysis, or detailed model training:
curl 'https://api.thestatsapi.com/api/football/matches/{match_id}/shots' \
-H 'Authorization: Bearer YOUR_API_KEY'
[
{
"minute": 14,
"player": "Hirving Lozano",
"team": "Mexico",
"x": 88.4,
"y": 51.2,
"xg": 0.27,
"is_on_target": true,
"body_part": "right_foot",
"result": "goal",
"assisted_by": "Edson Álvarez"
},
// ... more shots
]
x and y are pitch coordinates (0-100 scale, with 100,50 being the attacking goal). Use them to render shot maps in your UI.
Compute xPoints (expected points) from xG
xPoints is the expected number of league points a team should have earned given their xG performance. It's the simplest way to identify teams getting lucky or unlucky:
from math import factorial, exp
def poisson_pmf(k, mean):
return (mean ** k) * exp(-mean) / factorial(k)
def expected_points(xg_for, xg_against, max_goals=8):
p_win = 0
p_draw = 0
for i in range(max_goals + 1):
for j in range(max_goals + 1):
p = poisson_pmf(i, xg_for) * poisson_pmf(j, xg_against)
if i > j: p_win += p
elif i == j: p_draw += p
return p_win * 3 + p_draw * 1
# Mexico vs Cameroon
xpoints = expected_points(1.34, 0.87)
print(f"Mexico expected points: {xpoints:.2f}")
# Roughly 1.8 — expected to win or draw most of the time
Run this across an entire group and you have xPoints standings — much more predictive of future performance than actual league position.
Train a Poisson model on xG
xG-based Poisson is the bread-and-butter of football prediction:
import numpy as np
def predict_score_distribution(home_xg, away_xg, max_goals=8):
matrix = np.zeros((max_goals + 1, max_goals + 1))
for i in range(max_goals + 1):
for j in range(max_goals + 1):
matrix[i, j] = poisson_pmf(i, home_xg) * poisson_pmf(j, away_xg)
return matrix
matrix = predict_score_distribution(1.34, 0.87)
print(f"Most likely score: {np.unravel_index(matrix.argmax(), matrix.shape)}")
print(f"P(home win): {np.triu(matrix, 1).sum():.3f}")
print(f"P(draw): {np.diag(matrix).sum():.3f}")
print(f"P(away win): {np.tril(matrix, -1).sum():.3f}")
Our free Poisson Score Predictor tool does exactly this in the browser — pure client-side, useful for one-off calculations or as a working code reference.
Compare actual goals vs xG (overperformance detection)
Identify teams getting more goals than their xG suggests:
team_stats = requests.get(
'https://api.thestatsapi.com/api/football/teams/argentina/stats',
params={'competition_id': COMPETITION_ID, 'season': 2026},
headers=headers,
).json()['data']
actual = team_stats['goals_for']
expected = team_stats['xg_for']
overperformance = actual - expected
print(f"Argentina actual goals: {actual}")
print(f"Argentina expected goals: {expected:.2f}")
print(f"Overperformance: {overperformance:+.2f}")
Sustained overperformance usually regresses to the mean. It's a strong signal for "fade this team" predictions.
Use cases for xG in a World Cup app
- Post-match summaries — "Mexico dominated xG but lost the match"
- Pre-match previews — recent xG form vs opponent's xG against
- Shot maps — visualise where each goal/miss came from
- Player rankings — Golden Boot candidates ranked by xG vs goals
- Prediction models — Poisson, Dixon-Coles, neural nets
- Live in-play — running xG totals during a match (poll shots endpoint)
- Editorial — "the most unlucky team of the World Cup so far"
Frequently Asked Questions
What is xG (expected goals)?
xG is the probability that a given shot will be scored, based on historical shots from similar positions and circumstances. A clean shot from the penalty spot might be 0.78 xG; a long-range shot off-balance might be 0.03 xG. Summed across a match, total xG reflects the quality of chances each team created.
Is xG available for every World Cup match?
Yes — all 104 matches at the 2026 World Cup have match-level xG and shot-level xG via the API. Historical xG goes back to 2014 for World Cups; earlier matches don't have reliable xG data.
How accurate is xG for individual matches?
For individual matches, xG can be noisy — football is low-scoring and 1-on-1 conversion is highly variable. xG is much more accurate at predicting future goals than explaining past goals. Over 10+ matches, xG-based projections outperform results-based projections.
Can I get live xG during matches?
Yes — the shots endpoint updates within seconds of each shot. Sum the xG across shots so far to get a live xG total.
What's the formula behind xG?
Every provider uses a slightly different model. Common inputs: shot distance, angle, body part, type of pass leading to shot, defender positions, goalkeeper positioning, game state. The output is calibrated so the average xG of all shots matches the actual conversion rate.
How do I build a shot map?
Use the shots endpoint to get x/y coordinates and xG per shot. Render as circles on an SVG pitch with circle radius proportional to xG and colour by team. Libraries like mplsoccer (Python) or d3-soccer (JavaScript) handle the pitch geometry.
Can I use xG to predict the World Cup champion?
You can build a model — Elo + xG-based Poisson is a common starting point. Tournament prediction is hard because the sample is small. Sustained xG over the group stage is more predictive than any single match.
Ready to Power Your Sports App?
Start your 7-day free trial. All endpoints included on every plan.