epl_matches <- read_csv("https://bcdanl.github.io/data/epl_matches.csv")Soccer
Explore the data on a map
Explore the project data by location. Select a location for details.
Loading the map…
Data
On-page tables preview a sample. Each download combines previous and current English Premier League seasons in one CSV at a consistent unit of observation. Updated October 6, 2026.
epl_matches: 3,470 completed matches, from 2017–18 through the first five gameweeks of 2026–27.epl_teams: 200 team-season rows over those ten seasons.epl_players: 3,730 player-season rows, from 2021–22 through partial 2026–27.epl_gks: 335 goalkeeper-season rows over those same six seasons.
season_end_year is the year in which the season ends: 2027 means 2026–27. season supplies the display label. is_partial_season == 1 marks the incomplete 2026–27 season. The latest completed match in the source is September 20, 2026. Compare rates per match or per minute when analyzing a partial season alongside completed seasons.
Matches
Each row is one completed fixture, uniquely identified by season_end_year and match_id. All seasons use the same Football-Data results definitions. Club names have been standardized across years. The home_team_id and away_team_id values are normalized versions of those standardized names, shared with the team-season table.
| Variables | Meaning |
|---|---|
match_date, kickoff_time, referee |
Date, kickoff time where supplied, and referee |
home_team, away_team |
Clubs |
home_goals, away_goals |
Full-time goals |
result |
H = home win, D = draw, A = away win |
home_half_goals, away_half_goals, half_result |
Half-time goals and result |
home_shots, away_shots |
Shots attempted |
home_shots_on_target, away_shots_on_target |
Shots on target |
home_fouls, away_fouls |
Fouls |
home_corners, away_corners |
Corners |
home_yellow_cards, away_yellow_cards, home_red_cards, away_red_cards |
Cards |
source_url and retrieved_date record provenance. Betting odds and expected goals with inconsistent availability were dropped from this common match table. Counts are match totals. See the source’s field definitions.
Team seasons
epl_teams <- read_csv("https://bcdanl.github.io/data/epl_teams.csv")The key is season_end_year and team_id. Every season contains 20 clubs. Completed seasons contain 38 matches per club; 2026–27 currently contains five. Club name is squad.
matches_played, wins, draws, losses, goals, goals_against, and goal_difference summarize the match table. points is three per win plus one per draw and excludes administrative point deductions. Team goals include opponents’ own goals, unlike a sum of goals credited to individual players.
shots, shots_on_target, corners, fouls, yellow_cards, and red_cards sum the same source’s match statistics for every season. Divide totals by matches_played for comparable rates.
The earlier FBref measures remain in the same CSV as fbref_num_players, fbref_age, fbref_poss, fbref_assists, fbref_xg, and fbref_xa. They cover 2017–18 through 2024–25 and are missing afterward. Possession uses a 0–100 percentage scale. The provider prefix distinguishes those definitions from the common Football-Data totals.
Player seasons
epl_players <- read_csv("https://bcdanl.github.io/data/epl_players.csv")The key is season_end_year and player_id. Each row is a player’s league-season total. Historical FBref team-stint rows are aggregated once per player and season, so players who transferred between EPL clubs are not counted twice. Their squad lists clubs separated by semicolons.
Coverage changes by source and season:
| Seasons | Source and coverage |
|---|---|
| 2021–22 through 2024–25 | Historical FBref players with recorded EPL appearances |
| 2025–26 | All 841 players in the final FPL season archive, including players with zero minutes |
| 2026–27 | All 667 players listed in the current official FPL snapshot, including zero-minute players |
The 2025–26 snapshot comes from Vaastav Anand’s FPL Historical Dataset, pinned to its June 17, 2026 update after gameweek 38. All 480 players also present in the current API’s prior-season history match the archive across 16 fields, including minutes, goals, assists, cards, saves, and fantasy points. Credited goals plus own goals reconcile to the match table’s full season goal total. This archive includes players who left the league before the current season.
FPL snapshots include listed players with zero minutes, whereas historical FBref rows require a recorded appearance. The coverage and source columns identify these differences. Filter to minutes > 0 when comparing participating-player populations. Archived FPL club labels describe the final roster snapshot; a transferred player’s totals cover the whole league season.
player_id uses stable FPL player codes where available. Historical rows share an FPL code only when an exact normalized display/full-name match and equal birth year identify one candidate. Remaining historical rows use a fbref-name: name/birth-year key. These fallback keys are teaching identifiers, not official FBref IDs. Name variants without a verified match remain separate. fpl_season_player_id is the original FPL ID for that row’s season; it can change between seasons. fpl_player_code is the stable source code.
| Variables | Meaning |
|---|---|
player, birth_year, squad, nation, pos |
Player descriptors where supplied |
appearances, starts, minutes |
Season appearances where supplied, starts, and minutes |
goals, yellow_cards, red_cards |
Season totals |
conventional_assists |
FBref assists, historical rows only |
fpl_assists |
Fantasy assists under FPL scoring rules, FPL rows only |
gross_salary_weekly_pound, gross_salary_yearly_pound |
Historical salary estimates; missing for FPL rows and historical players with multiple clubs |
fantasy_price_million_pound |
FPL game price in millions of pounds; previous-season value is its closing price |
fbref_xg, fbref_xa |
Historical FBref expected goals/assists |
fpl_xg, fpl_xa, fpl_xg_conceded |
FPL expected statistics |
fpl_points |
Fantasy point total |
clean_sheets, goals_conceded, own_goals, penalties_saved, penalties_missed, saves |
FPL season totals |
FPL prices describe a fantasy game’s valuation and are not salaries. FPL assists can differ from conventional match assists; the two columns remain separate. Expected statistics also retain their provider names. Do not add these separate fields together or fill one provider’s missing values with another’s. FPL clean-sheet points require at least 60 minutes played without conceding, under the game’s rules.
Historical positions are FBref’s codes such as GK, DF, MF, and FW, including combined positions. Current positions are FPL’s GKP, DEF, MID, and FWD classifications. Historical per-90, progressive-action, and other advanced fields were dropped from the combined player table when they had no comparable current measure. Season totals and minutes allow you to calculate your own rates.
Source: official FPL, its current player endpoint and player-history endpoints, the 2025–26 FPL archive, and the supplied historical FBref EPL tables.
Goalkeeper seasons
epl_gks <- read_csv("https://bcdanl.github.io/data/epl_goalkeepers.csv")Each row is a goalkeeper’s season total, keyed by season_end_year and player_id. Historical team stints are aggregated. minutes comes from exact player-table totals, rather than multiplying rounded 90-minute units.
The historical goalkeeper field formerly named goals is now goals_conceded: it measures goals allowed, not goals scored. fbref_post_shot_xg and fbref_post_shot_xg_minus_goals retain historical shot-stopping estimates. They are missing in FPL seasons. FPL supplies starts, clean_sheets, saves, penalties_saved, fpl_xg_conceded, fantasy points, and fantasy prices; fields absent from historical tables remain missing.
FPL seasons use each season’s own goalkeeper classification: 97 listed goalkeepers in 2025–26 and 73 in 2026–27. Registered zero-minute goalkeepers remain included. Compare goals allowed and saves alongside minutes played, and respect the coverage differences described above.
Project ideas
- How do shots and shots on target predict match results over time?
- Does home advantage vary across seasons?
- Which clubs improve their points and goal difference per match?
- How do player goals per 90 minutes vary by role and season?
- How do fantasy valuations relate to fantasy performance within the FPL cohort?
- How do goalkeeper goals allowed per 90 minutes change across seasons?
Sports Reference removed its advanced soccer feed in January 2026. Source-specific historical measures remain labeled where retained, and the dated source archives remain available separately from these combined downloads.
