Skip to main content

QMJHL — additional Python functions

Hand-written wrappers, loaders, and helpers in sportsdataverse.hockey.qmjhl that are not generated API-endpoint wrappers (those have their own reference pages).

HockeyTech / LeagueStat​

qmjhl_game_corsi​

qmjhl_game_corsi(game_id: 'int', return_as_pandas: 'bool' = False) -> 'Any'

Player-level on-ice Corsi and Fenwick for a single QMJHL game.

Parameters

ParameterTypeDefaultDescription
game_idintThe HockeyTech game id.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per player on ice for a shot attempt: player_id (Int64), corsi_for / corsi_against / corsi_for_pct, fenwick_for / fenwick_against / fenwick_for_pct, corsi_includes_missed (Boolean), toi_seconds (Int64) and corsi_for_per60 (Float64, null without time on ice). A pandas DataFrame when return_as_pandas is True.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

qmjhl_game_shifts​

qmjhl_game_shifts(game_id: 'int', return_as_pandas: 'bool' = False) -> 'Any'

Parsed shift stints for a single QMJHL game.

Parameters

ParameterTypeDefaultDescription
game_idintThe HockeyTech game id.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per shift: game_id and player_id (Int64), first_name, last_name, jersey_number, home (Int64, 1 = home), period, start_time / end_time / length (clock strings), start_s / end_s (Int64 seconds) and the goal_on_shift / penalty_on_shift flags. A pandas DataFrame when return_as_pandas is True.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

qmjhl_game_summary​

qmjhl_game_summary(game_id: 'int') -> 'dict'

QMJHL game summary — dict of frames (game/goals/penalties/shots_by_period/three_stars).

Parameters

ParameterTypeDefaultDescription
game_idintThe HockeyTech game id.

Returns

game (one row: game_id, date, status, venue, attendance, both teams and scores), goals (one row per goal with the scorer, both assists and the plus / minus skaters), penalties (one row per penalty), shots_by_period (side, period, shots) and three_stars. When the league denies the summary view, the event frames are empty and game is a game_id stub row.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

qmjhl_leaders​

qmjhl_leaders(season: 'Optional[int]' = None, season_id: 'Optional[int]' = None, return_as_pandas: 'bool' = False) -> 'Any'

QMJHL statistical leaders for a given season.

Parameters

ParameterTypeDefaultDescription
seasonOptional[int]NoneSeason as an END year (2026 = the 2025-26 season). Defaults to the newest regular season when neither season nor season_id is given.
season_idOptional[int]NoneThe HockeyTech season id, when it is already known.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per ranked skater (points and goals leaders): rank (Int64), player_id, name, jersey_number, position, team_id / team_name / team_code, stat_formatted and type_formatted (player_id / team_id Int64, the rest String), plus photo and logo URLs. A pandas DataFrame when return_as_pandas is True.

col_nametypedescription
rankInt64Rank of the streak.
player_idInt64Unique player identifier.
jersey_numberStringJersey number.
nameStringTeam mascot name.
team_idInt64Unique team identifier.
team_nameStringTeam name.
team_codeStringTeam abbreviation.
team_logoStringURL to the team logo image.
team_logo_smallStringURL of the small-format team logo image for the player's QMJHL club.
stat_formattedStringThe leader's value in the type_formatted category as a display string; for the Points and Goals leaderboards requested here it is a whole-number count (e.g. '29'), and '0' on every row when the season has no games yet.
type_formattedStringHuman-readable label describing the statistical category for which the player appears on the leaders list (e.g., 'Points', 'Goals', 'Save Percentage').
photoStringURL to the player photo.
photo_smallStringURL of a small-format headshot image of the player from the QMJHL HockeyTech feed.
positionStringPlayer position.
divisionStringDivision identifier.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

qmjhl_pbp​

qmjhl_pbp(game_id: 'int', return_as_pandas: 'bool' = False) -> 'Any'

QMJHL play-by-play — one row per event, fully enriched.

Parameters

ParameterTypeDefaultDescription
game_idintThe HockeyTech game id.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per event (shot, goal, penalty, faceoff, hit, goalie change ...): game_id, event, team_id, period_of_game, time_of_period, rink x_coord / y_coord (Float64, the raw 600×300 feed canvas, NOT feet), the feet frames x_coord_fixed / y_coord_fixed (home team shoots right) and x_coord_right / y_coord_right (every team shoots right), the primary / second / third player and goalie ids (Int64) and names, the plus / minus skaters on a goal, game metadata from the game summary, and derived shot_distance / shot_angle / scoring_chance and the on_ice_home / on_ice_away skaters from the shift feed. The release loader load_pwhl_pbp publishes x_coord in feet, so compare it with x_coord_fixed / x_coord_right here, never with this x_coord. Some leagues (USHL, MJHL) publish only goals, penalties and goalie changes, with no coordinates. A pandas DataFrame when return_as_pandas is True.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

qmjhl_player_stats​

qmjhl_player_stats(player_id: 'int', return_as_pandas: 'bool' = False) -> 'Any'

QMJHL player season stats across all seasons.

Parameters

ParameterTypeDefaultDescription
player_idintThe HockeyTech player id.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per season (and team) the player played: season_id, season_name, playoff, team_id / team_name / team_code, games_played, goals, assists, points, plus_minus, penalty_minutes, power-play / short-handed / shootout splits, shots, faceoff_wins / faceoff_attempts, ice_time and stat_type. season_id and team_id are Int64; the rest are String, as the feed ships them. A pandas DataFrame when return_as_pandas is True.

col_nametypedescription
season_idInt64Season identifier.
season_nameStringFull season name (e.g., "2024-25 Regular Season").
shortnameStringPlayer short name.
playoffStringWhether the row is playoff statistics.
careerStringWhether this is a career-stats season.
sopt_track_faceoffsStringFlag or value indicating whether faceoff tracking is enabled for this player's statistical record in the QMJHL HockeyTech system.
max_start_dateStringLatest game start date for the season.
veteran_statusStringPlayer veteran status.
veteranStringWhether the player is a veteran.
jersey_numberStringJersey number.
goalsStringGoals scored.
games_playedStringGames played.
assistsStringAssists.
pointsStringTotal points (goals + assists).
plus_minusStringPlus/minus rating.
penalty_minutesStringPenalty minutes.
power_play_goalsStringPower-play goals.
power_play_assistsStringPower-play assists.
shotsStringShots on goal.
shootout_attemptsStringShootout attempts.
shootout_goalsStringShootout goals.
shootout_percentageStringShootout scoring percentage.
shooting_percentageStringShooting percentage.
shootout_winning_goalsStringShootout game-winning goals.
points_per_gameStringPoints per game.
short_handed_goalsStringShort-handed goals.
short_handed_assistsStringShort-handed assists.
game_winning_goalsStringGame-winning goals.
game_tieing_goalsStringGame-tying goals.
faceoff_winsStringFaceoff wins.
faceoff_attemptsStringFaceoff attempts.
faceoff_pctStringFaceoff win percentage.
hitsStringHits.
shots_onStringShots on goal count.
shots_wideStringNumber of shots the player directed wide of the net during the season, as tracked in the QMJHL HockeyTech feed.
team_nameStringTeam name.
team_codeStringTeam abbreviation.
team_cityStringTeam city.
team_nicknameStringTeam nickname.
team_idInt64Unique team identifier.
activeStringWhether athlete is currently active.
first_goalsStringFirst goals of a game.
insurance_goalsStringInsurance goals.
overtime_goalsStringOvertime goals.
unassisted_goalsStringUnassisted goals.
empty_net_goalsStringEmpty-net goals.
penalty_minutes_per_gameStringPenalty minutes per game.
divisionStringDivision identifier.
ice_timeStringTotal ice time.
ice_time_minutes_secondsStringIce time in minutes and seconds.
shots_blocked_by_playerStringShots blocked by the player.
stat_typeStringStatistic type ("regular"/"playoff").

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

qmjhl_player_toi​

qmjhl_player_toi(game_id: 'int', return_as_pandas: 'bool' = False) -> 'Any'

Per-player time-on-ice totals for a single QMJHL game.

Parameters

ParameterTypeDefaultDescription
game_idintThe HockeyTech game id.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per player: player_id (Int64), first_name, last_name, toi_seconds (Int64), num_shifts and avg_shift_s (Float64). A pandas DataFrame when return_as_pandas is True.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

qmjhl_schedule​

qmjhl_schedule(season: 'Optional[int]' = None, season_id: 'Optional[int]' = None, return_as_pandas: 'bool' = False) -> 'Any'

QMJHL schedule — one row per game of one season.

Parameters

ParameterTypeDefaultDescription
seasonOptional[int]NoneSeason as an END year (2026 = the 2025-26 season). Defaults to the newest regular season when neither season nor season_id is given.
season_idOptional[int]NoneThe HockeyTech season id, when it is already known.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per game: game_id, game_date, game_status, home_team / home_team_id / home_score, away_team / away_team_id / away_score, venue, season_id and game_type; the *_id columns are Int64, the rest String. Only the requested season's games: a regular season, its playoffs and its preseason are separate season ids, so pass season_id (from qmjhl_season_id()) for the playoffs. A pandas DataFrame when return_as_pandas is True.

col_nametypedescription
game_idInt64Unique game identifier.
game_dateStringGame date.
game_statusStringGame status text.
home_teamStringHome team name.
home_team_idInt64Home team identifier.
home_scoreStringHome team final score.
away_teamStringAway team name.
away_team_idInt64Away team identifier.
away_scoreStringAway team final score.
venueStringVenue where the game was played.
season_idInt64Season identifier.
game_typeStringGame type the row belongs to.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404. With no season given, the seasons feed lists no regular season.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.
ValueErrorNo season matches season.

qmjhl_standings​

qmjhl_standings(season: 'Optional[int]' = None, season_id: 'Optional[int]' = None, return_as_pandas: 'bool' = False) -> 'Any'

QMJHL standings — one row per team.

Parameters

ParameterTypeDefaultDescription
seasonOptional[int]NoneSeason as an END year (2026 = the 2025-26 season). Defaults to the newest regular season when neither season nor season_id is given.
season_idOptional[int]NoneThe HockeyTech season id, when it is already known.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per team: team, team_code, team_rank and wins (Int64), and games_played, losses, regulation_wins, non_reg_wins, non_reg_losses, points, goals_for, goals_against, games_remaining, percentage and overall_rank (String, as the feed ships them). A pandas DataFrame when return_as_pandas is True.

col_nametypedescription
team_codeStringTeam abbreviation.
winsStringWins.
lossesStringLosses.
ot_lossesStringOvertime losses.
ot_winsStringOvertime wins.
shootout_winsStringShootout wins.
shootout_lossesStringShootout losses.
rowString
pointsInt64Total points (goals + assists).
penalty_minutesStringPenalty minutes.
streakStringCurrent streak value.
goals_forStringGoals for.
goals_againstStringGoals against.
goals_diffStringGoals-for minus goals-against differential for the team through the current point in the QMJHL season.
percentageStringPoints percentage representing the fraction of available points earned by the team in the QMJHL standings.
overall_rankString
games_playedStringGames played.
team_rankInt64Team rank in the standings.
past_10StringWin-loss-overtime record string for the team over its most recent ten games (e.g., "7-2-1").
teamStringTeam name.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

qmjhl_team_roster​

qmjhl_team_roster(team_id: 'int', season: 'Optional[int]' = None, season_id: 'Optional[int]' = None, return_as_pandas: 'bool' = False) -> 'Any'

QMJHL team roster for a given team + season.

Parameters

ParameterTypeDefaultDescription
team_idintThe HockeyTech team id.
seasonOptional[int]NoneSeason as an END year (2026 = the 2025-26 season). Defaults to the newest regular season when neither season nor season_id is given.
season_idOptional[int]NoneThe HockeyTech season id, when it is already known.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per rostered player: player_id, person_id, names (first_name, last_name, display_name), position, tp_jersey_number, shoots / catches, height / weight, birthdate, home and birth places, rookie, veteran_status, draft_status and player_image. The id / *_id columns are Int64; the rest are String, as the feed ships them. A pandas DataFrame when return_as_pandas is True.

col_nametypedescription
idInt64Unique player identifier.
person_idInt64Unique person identifier.
activeStringWhether athlete is currently active.
first_nameStringPlayer first name.
last_nameStringPlayer last name.
phonetic_nameStringPhonetic spelling of the player name.
display_nameStringPlayer display name.
shootsStringShooting hand.
hometownStringProspect hometown.
homeprovStringPlayer home province/state.
homecntryStringPlayer home country.
homeplaceStringPlayer home place description.
birthtownStringPlayer birth town.
birthprovStringPlayer birth province/state.
birthcntryStringPlayer birth country.
birthplaceStringCombined birthplace string (typically city and country) for the player as stored in the HockeyTech roster feed.
heightStringPlayer height in inches.
weightStringPlayer weight in pounds.
height_hyphenatedStringPlayer height formatted as a hyphenated feet-inches string (e.g., "6-1") as returned by the HockeyTech feed.
hiddenStringFlag indicating whether this roster entry is suppressed from public-facing displays in the HockeyTech system.
current_teamStringName or identifier of the team to which the player is currently assigned within the HockeyTech system.
player_idInt64Unique player identifier.
statusStringStatus string (e.g. captain markers).
birthdateStringDate of birth.
birthdate_yearStringPlayer birth year.
rawbirthdateStringPlayer's date of birth as a raw string in the format returned by the HockeyTech feed (e.g., "YYYY-MM-DD").
latest_team_idInt64Most recent team identifier.
veteran_statusStringPlayer veteran status.
veteran_descriptionStringText label describing the player's veteran status or classification under QMJHL roster rules.
team_idInt64Unique team identifier.
team_nameStringTeam name.
divisionStringDivision identifier.
tp_jersey_numberStringJersey number assigned to the player on the QMJHL team's official roster (may differ from current game-night number).
rookieStringWhether the player is a rookie.
position_idInt64Official position identifier.
positionStringPlayer position.
nhlteamStringName or abbreviation of the NHL team that holds the player's NHL rights, if applicable.
player_id_1StringPrimary alternate player identifier used by the HockeyTech system to cross-reference player records.
is_rookieStringWhether the player is a rookie.
hString
wString
draft_statusStringDescription of the player's NHL or league draft eligibility or draft history (e.g., "Drafted", "Eligible").
nameStringTeam mascot name.
player_imageStringURL of the player's headshot or profile image as stored in the HockeyTech roster feed.
catchesStringCatching hand (goalies).

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

qmjhl_teams​

qmjhl_teams(season: 'Optional[int]' = None, season_id: 'Optional[int]' = None, return_as_pandas: 'bool' = False) -> 'Any'

QMJHL teams for a given season.

Parameters

ParameterTypeDefaultDescription
seasonOptional[int]NoneSeason as an END year (2026 = the 2025-26 season). Defaults to the newest regular season when neither season nor season_id is given.
season_idOptional[int]NoneThe HockeyTech season id, when it is already known.
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per team: team_id, team_name, team_code, team_nickname, team_label, division and team_logo; team_id is Int64, the rest String. A pandas DataFrame when return_as_pandas is True.

col_nametypedescription
team_nameStringTeam name.
team_idInt64Unique team identifier.
team_codeStringTeam abbreviation.
team_nicknameStringTeam nickname.
team_labelStringShort city label.
divisionStringDivision identifier.
team_logoStringURL to the team logo image.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.

Dates and seasons​

most_recent_qmjhl_season​

most_recent_qmjhl_season() -> 'int'

Newest QMJHL regular season as an end-year integer: the highest season_yr of a regular season that is not a one-off event, so a preseason listed first is not a default.

Returns

The newest regular season's END year (2026 = the 2025-26 season).

Raises

ExceptionDescription
NoDataErrorThe seasons feed lists no regular season.
AssetFetchErrorThe seasons feed failed.

qmjhl_season_id​

qmjhl_season_id(return_as_pandas: 'bool' = False) -> 'Any'

All QMJHL seasons with end-year + game-type labels.

Parameters

ParameterTypeDefaultDescription
return_as_pandasboolFalseReturn a pandas DataFrame instead of polars.

Returns

One row per season: season_id (Int64), season_name, season_short, career, playoff, start_date, end_date, season_yr (Int64, the END year) and game_type_label. A pandas DataFrame when return_as_pandas is True.

col_nametypedescription
season_idInt64Season identifier.
season_nameStringFull season name (e.g., "2024-25 Regular Season").
season_shortStringShort season name.
careerStringWhether this is a career-stats season.
playoffStringWhether the row is playoff statistics.
start_dateStringSeason start date.
end_dateStringSeason end date.
season_yrInt64End year of the season the row belongs to, read from its name: "2025-26", "2025/26" and "2025-2026" are 2026, "26-27" is 2027, a compact "2425" is 2025. A preseason or exhibition named with the one year it starts in belongs to the next season ("2026 Pre-season" is 2027). Null when the name holds no year.
game_type_labelStringGame type read from the season name, first match wins: "preseason" (pre-season, preseason), "playoffs" (playoff, post), "exhibition", else "regular". One-off events such as all-star games are labelled "regular" too; season resolution skips them.

Raises

ExceptionDescription
NoDataErrorThe feed answered 404.
AssetFetchErrorThe fetch failed: a non-2xx status, an empty or unparseable body, or an Undefined Tab / InvalidView sentinel.