Data and API
Where every number comes from, how fresh it is, and how to fetch it yourself.
Everything is up to date
6:54:03 PM ET| Scoreboardevery 60 s on game nights | every 60 s on game nights | 2026-11-14: 14 games, 0 live, 2 final · 6:53:55 PM |
| Play-by-playevery 10 s while live | every 10 s while live | 1 live · 6:25:22 PM |
| Final gamesas games go final | as games go final | 0 of 0 final games settled · 5:01:14 AM |
| Shift chartsuntil they appear | until they appear | 0 of 50 games without shifts have them now · 5:02:04 AM |
| Nightly importdaily 5:00 AM | daily 5:00 AM | done in 124 s · 5:02:04 AM |
| Trophy winnersnightly until a season’s are in | nightly until a season’s are in | 828 trophy winners · 1:41:37 PM |
Sources
NHL Web API api-web.nhle.com/v1
Scores, schedules, games and play-by-play, standings on any date, rosters, playoff brackets
NHL Stats API api.nhle.com/stats/rest/en
Shift charts, player bios (nationality for flags), season summaries, franchises and seasons
NHL Records records.nhl.com/site/api
Trophy winners and franchise history, for the seasons archive
sportsdataverse fastRhockey, sportsdataverse-py
How to parse the NHL’s documents; a possible one-time history import
Use the API
read-only JSON, no keyEvery page has a twin under /api/v1. Put it in front of the page’s path and you get the data behind the page.
$ curl https://hockeydata.io/api/v1/seasons/2024-25
{ "data": { "season": 20242025, "headline": "Florida wins the Stanley Cup again", … },
"meta": { "canonical": "/seasons/2024-25", "final": true, "updatedAt": … } } $ curl https://hockeydata.io\
/api/v1/seasons/2024-25
{ "data": {
"season": 20242025,
"headline": "Florida wins …", … },
"meta": {
"canonical": "/seasons/2024-25",
"final": true,
"updatedAt": … } } Credits and terms
Data © NHL. hockeydata.io is an independent fan project, not affiliated with or endorsed by the NHL or its teams. No team logos are used: the diagonal colour marks are our own, always shown with the team abbreviation. If you use our numbers, link the page you took them from.
The archive
every season since 1917–18, by what the NHL recorded then| Era | Seasons | Results | Box scores | Goals and penalties | Full play-by-play | Shot locations | Shifts |
|---|---|---|---|---|---|---|---|
| 2010–11 to now | 17 | every game | every game | every one | shots, hits, faceoffs, blocks | where each shot came from | every shift |
| 1997–98 to 2009–10 | 12 | every game | with ice time, hits, faceoffs | every one | not recorded | not recorded | counts per player only |
| 1917–18 to 1996–97 | 80 | every game | goals, assists, penalties; shots where kept | every one | not recorded | not recorded | not recorded |
108 finished seasons · 70,309 games · 7,970 skaters and 904 goalies, each with a bio and season lines · 2004–05 was not played
recorded partly not recorded
API reference
the same paths as the pages, under /api/v1| Base | /api/v1, the same paths as the pages |
|---|---|
| Access | Read-only JSON, no key, CORS open |
| Ids | team col · player 8477492 · game 2026-11-12/col-dal (an NHL game id redirects) · season 2026-27 |
| Time | ISO dates; UTC in data, Eastern on pages |
| Envelope | { data, meta }, where meta has canonical, updatedAt, final and sources |
| Caching | ETag and Cache-Control by freshness; final games are immutable |
| Errors | application/problem+json (RFC 9457): status, title, detail and suggested links in see |
| Versions | /v1 grows only by addition; breaking changes go to /v2 |
| GET /api/v1 | Returns | Fresh |
|---|---|---|
| /scores/{date} | Games on a date: teams, score, state, clock, three stars, flow-strip series | 30 s · past 1 d |
| /schedule/{yyyy-mm} | Days with game counts and matchups; ?team= | 1 d |
| /games/{date}/{away}-{home} | Venue, periods, goals, penalties, stars, team stats, skaters, goalies | 10 s · final ∞ |
| /games/{…}/flow | Every attempt, goals with the score after them, power plays, a box per period; ?strength= | 10 s · final ∞ |
| /games/{…}/shots | Attempts with x, y, shooter and goalie, per team; ?team= &period= &strength= &type= | 10 s · final ∞ |
| /games/{…}/shifts | A team’s units and ice time by strength, once the NHL’s shift charts are out; ?team= | 30 s · final ∞ |
| /games/{…}/live | Server-sent events: shot, goal, penalty, period, final | stream |
| /standings/{season} | The table; ?view= &date= | 5 min · past ∞ |
| /standings/{season}/race/{group} | Rank and points, week by week | 1 d |
| /leaders/{season}/{category} | Ranked players; ?pos= &team= &country= &rookies= &min-gp= | after finals |
| /teams | 32 teams, record, last ten, next game; ?view= | 5 min |
| /teams/{team}/{season} | Record, ranks, special teams, season strip, leaders, division, last and next game | 5 min · past 1 d |
| /teams/{team}/{season}/schedule | Every game with result, record and points after it; ?month= | 5 min · past 1 d |
| /teams/{team}/{season}/roster | Skaters and goalies with season stats; ?sort= &dir= | 5 min · past 1 d |
| /players | Directory; ?q= &team= &pos= &letter= &country=, paged with ?limit= &cursor= | 1 h |
| /players/{id} | Bio, this season with league ranks, last ten games, career, honours | 5 min · retired 1 d |
| /players/{id}/{season} | Game log with totals; ?type=playoffs | 5 min · past 1 d |
| /playoffs/{season} | Bracket, every series game by game, the Final; projected during the season | 1 h · past 1 d |
| /seasons | Every season: champion, Final, Presidents’ Trophy, trophy winners; ?decade= | 1 h |
| /seasons/{season} | Champion, trophies, scoring leaders, best record | 1 h · past 1 d |
| /search?q= | Players, teams, seasons, games and trophy winners | 1 h |
| /search-index | The whole search index in one file, versioned by a hash of its contents; ?v= is cached for a year | 1 h |
A wrong address answers 404 in problem+json with links to what you probably meant, the same suggestions as the page. The full reference is docs/api.md.
When we fetch
One worker mirrors the NHL into Postgres through one polite fetcher, about one request a second with backoff. Pages read our copy; every NHL response is kept, so history can be rebuilt without asking again.
| Daily, 5:00 AM | Seasons, the schedule, teams, rosters and bios, yesterday’s and today’s standings, the bracket once the regular season ends, trophy winners while a season’s are missing |
|---|---|
| Game days | The scoreboard every 60 s from 30 minutes before puck drop, otherwise every 10 minutes |
| While a game is live | Play-by-play every 10 s; each change goes to every open page of that game |
| When a game goes final | Box score, landing, play-by-play, shift charts (retried until they appear); the game becomes immutable |
| First run | The season so far, the final tables since 2015–16, the brackets since 2016 and the trophy winners since 2005–06 |
Freshness
| Final games | immutable: cached for a year |
|---|---|
| Past dates and seasons | 1 day |
| Today’s scores | 30 seconds |
| Live games | streamed; 15 s polling as the fallback |
| Standings and leaders | rebuilt after each final |
House rules
- The data belongs to the NHL: credited on every page, no logos, non-commercial.
- One fetcher, about one request a second, never scraping nhl.com pages.
- Unofficial endpoints change: every response is kept, and shapes are tested.
- Some data arrives late: we say “data incomplete” rather than guess.
About
hockeydata.io is NHL scores, standings, leaders and history on plain, bookmarkable pages: every page is a URL, and every page has a JSON twin. It is an independent fan project by Alex Silachev, built in the open under the MIT licence: github.com/asilachev/hockeydata-io.
- Data © NHL, from its public endpoints; team names and colours belong to their teams.
- Flags from flag-icons by Panayiotis Lipiridis, MIT licence.
- Type: IBM Plex Sans and Plex Mono, SIL Open Font License, bundled from Fontsource.
- Endpoints mapped by the NHL-API-Reference by Zmalski.
- Parsing after sportsdataverse and fastRhockey.
- Colours from the Nord Lane theme, after Nord.