NHL.com Play by Play data

PenguinMario

Registered User
Oct 21, 2011
1,041
1
Los Angeles
Should have been more clear. When you open the recap or box score, the full game ID is displayed in your address bar as id=0123456789. The first five numbers are the year, the last five are the individual game code. E.g., id=2012020418, plug in 20418 and go.

It looks like no 2013-14 data has been added yet, however.
 

Bear of Bad News

Your Third or Fourth Favorite HFBoards Admin
Sep 27, 2005
13,542
27,086
For those who know R, the nhlscrapr package has a way to extract all of the data into a very usable format. Kudos to Sam Ventura and Andrew Thomas for making this publicly available. Might even be worth learning R just for that.

Neat - I had no idea about the R package. Thanks!
 

Step7750

Registered User
Jan 24, 2014
55
1
Calgary, Alberta
Should have been more clear. When you open the recap or box score, the full game ID is displayed in your address bar as id=0123456789. The first five numbers are the year, the last five are the individual game code. E.g., id=2012020418, plug in 20418 and go.

It looks like no 2013-14 data has been added yet, however.

I believe that the actual game code is the last four digits of the gameid. If you look at how Neulion handles the structure of their video service, it is organized like that.

It seems that no matter what, the 5th and 6th digits are always 0 and 2 respectively.

ex. 2011020581

Year - 2011
Same Code - 02
Game Code - 0581

2012020144

Year - 2012
Same Code - 02
Game Code - 0144

2013020524

Year - 2013
Static Code - 02
Game Code - 0524

4 digits are necessary for the "Game Code" due to there being more than 999 games in a season; so if there is an extra 0 in the game code, ignore it when obtaining video highlights (significant digits).


So, the variable name would be contructed like so:

$gameid = $year . "02" . $gamecode; PHP

int gameid = year + "02" + gamecode C++/C

var gameid = year + "02" + gamecode; JavaScript



The structure for how Neulion (Video Service) handles it:

Ex. Highlight Video URL: http://e1.cdnak.neulion.com/nhl/vod...js_cgy_1314_h_discrete_CGY475_goal_1_1600.mp4

I believe the NHL website requires you to have NHL Gamecenter Live to view highlights but I'm not sure.

The URL can be accessed without any credentials, let me explain the structure for the URL to view any highlight from a game.

Base URL: http://e1.cdnak.neulion.com/nhl/vod/

/2014/ - Year of the game
/01/ - Month of the game
/30/ - Day of the game
/815/ - Game code (last 3 digits of the gameid)
2_ - It is a static value, always 2
815_ - Game code (last 3 digits of the gameid)
sjs_ - Away team (San Jose Sharks)
cgy_ - Home team (Calgary Flames)
1314_ - Game season (2013 - 2014)
h_discrete_ - Static value
CGY - Home team (Calgary Flames)
475_ - Highlight ID (You can obtain this from PlayByPlay.jsonp, gcbx.jsonp, gcsb.jsonp etc...)
goal_ - Type of highlight (Goal, save, hit etc...)
1_ - I don't really know what this value stands for, it is either 1 or 2
1600 - Bitrate of the highlight (This is the only bitrate available)



Player "Mug" Pictures:

You need the id of the player in order to access this which can be obtained by scraping the roster data below (I'm still looking for the JSON):

URL: http://3.cdn.nhle.com/photos/mugs/thumb/8476822.jpg

Self explanatory, just change the ending to the desired player id.



Game Calendar:

http://www.nhl.com/gamecenter/en/ajax/gamecalendarjson.htm?month=4&year=2011

Number of games on each day in the specified month; structure is self explanatory.



Game Data for the specified day:

http://live.nhle.com/GameData/GCScoreboard/2010-01-05.jsonp

Year/Month/Day

Returns Team Name, City Name, Winner, Current time of the game, ID of the game, whether Game Center Live is available, Goals Scored (total and for each team), Abbreviations (for getting video highlights) etc... for all of the games that day.

Obviously this is missing some crucial information which can be accessed on a different URL(s).


Game Data for a Specific Game:

There are a couple of URL's for this data, the most common that NHL.com uses are:

Structure: "http://live.nhle.com/GameData/" + Year (ex 20132014) + "/" + Gameid (ex 2013020821) + "/gc/" + Data Wanted (gcsb, gcbx etc...) + ".jsonp"


http://live.nhle.com/GameData/20132014/2013020821/gc/gcsb.jsonp

- Updates way quicker than the data for the specified day (http://live.nhle.com/GameData/GCScoreboard/2013-01-31.jsonp) and contains Team ID's, Player's currently on the ice (gives their jersey numbers), Shots and goals for each team separated by the total or by period, current game time (in seconds in the sr listing), most recent event/play.


http://live.nhle.com/GameData/20132014/2013020758/gc/gcbx.jsonp

- Recommended for in depth recent in-game plays and player stats. Contains recent events (it does not contain all of the events!), goal summary (goal scorer, assists, time, id, teams involved, type of play (you can find the alphabetical equivalents that correspond to the numbers on a script the NHL has which will be discussed below), penalty summary, and the only way to obtain the game stats for each player in the game according to their jersey number (the NHL.com Player ID is not necessary).

- For each player it includes their Assists, Goals, PIM, Plus Minus, Shots, and Time On Ice for that game


PlayByPlay.jsonp is not used by the NHL.com at this current time but contains all of the plays of the game, and goal info; I don't know whether NHL.com will continue to update it in the future.





You can get the roster data for a specific game by scraping the NHL "Ice Tracker" page and finding the gcPlayerMap variable which contains the rosters of the teams involved in the game in JSON.

Ex URL: http://www.nhl.com/gamecenter/en/icetracker?id=2013020780&navid=sb:icetracker

var gcPlayerMap = **"home":**"sw67":**"id":8473564,"so_spctg":"13.3","last":"Frolik","name":"M. Frolik","so_gdg":1,"so_st":15,"so_g":2,"first":"Michael","pos":"R"},"sw2":**"id":8471385,"so_spctg":"0.0","last":"Pardy","name":"A. Pardy","so_gdg":"0","so_st":"0","so_g":"0","first":"Adam","pos":"D"},"sw55":**"id":8476460,"so_spctg":"0.0","last":"Scheifele","name":"M. Scheifele","so_gdg":0,"so_st":1,"so_g":0,"first":"Mark","pos":"C"},"sw7":**"id":8474184,"so_spctg":"0.0","last":"Ellerby","name":"K. Ellerby","so_gdg":"0","so_st":"0","so_g":"0","first":"Keaton","pos":"D"},"sw39":**"id":8470828,"so_spctg":"0.0","last":"Enstrom","name":"T. Enstrom","so_gdg":0,"so_st":1,"so_g":0,"first":"Tobias","pos":"D"},"sw5":**"id":8470614,"so_spctg":"0.0","last":"Stuart","name":"M. Stuart","so_gdg":"0","so_st":"0","so_g":"0","first":"Mark","pos":"D"},"sw16":**"id":8471217,"so_spctg":"48.0","last":"Ladd","name":"A. Ladd","so_gdg":6,"so_st":25,"so_g":12,"first":"Andrew","pos":"L"},"sw9":**"id":8475169,"so_spctg":"9.1","last":"Kane","name":"E. Kane","so_gdg":1,"so_st":11,"so_g":1,"first":"Evander","pos":"L"},"sw17":**"id":8474674,"so_spctg":"0.0","last":"Wright","name":"J. Wright","so_gdg":"0","so_st":"0","so_g":"0","first":"James","pos":"C"},"sw26":**"id":8471218,"so_spctg":"38.1","last":"Wheeler","name":"B. Wheeler","so_gdg":2,"so_st":42,"so_g":16,"first":"Blake","pos":"R"},"sw8":**"id":8476885,"so_spctg":"0.0","last":"Trouba","name":"J. Trouba","so_gdg":"0","so_st":"0","so_g":"0","first":"Jacob","pos":"D"},"sw18":**"id":8473412,"so_spctg":"32.4","last":"Little","name":"B. Little","so_gdg":4,"so_st":34,"so_g":11,"first":"Bryan","pos":"R"},"sw12":**"id":8466140,"so_spctg":"35.7","last":"Jokinen","name":"O. Jokinen","so_gdg":8,"so_st":56,"so_g":20,"first":"Olli","pos":"C"},"sw31":**"id":8471715,"so_spctg":".624","so_l":18,"last":"Pavelec","name":"O. Pavelec","so_w":13,"first":"Ondrej","so_sa":109,"so_ga":41,"pos":"G"},"sw40":**"id":8471682,"so_spctg":"43.5","last":"Setoguchi","name":"D. Setoguchi","so_gdg":5,"so_st":23,"so_g":10,"first":"Devin","pos":"R"},"sw22":**"id":8469501,"so_spctg":"0.0","last":"Thorburn","name":"C. Thorburn","so_gdg":0,"so_st":1,"so_g":0,"first":"Chris","pos":"R"},"sw14":**"id":8474061,"so_spctg":"0.0","last":"Peluso","name":"A. Peluso","so_gdg":0,"so_st":1,"so_g":0,"first":"Anthony","pos":"R"},"sw33":**"id":8470834,"so_spctg":"0.0","last":"Byfuglien","name":"D. Byfuglien","so_gdg":0,"so_st":8,"so_g":0,"first":"Dustin","pos":"D"},"sw35":**"id":8471219,"so_spctg":".633","so_l":5,"last":"Montoya","name":"A. Montoya","so_w":2,"first":"Al","so_sa":30,"so_ga":11,"pos":"G"},"sw44":**"id":8474567,"so_spctg":"100.0","last":"Bogosian","name":"Z. Bogosian","so_gdg":1,"so_st":1,"so_g":1,"first":"Zach","pos":"D"}},"away":**"sw51":**"id":8474581,"so_spctg":"0.0","last":"Gardiner","name":"J. Gardiner","so_gdg":"0","so_st":"0","so_g":"0","first":"Jake","pos":"D"},"sw3":**"id":8470602,"so_spctg":"0.0","last":"Phaneuf","name":"D. Phaneuf","so_gdg":0,"so_st":7,"so_g":0,"first":"Dion","pos":"D"},"sw19":**"id":8470207,"so_spctg":"44.0","last":"Lupul","name":"J. Lupul","so_gdg":6,"so_st":25,"so_g":11,"first":"Joffrey","pos":"L"},"sw37":**"id":8475154,"so_spctg":"0.0","last":"Ashton","name":"C. Ashton","so_gdg":"0","so_st":"0","so_g":"0","first":"Carter","pos":"R"},"sw81":**"id":8473548,"so_spctg":"27.3","last":"Kessel","name":"P. Kessel","so_gdg":13,"so_st":55,"so_g":15,"first":"Phil","pos":"C"},"sw4":**"id":8471742,"so_spctg":"20.0","last":"Franson","name":"C. Franson","so_gdg":1,"so_st":5,"so_g":1,"first":"Cody","pos":"D"},"sw28":**"id":8468778,"so_spctg":"0.0","last":"Orr","name":"C. Orr","so_gdg":"0","so_st":"0","so_g":"0","first":"Colton","pos":"R"},"sw8":**"id":8469476,"so_spctg":"0.0","last":"Gleason","name":"T. Gleason","so_gdg":"0","so_st":"0","so_g":"0","first":"Tim","pos":"D"},"sw42":**"id":8475098,"so_spctg":"55.6","last":"Bozak","name":"T. Bozak","so_gdg":2,"so_st":18,"so_g":10,"first":"Tyler","pos":"C"},"sw11":**"id":8469508,"so_spctg":"50.0","last":"McClement","name":"J. McClement","so_gdg":0,"so_st":4,"so_g":2,"first":"Jay","pos":"C"},"sw24":**"id":8475180,"so_spctg":"0.0","last":"Holland","name":"P. Holland","so_gdg":"0","so_st":"0","so_g":"0","first":"Peter","pos":"C"},"sw43":**"id":8475172,"so_spctg":"23.1","last":"Kadri","name":"N. Kadri","so_gdg":2,"so_st":13,"so_g":3,"first":"Nazem","pos":"C"},"sw12":**"id":8471664,"so_spctg":"27.3","last":"Raymond","name":"M. Raymond","so_gdg":5,"so_st":33,"so_g":9,"first":"Mason","pos":"L"},"sw40":**"id":8470867,"so_spctg":"0.0","last":"Bodie","name":"T. Bodie","so_gdg":"0","so_st":"0","so_g":"0","first":"Troy","pos":"R"},"sw41":**"id":8473579,"so_spctg":"30.0","last":"Kulemin","name":"N. Kulemin","so_gdg":2,"so_st":20,"so_g":6,"first":"Nikolai","pos":"L"},"sw34":**"id":8473503,"so_spctg":".667","so_l":9,"last":"Reimer","name":"J. Reimer","so_w":7,"first":"James","so_sa":54,"so_ga":18,"pos":"G"},"sw21":**"id":8474037,"so_spctg":"50.0","last":"van Riemsdyk","name":"J. van Riemsdyk","so_gdg":3,"so_st":14,"so_g":7,"first":"James","pos":"L"},"sw44":**"id":8476853,"so_spctg":"0.0","last":"Rielly","name":"M. Rielly","so_gdg":"0","so_st":"0","so_g":"0","first":"Morgan","pos":"D"},"sw45":**"id":8473541,"so_spctg":".585","so_l":8,"last":"Bernier","name":"J. Bernier","so_w":6,"first":"Jonathan","so_sa":41,"so_ga":17,"pos":"G"},"sw36":**"id":8474125,"so_spctg":"0.0","last":"Gunnarsson","name":"C. Gunnarsson","so_gdg":"0","so_st":"0","so_g":"0","first":"Carl","pos":"D"}},"homeAbbrev":"WPG","awayAbbrev":"TOR"};


I don't know of a better way to obtain the player id's since that allows you to retrieve stats and link the player with the current game stats.


I am considering to create an API but I would rather have a more reliable player data source (without scraping HTML) before doing so.


The data from NHL's data url's above have almost no delay from the live action which is quite ideal. Here is an example that you can use to see how delayed the data is from realtime, it is a live scoreboard using the data:
singlegame.php


You can just change the parameters on the url (http://54.201.58.234/singlegame.php?gameid=2013020823&date=2014-01-31) to the gameid that you want and the date it is on.

The data for the scores and time is obtained from the gcsb.jsonp address while the plays are obtained from the PlayByPlay.jsonp.
 
Last edited:

Ad

Upcoming events

Ad

Ad