TheStatsDontLie APIthestatsdontlie.com ↗
Get match-level World Cup 2026 stats — goals, xG, shots, corners, cards — for every fixture. Filter by team or stage. One flat record per match.
What is the TheStatsDontLie API?
The TheStatsDontLie World Cup 2026 API exposes a single list_matches endpoint that returns one flat record per fixture across the entire tournament, covering up to 104 matches from the group stage through the Final. Each record includes 15+ fields: round label, date, both team names, full-time score, penalty-shootout winner, goals by half, yellow and red cards, corners, expected goals (xG), shots, shots on target, and fouls — ready for direct tabular or CSV use.
curl -X GET 'https://api.parse.bot/scraper/6255cc44-0e6d-4216-9c67-26e947137d5b/list_matches?stage=knockouts' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace thestatsdontlie-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: World Cup 2026 match stats — bounded, re-runnable."""
from parse_apis.thestatsdontlie_com_api import WorldCup2026, Stage, InputFormatInvalid
client = WorldCup2026()
# List knockout-stage matches, capped at 5 items.
for match in client.matches.list(stage=Stage.KNOCKOUTS, limit=5):
print(f"{match.team1} {match.team1_score}-{match.team2_score} {match.team2} ({match.round})")
# Filter by team name to find their tournament path.
argentina = client.matches.list(team="Argentina", stage=Stage.ALL, limit=10)
first = argentina.first()
if first is not None:
print(f"\nFirst Argentina match: {first.team1} vs {first.team2}, xG {first.team1_xg}-{first.team2_xg}")
print(f" Corners: {first.total_corners} Cards: {first.team1_yellow_cards}Y/{first.team1_red_cards}R vs {first.team2_yellow_cards}Y/{first.team2_red_cards}R")
# Group-stage sweep: show all group matches for Brazil.
try:
for match in client.matches.list(team="Brazil", stage=Stage.GROUP_STAGE, limit=5):
print(f"{match.date} {match.team1} {match.team1_score}-{match.team2_score} {match.team2}")
except InputFormatInvalid as e:
# Raised when the stage value is not accepted by the site.
print(f"Invalid input: {e.message}")
print("\nexercised: matches.list (knockouts / team filter / group_stage)")
Returns one flat record per World Cup 2026 match from the site's Fixtures / Results / Match Stats table, in the site's order (by round, then date). Each record carries the round label, date (DD/MM/YYYY), both team names, full-time score, penalty-shootout winner when the site marks one, and per-team statistics: goals by half, yellow and red cards, corners by half and for the match, match total corners, xG, shots, shots on target and fouls. A statistic cell the site leaves blank comes back as null. `stage` selects the group stage table, the knockout table (Round of 32 through the Final; the site lists no third-place match), or both; `team` is an optional exact (case-insensitive) team-name filter applied over the selected stage(s), and an unknown name yields an empty `matches` list. The whole table is returned in one call (no pagination); two or three upstream page loads per call.
| Param | Type | Description |
|---|---|---|
| team | string | Team name as shown on the site (e.g. Argentina); matched case-insensitively against either team of a match. Omitted = no filter. |
| stage | string | Which part of the tournament to return. |
{
"type": "object",
"fields": {
"team": "lower-cased team filter applied, or null when none",
"count": "number of match records returned",
"stage": "the stage selection applied (group_stage, knockouts or all)",
"matches": "array of match records; each has stage, round (e.g. Group Stage, Round Of 32, Final), date (DD/MM/YYYY), team1, team2, team1_score, team2_score, penalty_winner (team name or null), team1_xg/team2_xg (decimal), total_corners, and team1_/team2_ prefixed integers for first_half_goals, second_half_goals, yellow_cards, red_cards, first_half_corners, second_half_corners, match_corners, shots, shots_on_target, fouls (null when the site leaves the cell blank)"
},
"sample": {
"data": {
"team": "argentina",
"count": 5,
"stage": "knockouts",
"matches": [
{
"date": "19/07/2026",
"round": "Final",
"stage": "knockouts",
"team1": "Spain",
"team2": "Argentina",
"team1_xg": 2.29,
"team2_xg": 0.22,
"team1_fouls": 21,
"team1_score": 1,
"team1_shots": 20,
"team2_fouls": 25,
"team2_score": 0,
"team2_shots": 2,
"total_corners": 13,
"penalty_winner": null,
"team1_red_cards": 0,
"team2_red_cards": 1,
"team1_yellow_cards": 0,
"team2_yellow_cards": 5,
"team1_match_corners": 9,
"team2_match_corners": 4,
"team1_shots_on_target": 12,
"team2_shots_on_target": 0,
"team1_first_half_goals": 0,
"team2_first_half_goals": 0,
"team1_second_half_goals": 0,
"team2_second_half_goals": 0,
"team1_first_half_corners": 2,
"team2_first_half_corners": 0,
"team1_second_half_corners": 7,
"team2_second_half_corners": 1
}
]
},
"status": "success"
}
}About the TheStatsDontLie API
What the API Returns
The list_matches endpoint returns an array of match records sourced from the Fixtures / Results / Match Stats table on TheStatsDontLie's World Cup 2026 page. Records are ordered by round, then by date. Every record includes the round label (e.g. Group Stage, Round Of 32, Semi-Final, Final), the date in DD/MM/YYYY format, team1 and team2 names, the full-time score fields (team1_score, team2_score), and a penalty_winner field populated when the site marks a shootout result.
Match Statistics Fields
Beyond the scoreline, each record carries per-team split stats: team1_xg / team2_xg (expected goals), team1_shots / team2_shots, team1_shots_on_target / team2_shots_on_target, team1_corners / team2_corners, team1_fouls / team2_fouls, team1_yellow_cards / team2_yellow_cards, and team1_red_cards / team2_red_cards. Half-time goals are also included where the site provides them.
Filtering
The endpoint accepts two optional input parameters. The team parameter filters results to matches where either team1 or team2 matches the supplied string (case-insensitive). The stage parameter accepts group_stage, knockouts, or all (default), letting you narrow the response to one phase of the tournament. The response envelope wraps the match array with count, the applied team filter, and the applied stage value so downstream consumers can verify what was returned.
Coverage and Freshness
Data reflects what TheStatsDontLie has published for each fixture. Matches that have not yet been played will appear with score and stat fields absent or null. The dataset spans the full World Cup 2026 tournament schedule, from the opening group-stage matches through the Final, as the site populates results.
The TheStatsDontLie API is a managed, monitored endpoint for thestatsdontlie.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when thestatsdontlie.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official thestatsdontlie.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a live World Cup 2026 results table with full-time scores and penalty-shootout outcomes.
- Analyse xG versus actual goals scored for every group-stage match to quantify over- and under-performance.
- Generate per-team disciplinary summaries (yellow cards, red cards) across all knockout fixtures.
- Track corners and shots on target trends for a specific nation using the
teamfilter. - Compare half-time and full-time goal distributions across rounds to study tournament pacing.
- Feed match-level fouls and cards data into a referee bias or match-control analysis.
- Export a flat CSV of all 104 fixtures with stats for use in spreadsheet-based tournament models.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does TheStatsDontLie have an official developer API?+
How does the `stage` filter split group stage from knockout matches?+
stage=group_stage returns only records whose round field is Group Stage. Passing stage=knockouts returns everything else — Round Of 32, Round Of 16, Quarter-Final, Semi-Final, Third Place, and Final. Passing stage=all (or omitting the parameter) returns the full tournament.What happens to stat fields for matches that haven't been played yet?+
team1_score, team2_score) and all per-team stat fields (xG, shots, corners, cards, fouls) will be null or absent in the record. The round, date, team1, and team2 fields are still populated from the schedule.