Skip to contents

fastRhockey is an R package for accessing hockey data via public web APIs: the PWHL (Professional Women’s Hockey League), the NHL (National Hockey League), the AHL and the three Canadian major-junior leagues (OHL, WHL, QMJHL), thirteen European leagues, and NCAA men’s and women’s college hockey through ESPN. It provides structured data frames of play-by-play, schedule, standings, roster, draft, player stats, and team data. The package also includes integrated expected goals (xG) models for NHL data.

Part of the SportsDataverse family of R/Python packages for sports analytics.

fastRhockey holographic logo banner
fastRhockey holographic logo banner

Installation

You can install the CRAN version of fastRhockey with:

install.packages("fastRhockey")

You can install the development version from GitHub with:

if (!requireNamespace('pak', quietly = TRUE)){
  install.packages('pak')
}
pak::pak("sportsdataverse/fastRhockey")

PWHL Data

The PWHL (Professional Women’s Hockey League) launched in January 2024 with six teams (Boston, Minnesota, Montreal, New York, Ottawa and Toronto) and added Seattle and Vancouver for 2025-26. fastRhockey provides full access to PWHL schedules, standings, play-by-play, player box scores, team rosters, and stat leaders.

Schedule

Let’s pull the 2024 PWHL season schedule:

schedule <- pwhl_schedule(season = 2024)

schedule %>%
  dplyr::filter(game_status == "Final") %>%
  dplyr::select(game_id, game_date, home_team, away_team,
                home_score, away_score, winner, venue) %>%
  head(10)

The schedule returns game IDs, dates, teams, scores, and venue information for every game in the season.

Standings

pwhl_standings(season = 2024) %>%
  dplyr::select(team_rank, team, games_played, points,
                wins, losses, goals_for, goals_against)

Player Box Scores

Pick a game from the schedule and pull individual player stats. pwhl_player_box() returns a list with two data frames: skaters and goalies.

box <- pwhl_player_box(game_id = 27)

# Skater stats
box[[1]] %>%
  dplyr::select(first_name, last_name, position, team_id,
                goals, assists, points, shots, toi) %>%
  dplyr::arrange(dplyr::desc(points)) %>%
  head(10)

# Goalie stats
box[[2]] %>%
  dplyr::select(first_name, last_name, team_id,
                saves, goals_against, shots_against, toi)

Play-by-Play

The real power of fastRhockey is in the play-by-play data. pwhl_pbp() returns detailed event-level data including shot locations, faceoff results, penalties, goals with assist information, and plus/minus player tracking.

pbp <- pwhl_pbp(game_id = 27)

pbp %>%
  dplyr::select(event, team_id, period_of_game, time_of_period,
                player_name_first, player_name_last,
                x_coord, y_coord) %>%
  head(15)

The play-by-play data includes 90+ columns with event details, player information, coordinates (raw and transformed), and game context.

Stat Leaders

Pull league-wide goalie or skater stats:

# Goalie stats
pwhl_stats(position = "goalie", season = 2024) %>%
  dplyr::select(player_name, team, games_played,
                goals_against_avg, save_percentage, shutouts) %>%
  head(10)
# Skater stats (all teams)
pwhl_stats(position = "skater", season = 2024) %>%
  dplyr::select(player_name, team, games_played,
                goals, assists, points) %>%
  head(10)

NHL Data

fastRhockey also provides extensive access to NHL data via the api-web.nhle.com and api.nhle.com/stats APIs.

Schedule

nhl_schedule(season = "20242025") %>%
  head(10)

Standings

nhl_standings(season = "20242025") %>%
  head(10)

Game Feed and Play-by-Play

The nhl_game_feed() function returns detailed game data including play-by-play, rosters, and game information. nhl_game_pbp() provides play-by-play with shift data integrated.

feed <- nhl_game_feed(game_id = 2024020001)

dplyr::glimpse(feed)

Player Stats

# Skater season stats
nhl_stats_skaters(season = "20242025") %>%
  head(10)

Draft Data

# Get 2024 draft picks (round 1)
nhl_draft_year(year = 2024, round = 1)

Full Season Loaders

For bulk historical data, use the loader functions, which read pre-built season files from the sportsdataverse-data releases instead of calling the APIs. There are 23 NHL loaders (load_nhl_*(), from 2010) and 17 PWHL loaders (load_pwhl_*(), from 2024), plus aliases named to match sportsdataverse-py:

# Full season of play-by-play
pbp <- load_nhl_pbp(seasons = 2024)

# Full season schedule
sched <- load_nhl_schedule(seasons = 2024)

# Full season rosters
rosters <- load_nhl_rosters(seasons = 2024)

Plotting shots on a rink

sportyR draws regulation rinks as ggplot2 layers. The PWHL play-by-play’s x_coord_fixed / y_coord_fixed columns (the AHL, OHL, WHL and QMJHL *_pbp() functions return the same ones) are in feet from centre ice with the home team shooting right, which is the frame sportyR::geom_hockey("pwhl") draws. Neither sportyR nor ggplot2 is a fastRhockey dependency, so install them first (install.packages(c("sportyR", "ggplot2"))). For team logos and colours, see sdvplotR.

library(ggplot2)

pwhl_shots <- load_pwhl_pbp(seasons = 2025) %>%
  dplyr::filter(event %in% c("shot", "goal"),
                !is.na(x_coord_fixed), !is.na(y_coord_fixed))

sportyR::geom_hockey("pwhl") +
  geom_point(
    data = pwhl_shots,
    aes(x = x_coord_fixed, y = y_coord_fixed, colour = event == "goal"),
    alpha = 0.3, size = 0.8
  ) +
  scale_colour_manual(values = c(`FALSE` = "grey40", `TRUE` = "red"),
                      labels = c("Shot", "Goal"), name = NULL)

More leagues

The same calling style covers the other families. Each links to its section of the function reference.

ESPN and Fox Sports NHL

espn_nhl_*() (126 functions) read ESPN’s NHL API and fox_nhl_*() (8 functions) read Fox Sports’ Bifrost API.

espn_nhl_scoreboard(dates = 20250301)
espn_nhl_pbp(game_id = "401688263")
fox_nhl_standings(team_id = "1")

AHL, OHL, WHL and QMJHL

The AHL, OHL, WHL and QMJHL run on the same HockeyTech feed as the PWHL, so each league has the same 12 functions (<league>_schedule(), <league>_pbp(), <league>_standings(), …).

ahl_schedule(season = 2026)
ohl_standings(season = 2026)

European leagues

Thirteen European leagues (211 functions): DEL (del_*), ICE Hockey League (icehl_*), EIHL (eihl_*), Metal Ligaen (metal_*), KHL (khl_*), VHL (vhl_*), SHL (shl_*), HockeyAllsvenskan (ha_*), Liiga (liiga_*), the Swiss federation (sihf_*) and National League (nl_*), the Czech Extraliga (elh_*) and Ligue Magnus (magnus_*). Seasons are end years (2026 = 2025-26). Requests to one host are spaced at least a second apart, and a failed request raises a classed condition (fastRhockey_no_data, fastRhockey_asset_fetch or fastRhockey_bad_request, all inheriting fastRhockey_error) that you can catch with tryCatch().

liiga_schedule(season = 2026)

tryCatch(
  khl_standings(season = 2026),
  fastRhockey_error = function(e) message("KHL request failed: ", conditionMessage(e))
)

NCAA college hockey

ESPN’s men’s (espn_mch_*()) and women’s (espn_wch_*()) college hockey wrappers, 121 per league, mirror the ESPN NHL family.


Deprecated PHF Functions

The Premier Hockey Federation (PHF), formerly the National Women’s Hockey League (NWHL), ceased operations prior to the formation of the PWHL. All phf_* and load_phf_* functions have been defunct since v1.0.0 and stop with an error when called. Use the pwhl_* functions instead for women’s professional hockey data.


Follow the SportsDataverse on Twitter and star this repo

Twitter Follow

GitHub stars

Our Authors

Our Contributors (they’re awesome)

Citations

To cite the fastRhockey R package in publications, use:

BibTeX Citation

@misc{howell_gilani_fastRhockey,
  author = {Ben Howell and Saiem Gilani},
  title = {fastRhockey: Functions to Access Professional Women's Hockey League and National Hockey League Play by Play Data.},
  url = {https://fastRhockey.sportsdataverse.org/},
  doi = {10.32614/CRAN.package.fastRhockey},
  year = {2026}
}