๐ NBA hoops with sportsdataverse-py
This page is the executed notebook
04_nba_intro.ipynb: download it to run it yourself.
Welcome to the hardwood! ๐ In just a few lines of Python you're about to pull a whole season of NBA data โ teams, standings, rosters, play-by-play, box scores, schedules and statistical leaders โ straight from ESPN and the SportsDataverse data releases. Everything comes back as a tidy polars DataFrame that's ready to slice, model, and chart. ๐
We lead with the richest surface in the package: the espn_nba_* family,
backed by ESPN's site / web / core APIs. If you know the R package
hoopR, these names will feel like home.
Python neighbor for the raw NBA Stats endpoints:
nba_api. Let's lace 'em up! ๐
๐งฐ The toolboxโ
Here's the kit we'll reach for. The espn_nba_* wrappers (โญ our
premium source) hit ESPN live and parse the JSON into polars for you; the
load_nba_* loaders pull pre-built season parquets from the
sportsdataverse-data
releases โ fast and reliable. Click any name for the full reference.
| Function | What it gives you | Source |
|---|---|---|
espn_nba_teams | All 30 NBA teams (grab team_ids here) | โญ ESPN |
espn_nba_scoreboard | A day's slate โ scores, status, matchups | โญ ESPN |
espn_nba_schedule | Schedule for a date / date-range | โญ ESPN |
espn_nba_standings | Conference standings (W-L, win%, streak) | โญ ESPN |
espn_nba_team_roster | A team's active roster | โญ ESPN |
espn_nba_team_schedule | One team's full-season schedule | โญ ESPN |
espn_nba_player_gamelog | A player's game-by-game log | โญ ESPN |
espn_nba_leaders | League statistical leaders | โญ ESPN |
espn_nba_pbp | Full game payload (play-by-play, win prob, box) | โญ ESPN |
espn_nba_game_rosters | Both teams' rosters for one game | โญ ESPN |
load_nba_schedule | Multi-season schedule parquet | ๐ฆ release |
load_nba_player_boxscore | Player box scores, every game | ๐ฆ release |
load_nba_standings | Historical standings | ๐ฆ release |
espn_nba_injuries | League-wide injury report, one row per team | โญ ESPN |
load_nba_team_boxscore | Team box scores, every game (off/def, shooting) | ๐ฆ release |
load_nba_shots | Every made shot with court coordinates | ๐ฆ release |
most_recent_nba_season | The current season year helper | ๐งฎ util |
๐ Setupโ
pip install sportsdataverse
No API key needed โ ESPN's public endpoints and the data releases are open. ๐
import polars as pl
import sportsdataverse as sdv
from sportsdataverse.nba import most_recent_nba_season
pl.Config.set_tbl_rows(8)
SEASON = most_recent_nba_season()
print('current NBA season:', SEASON)
current NBA season: 2027
ESPN endpoints are live and seasonal, so we'll route every network call
through a tiny safe() helper. When the feed is up you get the frame; when
it's mid-offseason or briefly rate-limited you get a friendly one-liner
instead of a scary traceback. ๐
from sportsdataverse.errors import AssetFetchError, NoDataError
def safe(label, thunk):
try:
out = thunk()
n = out.height if isinstance(out, pl.DataFrame) else (len(out) if hasattr(out, '__len__') else '?')
print(f'โ
{label} โ {n} rows')
return out
except (NoDataError, AssetFetchError) as e:
print(f"\u23ed\ufe0f {label}: {type(e).__name__}: {e}")
return None
๐๏ธ Teamsโ
Start with espn_nba_teams โ
one wide row per franchise. The team_id column is the key you'll pass into
roster, schedule and standings calls everywhere else.
teams = safe('teams', sdv.nba.espn_nba_teams)
(teams.select(['team_id', 'team_location', 'team_name', 'team_abbreviation', 'team_color']).head(10)
if teams is not None else 'teams feed unavailable')
โ
teams โ 30 rows
shape: (10, 5)
โโโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ team_id โ team_location โ team_name โ team_abbreviation โ team_color โ
โ --- โ --- โ --- โ --- โ --- โ
โ i64 โ str โ str โ str โ str โ
โโโโโโโโโโโชโโโโโโโโโโโโโโโโชโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโก
โ 1 โ Atlanta โ Hawks โ ATL โ c8102e โ
โ 2 โ Boston โ Celtics โ BOS โ 008348 โ
โ 17 โ Brooklyn โ Nets โ BKN โ 000000 โ
โ 30 โ Charlotte โ Hornets โ CHA โ 008ca8 โ
โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ
โ 6 โ Dallas โ Mavericks โ DAL โ 0064b1 โ
โ 7 โ Denver โ Nuggets โ DEN โ 0e2240 โ
โ 8 โ Detroit โ Pistons โ DET โ 1d428a โ
โ 9 โ Golden State โ Warriors โ GS โ fdb927 โ
โโโโโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโ
๐ Today on the slate (scoreboard)โ
espn_nba_scoreboard returns a
tidy frame of every game for a date โ final scores, live status, and
matchups. Pass dates='YYYYMMDD' for one day. Here's a slice of the 2024
NBA Finals opener.
sb = safe('scoreboard', lambda: sdv.nba.espn_nba_scoreboard(dates='20240606'))
keep = ['game_id', 'short_name', 'home_abbreviation', 'away_abbreviation',
'home_score', 'away_score', 'status_type_detail']
(sb.select([c for c in keep if c in sb.columns]).head()
if sb is not None and sb.height else 'no games on that date')
โ
scoreboard โ 1 rows
shape: (1, 7)
โโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ
โ game_id โ short_name โ home_abbrevia โ away_abbrevia โ home_score โ away_score โ status_type_d โ
โ --- โ --- โ tion โ tion โ --- โ --- โ etail โ
โ i64 โ str โ --- โ --- โ str โ str โ --- โ
โ โ โ str โ str โ โ โ str โ
โโโโโโโโโโโโโชโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโชโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโก
โ 401656359 โ DAL @ BOS โ BOS โ DAL โ 107 โ 89 โ Final โ
โโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโ
๐ Standingsโ
espn_nba_standings gives one
row per team with wins, losses, win%, point differential and current streak.
Pass season= (the end year of the season).
standings = safe('standings', lambda: sdv.nba.espn_nba_standings(season=SEASON))
cols = ['team_display_name', 'wins', 'losses', 'win_percent', 'games_behind',
'point_differential', 'streak']
(standings.select([c for c in cols if c in standings.columns])
.sort('win_percent', descending=True).head(10)
if standings is not None and standings.height else 'standings unavailable')
โ
standings โ 30 rows
shape: (10, 7)
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโ
โ team_display_name โ wins โ losses โ win_percent โ games_behind โ point_differential โ streak โ
โ --- โ --- โ --- โ --- โ --- โ --- โ --- โ
โ str โ f64 โ f64 โ f64 โ f64 โ f64 โ f64 โ
โโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโชโโโโโโโโโชโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโก
โ Detroit Pistons โ 3.0 โ 0.0 โ 1.0 โ 0.0 โ 38.0 โ 3.0 โ
โ Portland Trail โ 2.0 โ 0.0 โ 1.0 โ 0.5 โ 49.0 โ 2.0 โ
โ Blazers โ โ โ โ โ โ โ
โ Minnesota โ 3.0 โ 0.0 โ 1.0 โ 0.0 โ 70.0 โ 3.0 โ
โ Timberwolves โ โ โ โ โ โ โ
โ Oklahoma City Thunder โ 3.0 โ 0.0 โ 1.0 โ 0.0 โ 31.0 โ 3.0 โ
โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ
โ Houston Rockets โ 3.0 โ 0.0 โ 1.0 โ 0.0 โ 29.0 โ 3.0 โ
โ Philadelphia 76ers โ 3.0 โ 1.0 โ 0.75 โ 0.5 โ 12.0 โ -1.0 โ
โ Atlanta Hawks โ 2.0 โ 1.0 โ 0.6666667 โ 1.0 โ 47.0 โ -1.0 โ
โ Toronto Raptors โ 2.0 โ 1.0 โ 0.6666667 โ 1.0 โ 30.0 โ -1.0 โ
โโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโ
๐ณ Cookbook: common NBA tasksโ
Now the fun part โ a handful of recipes you'll reach for again and again.
Each one leans on the premium espn_nba_* wrappers.
Recipe 1 โ A team and its roster ๐ฅโ
Grab a team_id from espn_nba_teams,
then pull the active roster with
espn_nba_team_roster.
tid = None
if teams is not None and teams.height:
# Boston Celtics if present, else the first team
row = teams.filter(pl.col('team_abbreviation') == 'BOS')
tid = int((row if row.height else teams)['team_id'][0])
roster = safe(f'roster {tid}', lambda: sdv.nba.espn_nba_team_roster(team_id=tid)) if tid else None
cols = ['full_name', 'jersey', 'position_abbreviation', 'height', 'weight', 'age']
(roster.select([c for c in cols if c in roster.columns]).head(10)
if roster is not None and roster.height else 'roster unavailable')
โ
roster 2 โ 17 rows
shape: (10, 6)
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโฌโโโโโโ
โ full_name โ jersey โ position_abbreviation โ height โ weight โ age โ
โ --- โ --- โ --- โ --- โ --- โ --- โ
โ str โ str โ str โ f64 โ f64 โ i64 โ
โโโโโโโโโโโโโโโโโโโโชโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโชโโโโโโโโโชโโโโโโก
โ Devin Carter โ 99 โ G โ 74.0 โ 188.0 โ 24 โ
โ Chris Cenac Jr. โ 12 โ F โ 83.0 โ 240.0 โ 19 โ
โ Mike Conley โ 45 โ G โ 73.0 โ 175.0 โ 39 โ
โ Luka Garza โ 52 โ C โ 82.0 โ 243.0 โ 27 โ
โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ
โ Ron Harper Jr. โ 8 โ G โ 77.0 โ 233.0 โ 26 โ
โ Sam Hauser โ 30 โ F โ 80.0 โ 221.0 โ 28 โ
โ Dillon Mitchell โ 20 โ F โ 80.0 โ 210.0 โ 23 โ
โ Payton Pritchard โ 11 โ G โ 74.0 โ 211.0 โ 28 โ
โโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโดโโโโโโ
Recipe 2 โ One team's season schedule ๐โ
espn_nba_team_schedule
returns every game on a team's calendar for a season โ perfect for building
a results table or a strength-of-schedule view.
tsched = safe(f'team schedule {tid}',
lambda: sdv.nba.espn_nba_team_schedule(team_id=tid, season=SEASON)) if tid else None
cols = ['id', 'date', 'name', 'short_name', 'season_year']
(tsched.select([c for c in cols if c in tsched.columns]).head()
if tsched is not None and tsched.height else 'team schedule unavailable')
โ
team schedule 2 โ 80 rows
shape: (5, 5)
โโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โ id โ date โ name โ short_name โ season_year โ
โ --- โ --- โ --- โ --- โ --- โ
โ i64 โ str โ str โ str โ i64 โ
โโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโชโโโโโโโโโโโโโโก
โ 401909088 โ 2026-10-20T19:00Z โ Boston Celtics at Detroit Pistโฆ โ BOS @ DET โ 2027 โ
โ 401909095 โ 2026-10-23T23:00Z โ New York Knicks at Boston Celtโฆ โ NY @ BOS โ 2027 โ
โ 401909870 โ 2026-10-26T23:30Z โ Chicago Bulls at Boston Celticโฆ โ CHI @ BOS โ 2027 โ
โ 401909877 โ 2026-10-27T23:30Z โ Brooklyn Nets at Boston Celticโฆ โ BKN @ BOS โ 2027 โ
โ 401909278 โ 2026-10-30T23:30Z โ Chicago Bulls at Boston Celticโฆ โ CHI @ BOS โ 2027 โ
โโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโโ
Recipe 3 โ A player's game log โน๏ธโ
espn_nba_player_gamelog
returns a game-by-game stat line for one athlete. The stat_* columns are
positional (the ordered ESPN box categories); pair them with the opponent
and result columns to see how the night went. (1966 = LeBron James.)
gamelog = safe('LeBron gamelog',
lambda: sdv.nba.espn_nba_player_gamelog(athlete_id=1966, season=SEASON))
cols = ['event_date', 'opponent_abbreviation', 'home_away', 'game_result', 'score',
'stat_0', 'stat_1', 'stat_2']
(gamelog.select([c for c in cols if c in gamelog.columns]).head()
if gamelog is not None and gamelog.height else 'gamelog unavailable')
โ
LeBron gamelog โ 5 rows
shape: (5, 8)
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโ
โ event_date โ opponent_abbreviation โ home_away โ game_result โ score โ stat_0 โ stat_1 โ stat_2 โ
โ --- โ --- โ --- โ --- โ --- โ --- โ --- โ --- โ
โ str โ str โ str โ str โ str โ str โ str โ str โ
โโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโชโโโโโโโโโโโโโโชโโโโโโโโชโโโโโโโโโชโโโโโโโโโชโโโโโโโโโก
โ null โ null โ null โ null โ null โ 33 โ 8-15 โ 53.3 โ
โ null โ null โ null โ null โ null โ 33 โ 5-14 โ 35.7 โ
โ null โ null โ null โ null โ null โ 34 โ 5-13 โ 38.5 โ
โ null โ null โ null โ null โ null โ 25 โ 4-9 โ 44.4 โ
โ null โ null โ null โ null โ null โ 18 โ 1-1 โ 100.0 โ
โโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโดโโโโโโโโโดโโโโโโโโโ
Recipe 4 โ Top scorers from the box-score release ๐ฅโ
For a whole-season leaderboard the
load_nba_player_boxscore
release is your friend โ it's a fast parquet download, no live API needed.
Here we average points per game and rank the top 10 scorers.
box = safe('player boxscore release', lambda: sdv.nba.load_nba_player_boxscore(seasons=[SEASON]))
if box is not None and box.height:
leaders = (
box.filter(pl.col('minutes') > 0)
.group_by(['athlete_display_name', 'team_abbreviation'])
.agg(pl.len().alias('gp'),
pl.col('points').mean().round(1).alias('ppg'),
pl.col('rebounds').mean().round(1).alias('rpg'),
pl.col('assists').mean().round(1).alias('apg'))
.filter(pl.col('gp') >= 20)
.sort('ppg', descending=True)
.head(10)
)
out = leaders
else:
out = 'box-score release unavailable'
out
โ
player boxscore release โ 995 rows
shape: (0, 6)
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโฌโโโโโโฌโโโโโโฌโโโโโโ
โ athlete_display_name โ team_abbreviation โ gp โ ppg โ rpg โ apg โ
โ --- โ --- โ --- โ --- โ --- โ --- โ
โ str โ str โ u32 โ f64 โ f64 โ f64 โ
โโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโชโโโโโโชโโโโโโชโโโโโโชโโโโโโก
โโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโดโโโโโโดโโโโโโดโโโโโโดโโโโโโ
Recipe 5 โ Offense vs defense, every team ๐ก๏ธโ
The load_nba_team_boxscore
release has one row per team-game with both team_score and
opponent_team_score โ so points-for, points-against and net rating are a
single group_by away.
tbox = safe('team boxscore release', lambda: sdv.nba.load_nba_team_boxscore(seasons=[SEASON]))
if tbox is not None and tbox.height:
netrtg = (
tbox.group_by('team_abbreviation')
.agg(pl.len().alias('gp'),
pl.col('team_score').mean().round(1).alias('off_ppg'),
pl.col('opponent_team_score').mean().round(1).alias('def_ppg'))
.with_columns((pl.col('off_ppg') - pl.col('def_ppg')).round(1).alias('net'))
.sort('net', descending=True)
.head(10)
)
out = netrtg
else:
out = 'team box-score release unavailable'
out
โ
team boxscore release โ 72 rows
shape: (10, 5)
โโโโโโโโโโโโโโโโโโโโโฌโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโ
โ team_abbreviation โ gp โ off_ppg โ def_ppg โ net โ
โ --- โ --- โ --- โ --- โ --- โ
โ str โ u32 โ f64 โ f64 โ f64 โ
โโโโโโโโโโโโโโโโโโโโโชโโโโโโชโโโโโโโโโโชโโโโโโโโโโชโโโโโโโก
โ TOR โ 2 โ 123.5 โ 97.0 โ 26.5 โ
โ POR โ 2 โ 126.0 โ 101.5 โ 24.5 โ
โ MIN โ 2 โ 123.0 โ 99.5 โ 23.5 โ
โ ATL โ 3 โ 124.7 โ 109.0 โ 15.7 โ
โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ
โ OKC โ 2 โ 106.0 โ 94.0 โ 12.0 โ
โ MEM โ 2 โ 117.0 โ 105.5 โ 11.5 โ
โ HOU โ 3 โ 121.0 โ 111.3 โ 9.7 โ
โ LAC โ 2 โ 119.0 โ 110.5 โ 8.5 โ
โโโโโโโโโโโโโโโโโโโโโดโโโโโโดโโโโโโโโโโดโโโโโโโโโโดโโโโโโโ
Recipe 6 โ Who lived behind the arc? ๐ฏโ
Sum makes and attempts across the season to get each team's true
three-point percentage (game-level percentages can't just be averaged).
Reuses the tbox frame from Recipe 5 โ no second download.
if tbox is not None and tbox.height:
three_pt = (
tbox.group_by('team_abbreviation')
.agg(pl.col('three_point_field_goals_made').sum().alias('made'),
pl.col('three_point_field_goals_attempted').sum().alias('att'))
.with_columns((100 * pl.col('made') / pl.col('att')).round(1).alias('three_pt_pct'))
.filter(pl.col('att') > 0)
.sort('three_pt_pct', descending=True)
.head(10)
)
out = three_pt
else:
out = 'team box-score release unavailable'
out
shape: (10, 4)
โโโโโโโโโโโโโโโโโโโโโฌโโโโโโโฌโโโโโโฌโโโโโโโโโโโโโโโ
โ team_abbreviation โ made โ att โ three_pt_pct โ
โ --- โ --- โ --- โ --- โ
โ str โ i32 โ i32 โ f64 โ
โโโโโโโโโโโโโโโโโโโโโชโโโโโโโชโโโโโโชโโโโโโโโโโโโโโโก
โ DET โ 33 โ 78 โ 42.3 โ
โ HOU โ 40 โ 96 โ 41.7 โ
โ LAL โ 25 โ 60 โ 41.7 โ
โ LAC โ 30 โ 72 โ 41.7 โ
โ โฆ โ โฆ โ โฆ โ โฆ โ
โ BOS โ 32 โ 81 โ 39.5 โ
โ MEM โ 28 โ 73 โ 38.4 โ
โ MIL โ 45 โ 121 โ 37.2 โ
โ NY โ 27 โ 73 โ 37.0 โ
โโโโโโโโโโโโโโโโโโโโโดโโโโโโโดโโโโโโดโโโโโโโโโโโโโโโ
Recipe 7 โ Double-double machines ๐ชโ
A double-double is double digits in two of points / rebounds / assists.
Count the categories per player-game, keep the ones that cleared two, then
tally them up โ straight from
load_nba_player_boxscore.
pbox = safe('player boxscore release', lambda: sdv.nba.load_nba_player_boxscore(seasons=[SEASON]))
if pbox is not None and pbox.height:
dd = (
pbox.filter(pl.col('minutes') > 0)
.with_columns(
((pl.col('points') >= 10).cast(pl.Int8)
+ (pl.col('rebounds') >= 10).cast(pl.Int8)
+ (pl.col('assists') >= 10).cast(pl.Int8)).alias('cats10'))
.filter(pl.col('cats10') >= 2)
.group_by(['athlete_display_name', 'team_abbreviation'])
.agg(pl.len().alias('double_doubles'))
.sort('double_doubles', descending=True)
.head(10)
)
out = dd
else:
out = 'player box-score release unavailable'
out
โ
player boxscore release โ 995 rows
shape: (10, 3)
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโ
โ athlete_display_name โ team_abbreviation โ double_doubles โ
โ --- โ --- โ --- โ
โ str โ str โ u32 โ
โโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโก
โ Amen Thompson โ HOU โ 3 โ
โ Trae Young โ WSH โ 2 โ
โ Karl-Anthony Towns โ NY โ 2 โ
โ Domantas Sabonis โ SAC โ 2 โ
โ โฆ โ โฆ โ โฆ โ
โ Victor Wembanyama โ SA โ 2 โ
โ Davion Mitchell โ MIA โ 2 โ
โ Jalen Johnson โ ATL โ 2 โ
โ Paul Reed โ DET โ 1 โ
โโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโ
Recipe 8 โ A tidy standings table ๐โ
The load_nba_standings
release ships in long format (one row per team ร stat). Pivot the stats
you care about into columns to get a classic standings grid, sorted by
win percentage.
stload = safe('standings release', lambda: sdv.nba.load_nba_standings(seasons=[SEASON]))
wanted = ['wins', 'losses', 'winPercent', 'playoffSeed', 'pointDifferential']
if stload is not None and stload.height and {'stat_name', 'value'}.issubset(stload.columns):
table = (
stload.filter(pl.col('stat_name').is_in(wanted))
.select(['team_abbreviation', 'group_name', 'stat_name', 'value'])
.pivot(values='value', index=['team_abbreviation', 'group_name'], on='stat_name')
.sort('winPercent', descending=True)
.head(12)
)
out = table
else:
out = 'standings release unavailable'
out
โ
standings release โ 0 rows
'standings release unavailable'
Recipe 9 โ Built on threes (shot release + a join) ๐งฑโ
load_nba_shots is one row per
made shot with a score_value. Tally points from twos vs threes per team,
then join team abbreviations from the box-score release to find who
leaned hardest on the long ball.
shots = safe('shots release', lambda: sdv.nba.load_nba_shots(seasons=[SEASON]))
if shots is not None and shots.height and tbox is not None and tbox.height:
fg = shots.filter(pl.col('score_value').is_in([2, 3]))
reliance = (
fg.group_by('team_id')
.agg(pl.col('score_value').filter(pl.col('score_value') == 3).len().alias('threes_made'),
pl.col('score_value').sum().alias('points_from_fg'))
.with_columns((3 * pl.col('threes_made')).alias('points_from_threes'))
.with_columns((100 * pl.col('points_from_threes') / pl.col('points_from_fg'))
.round(1).alias('pct_pts_from_3'))
.filter(pl.col('threes_made') >= 500) # drop All-Star / special rosters
)
abbr = tbox.select(['team_id', 'team_abbreviation']).unique()
out = (reliance.join(abbr, on='team_id', how='left')
.select(['team_abbreviation', 'threes_made', 'pct_pts_from_3'])
.sort('pct_pts_from_3', descending=True).head(10))
else:
out = 'shots / team box-score release unavailable'
out
โ
shots release โ 8390 rows
shape: (0, 3)
โโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโ
โ team_abbreviation โ threes_made โ pct_pts_from_3 โ
โ --- โ --- โ --- โ
โ str โ u32 โ f64 โ
โโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโก
โโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโ
Recipe 10 โ Head-to-head, game by game ๐คโ
Filter the team box-score release to one matchup and you get the full season series โ every meeting, the score, and who won. Swap the two abbreviations for any rivalry you like.
TEAM_A, TEAM_B = 'BOS', 'NY'
if tbox is not None and tbox.height and 'opponent_team_abbreviation' in tbox.columns:
series = (
tbox.filter((pl.col('team_abbreviation') == TEAM_A)
& (pl.col('opponent_team_abbreviation') == TEAM_B))
.select([c for c in ['game_date', 'team_home_away', 'team_score',
'opponent_team_score', 'team_winner']
if c in tbox.columns])
.sort('game_date')
)
out = series if series.height else f'no {TEAM_A} vs {TEAM_B} games in {SEASON}'
else:
out = 'team box-score release unavailable'
out
shape: (1, 5)
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โ game_date โ team_home_away โ team_score โ opponent_team_score โ team_winner โ
โ --- โ --- โ --- โ --- โ --- โ
โ date โ str โ i32 โ i32 โ bool โ
โโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโก
โ 2026-10-23 โ home โ 107 โ 103 โ true โ
โโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโ
Recipe 11 โ Who's banged up? ๐ฉน (pandas interop)โ
espn_nba_injuries hits ESPN
live for the league-wide injury report. Ask for a pandas frame with
return_as_pandas=True (a handy interop point), count the listed players
per team, then hand the result back to polars for the final sort.
import ast
inj = safe('injuries', lambda: sdv.nba.espn_nba_injuries(return_as_pandas=True))
if inj is not None and getattr(inj, 'shape', (0,))[0] and 'injuries' in inj.columns:
def _n_listed(s):
try:
v = ast.literal_eval(s) if isinstance(s, str) else s
return len(v) if isinstance(v, list) else 0
except Exception:
return 0
inj = inj.copy()
inj['players_listed'] = inj['injuries'].apply(_n_listed)
out = (pl.from_pandas(inj[['display_name', 'players_listed']])
.filter(pl.col('players_listed') > 0)
.sort('players_listed', descending=True)
.head(12))
else:
out = 'injury report unavailable (off-season or feed down)'
out
โ
injuries โ 27 rows
shape: (12, 2)
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโ
โ display_name โ players_listed โ
โ --- โ --- โ
โ str โ i64 โ
โโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโก
โ Dallas Mavericks โ 6 โ
โ Golden State Warriors โ 6 โ
โ Oklahoma City Thunder โ 6 โ
โ Philadelphia 76ers โ 6 โ
โ โฆ โ โฆ โ
โ Indiana Pacers โ 4 โ
โ Sacramento Kings โ 4 โ
โ Chicago Bulls โ 3 โ
โ Detroit Pistons โ 3 โ
โโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโ
๐ฌ Play-by-play & game rostersโ
Now for the granular stuff. espn_nba_pbp
returns the whole game payload as a dict โ play-by-play, win probability,
box score, and header โ keyed by game_id (an ESPN event id). Pair it with
espn_nba_game_rosters for who actually
suited up.
We'll use Game 1 of the 2024 Finals (game_id=401585660).
GAME_ID = 401585660
pbp = safe('pbp payload', lambda: sdv.nba.espn_nba_pbp(game_id=GAME_ID))
(list(pbp.keys())[:8] if isinstance(pbp, dict) else 'pbp unavailable')
โ
pbp payload โ 22 rows
['gameId',
'plays',
'winprobability',
'boxscore',
'header',
'format',
'broadcasts',
'videos']
plays = (pl.DataFrame(pbp['plays'], infer_schema_length=None)
if isinstance(pbp, dict) and pbp.get('plays') else None)
cols = ['period.number', 'clock.displayValue', 'text', 'homeScore', 'awayScore', 'scoringPlay']
(plays.select([c for c in cols if c in plays.columns]).head()
if plays is not None and plays.height else 'no plays parsed')
shape: (5, 6)
โโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โ period.number โ clock.displayValue โ text โ homeScore โ awayScore โ scoringPlay โ
โ --- โ --- โ --- โ --- โ --- โ --- โ
โ i64 โ str โ str โ i64 โ i64 โ bool โ
โโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโชโโโโโโโโโโโโชโโโโโโโโโโโโโโก
โ 1 โ 12:00 โ Myles Turner vs. โ 0 โ 0 โ false โ
โ โ โ Anthony Davisโฆ โ โ โ โ
โ 1 โ 11:42 โ Aaron Nesmith makes โ 0 โ 3 โ true โ
โ โ โ 26-foot thโฆ โ โ โ โ
โ 1 โ 11:17 โ Austin Reaves misses โ 0 โ 3 โ false โ
โ โ โ driving lโฆ โ โ โ โ
โ 1 โ 11:14 โ Austin Reaves โ 0 โ 3 โ false โ
โ โ โ offensive rebounโฆ โ โ โ โ
โ 1 โ 11:12 โ Austin Reaves misses โ 0 โ 3 โ false โ
โ โ โ 14-foot tโฆ โ โ โ โ
โโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโ
Slice it: every 3-pointer in the game ๐ฏโ
The plays frame is just polars โ so a scoring slice is one filter away.
Here we pull made three-pointers in chronological order.
if plays is not None and plays.height:
threes = (
plays.filter(pl.col('scoringPlay') == True)
.filter(pl.col('text').str.contains('(?i)three point|3pt|three-point'))
.select([c for c in ['period.number', 'clock.displayValue', 'text',
'homeScore', 'awayScore'] if c in plays.columns])
)
out = threes.head(10) if threes.height else 'no three-pointers matched the text filter'
else:
out = 'no plays to slice'
out
shape: (10, 5)
โโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโ
โ period.number โ clock.displayValue โ text โ homeScore โ awayScore โ
โ --- โ --- โ --- โ --- โ --- โ
โ i64 โ str โ str โ i64 โ i64 โ
โโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโชโโโโโโโโโโโโก
โ 1 โ 11:42 โ Aaron Nesmith makes 26-foot thโฆ โ 0 โ 3 โ
โ 1 โ 10:14 โ Andrew Nembhard makes 23-foot โฆ โ 2 โ 6 โ
โ 1 โ 9:58 โ LeBron James makes 26-foot thrโฆ โ 5 โ 6 โ
โ 1 โ 5:44 โ Myles Turner makes 25-foot thrโฆ โ 15 โ 19 โ
โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ
โ 2 โ 10:05 โ Max Christie makes 25-foot thrโฆ โ 41 โ 40 โ
โ 2 โ 9:39 โ Obi Toppin makes 27-foot threeโฆ โ 41 โ 43 โ
โ 2 โ 8:44 โ Aaron Nesmith makes 26-foot thโฆ โ 41 โ 49 โ
โ 2 โ 7:02 โ Rui Hachimura makes 22-foot thโฆ โ 51 โ 51 โ
โโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโ
Who played? Game rosters ๐โ
espn_nba_game_rosters returns both teams'
rosters for a single game, one row per athlete โ including the starter
flag and jersey number.
grosters = safe('game rosters', lambda: sdv.nba.espn_nba_game_rosters(game_id=GAME_ID))
cols = ['athlete_display_name', 'team_abbreviation', 'starter', 'jersey', 'position_name']
(grosters.select([c for c in cols if c in grosters.columns]).head(10)
if grosters is not None and grosters.height else 'game rosters unavailable')
โ
game rosters โ 26 rows
shape: (10, 5)
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโ
โ athlete_display_name โ team_abbreviation โ starter โ jersey โ position_name โ
โ --- โ --- โ --- โ --- โ --- โ
โ str โ str โ bool โ str โ str โ
โโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโชโโโโโโโโโชโโโโโโโโโโโโโโโโก
โ LeBron James โ LAL โ true โ 23 โ Forward โ
โ Anthony Davis โ LAL โ true โ 23 โ Forward โ
โ Rui Hachimura โ LAL โ true โ 28 โ Forward โ
โ Spencer Dinwiddie โ LAL โ true โ 26 โ Point Guard โ
โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ
โ Cam Reddish โ LAL โ false โ 5 โ Small Forward โ
โ Jaxson Hayes โ LAL โ false โ 11 โ Center โ
โ Max Christie โ LAL โ false โ 0 โ Guard โ
โ Harry Giles III โ LAL โ false โ 20 โ Power Forward โ
โโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโ
๐ฆ Bulk season data with the loadersโ
When you want everything for a season at once โ not one game at a time โ
the load_nba_* loaders pull pre-built parquet releases. They're fast,
reliable, and don't depend on a live API being up.
| Loader | Grain |
|---|---|
load_nba_schedule | one row per game |
load_nba_player_boxscore | one row per player-game |
load_nba_standings | one row per team-season |
sched = safe('schedule release', lambda: sdv.nba.load_nba_schedule(seasons=[SEASON]))
cols = ['id', 'date', 'home_display_name', 'away_display_name', 'home_score', 'away_score']
(sched.select([c for c in cols if c in sched.columns]).head()
if sched is not None and sched.height else 'schedule release unavailable')
โ
schedule release โ 1206 rows
shape: (5, 6)
โโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ id โ date โ home_display_name โ away_display_name โ home_score โ away_score โ
โ --- โ --- โ --- โ --- โ --- โ --- โ
โ i32 โ str โ str โ str โ i32 โ i32 โ
โโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโชโโโโโโโโโโโโโก
โ 401910945 โ 2027-04-12T00:30Z โ Dallas Mavericks โ Memphis Grizzlies โ 0 โ 0 โ
โ 401910946 โ 2027-04-12T00:30Z โ Minnesota โ Houston Rockets โ 0 โ 0 โ
โ โ โ Timberwolves โ โ โ โ
โ 401910947 โ 2027-04-12T00:30Z โ San Antonio Spurs โ Portland Trail โ 0 โ 0 โ
โ โ โ โ Blazers โ โ โ
โ 401910948 โ 2027-04-12T00:30Z โ Denver Nuggets โ Oklahoma City โ 0 โ 0 โ
โ โ โ โ Thunder โ โ โ
โ 401910949 โ 2027-04-12T00:30Z โ Golden State โ Utah Jazz โ 0 โ 0 โ
โ โ โ Warriors โ โ โ โ
โโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโ
Pipeline: the highest-scoring games of the season ๐ฅโ
With the schedule release in hand, a combined-points leaderboard is a quick polars pipeline โ cast the scores, sum them, sort descending.
stats.nba.com surface (nba_stats_*)โ
Beyond the ESPN wrappers, sportsdataverse.nba also ships 128 wrappers for the official stats.nba.com API โ the same source powering nba_api. The module is nba_stats and every function is named nba_stats_<slug>. These are the capture-confirmed live, non-deprecated endpoints; deprecated and never-populated endpoints are excluded (see ENDPOINT_HEALTH.md in sdv-internal-refs for the full active/dying/barren/dead matrix).
League routing is a single league_id parameter: "00" โ NBA, "20" โ G-League, "15" โ Summer League. One stem, one host, league chosen per call.
curl_cffi required for live calls: stats.nba.com uses TLS/JA3 fingerprinting that silently blocks plain requests. Install the optional transport: pip install "sportsdataverse[all]" (or pip install curl_cffi). The wrappers run fully offline when fed a fixture โ live calls simply need the extra installed.
Wrappers return a tidy polars DataFrame by default (parsed via the generic parse_nba_stats_result_sets parser โ which also flattens the shot-location endpoints' grouped 2-level headers into composite columns and unrolls the scoreboardv3 game feed). Pass return_parsed=False for the raw Dict or return_as_pandas=True for pandas. Multi-result-set endpoints (e.g. playercareerstats) return dict[str, DataFrame].
from sportsdataverse.nba import nba_stats
# NBA player dashboard (polars DataFrame by default)
# Live calls require: pip install "sportsdataverse[all]" (curl_cffi transport)
df = safe('nba_stats_leaguedashplayerstats (NBA)',
lambda: nba_stats.nba_stats_leaguedashplayerstats(league_id="00"))
# Same endpoint, other leagues via league_id on the SAME stem:
gleague = safe('nba_stats_leaguedashplayerstats (G-League)',
lambda: nba_stats.nba_stats_leaguedashplayerstats(league_id="20"))
summer = safe('nba_stats_leaguedashplayerstats (Summer League)',
lambda: nba_stats.nba_stats_leaguedashplayerstats(league_id="15"))
# Multi result-set endpoint -> dict[str, polars.DataFrame]
career = safe('nba_stats_playercareerstats (LeBron)',
lambda: nba_stats.nba_stats_playercareerstats(player_id="2544"))
print('career result sets:', list(career.keys()) if isinstance(career, dict) else career)
df
โ
nba_stats_leaguedashplayerstats (NBA) โ 582 rows
โ
nba_stats_leaguedashplayerstats (G-League) โ 526 rows
โ
nba_stats_leaguedashplayerstats (Summer League) โ 450 rows
โ
nba_stats_playercareerstats (LeBron) โ 14 rows
career result sets: ['SeasonTotalsRegularSeason', 'CareerTotalsRegularSeason', 'SeasonTotalsPostSeason', 'CareerTotalsPostSeason', 'SeasonTotalsAllStarSeason', 'CareerTotalsAllStarSeason', 'SeasonTotalsCollegeSeason', 'CareerTotalsCollegeSeason', 'SeasonTotalsShowcaseSeason', 'CareerTotalsShowcaseSeason', 'SeasonRankingsRegularSeason', 'SeasonRankingsPostSeason', 'SeasonHighs', 'CareerHighs']
shape: (582, 69)
โโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโ
โ player_id โ player_nam โ nickname โ team_id โ โฆ โ td3_rank โ wnba_fant โ fp_high_s โ team_coun โ
โ --- โ e โ --- โ --- โ โ --- โ asy_pts_r โ core_rank โ t โ
โ i64 โ --- โ str โ i64 โ โ i64 โ ank โ --- โ --- โ
โ โ str โ โ โ โ โ --- โ i64 โ i64 โ
โ โ โ โ โ โ โ i64 โ โ โ
โโโโโโโโโโโโโชโโโโโโโโโโโโโชโโโโโโโโโโโชโโโโโโโโโโโโชโโโโชโโโโโโโโโโโชโโโโโโโโโโโโชโโโโโโโโโโโโชโโโโโโโโโโโโก
โ 1630639 โ A.J. โ A.J. โ 161061276 โ โฆ โ 38 โ 449 โ 454 โ 1 โ
โ โ Lawson โ โ 1 โ โ โ โ โ โ
โ 1631260 โ AJ Green โ AJ โ 161061274 โ โฆ โ 38 โ 139 โ 167 โ 1 โ
โ โ โ โ 9 โ โ โ โ โ โ
โ 1642358 โ AJ Johnson โ AJ โ 161061274 โ โฆ โ 38 โ 413 โ 412 โ 2 โ
โ โ โ โ 2 โ โ โ โ โ โ
โ 203932 โ Aaron โ Aaron โ 161061274 โ โฆ โ 38 โ 241 โ 250 โ 1 โ
โ โ Gordon โ โ 3 โ โ โ โ โ โ
โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ
โ 1630192 โ Zeke Nnaji โ Zeke โ 161061274 โ โฆ โ 38 โ 371 โ 373 โ 1 โ
โ โ โ โ 3 โ โ โ โ โ โ
โ 1630533 โ Ziaire โ Ziaire โ 161061275 โ โฆ โ 38 โ 233 โ 244 โ 1 โ
โ โ Williams โ โ 1 โ โ โ โ โ โ
โ 1629627 โ Zion โ Zion โ 161061274 โ โฆ โ 38 โ 70 โ 65 โ 1 โ
โ โ Williamson โ โ 0 โ โ โ โ โ โ
โ 1642389 โ Zyon โ Zyon โ 161061275 โ โฆ โ 38 โ 537 โ 533 โ 1 โ
โ โ Pullin โ โ 0 โ โ โ โ โ โ
โโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโดโโโโดโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโ
if sched is not None and sched.height and {'home_score', 'away_score'}.issubset(sched.columns):
hot = (
sched.with_columns(
(pl.col('home_score').cast(pl.Int64, strict=False)
+ pl.col('away_score').cast(pl.Int64, strict=False)).alias('total_points')
)
.filter(pl.col('total_points').is_not_null())
.sort('total_points', descending=True)
.select([c for c in ['date', 'home_display_name', 'away_display_name',
'home_score', 'away_score', 'total_points'] if c in sched.columns])
.head(10)
)
out = hot
else:
out = 'schedule release unavailable'
out
shape: (10, 5)
โโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ date โ home_display_name โ away_display_name โ home_score โ away_score โ
โ --- โ --- โ --- โ --- โ --- โ
โ str โ str โ str โ i32 โ i32 โ
โโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโชโโโโโโโโโโโโโก
โ 2026-10-25T01:00Z โ Denver Nuggets โ New Orleans Pelicans โ 141 โ 135 โ
โ 2026-10-23T20:00Z โ Milwaukee Bucks โ Chicago Bulls โ 125 โ 132 โ
โ 2026-10-21T23:00Z โ Orlando Magic โ Atlanta Hawks โ 125 โ 132 โ
โ 2026-10-25T02:00Z โ Phoenix Suns โ Golden State Warriors โ 131 โ 122 โ
โ โฆ โ โฆ โ โฆ โ โฆ โ โฆ โ
โ 2026-10-25T00:00Z โ Chicago Bulls โ Washington Wizards โ 120 โ 124 โ
โ 2026-10-21T23:00Z โ Washington Wizards โ Milwaukee Bucks โ 128 โ 116 โ
โ 2026-10-24T23:30Z โ Philadelphia 76ers โ Milwaukee Bucks โ 127 โ 116 โ
โ 2026-10-22T00:00Z โ New Orleans Pelicans โ Indiana Pacers โ 120 โ 123 โ
โโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโ
๐ Where to nextโ
You just toured the premium espn_nba_* surface plus the season
loaders โ teams, scoreboard, standings, rosters, schedules, player game
logs, play-by-play, and bulk box scores. A few parting tips:
- Pass
return_as_pandas=Trueto any wrapper for a pandas frame instead of polars. - ESPN
espn_nba_*wrappers also acceptreturn_parsed=Falsefor the raw JSON dict. - Full reference lives in the NBA section of the sidebar: ESPN site API ยท ESPN web API ยท ESPN core API ยท additional functions ยท loaders
- R user? The same surface lives in hoopR.
- Need raw NBA Stats endpoints? See nba_api.
Now go break down some film โ and may your jumper always find the bottom of the net! ๐๐ฅ
๐ฆ Officiatingโ
Last Two Minute reports and referee assignments, from official.nba.com and the
NBA's own feeds.
from sportsdataverse.nba import nba_officiating
print("nba_officiating:", [n for n in dir(nba_officiating) if not n.startswith("_")][:8])
safe("referee assignments", lambda: nba_officiating.nba_referee_assignments("2024-04-01"))
safe("L2M games", lambda: nba_officiating.nba_l2m_games(2024))
nba_officiating: ['Any', 'AssetFetchError', 'L2M_CALLS_SCHEMA', 'L2M_GAME_SCHEMA', 'L2M_STATS_SCHEMA', 'Literal', 'NBA_REFEREE_ASSIGN_SCHEMA', 'NBA_REFEREE_REPLAY_SCHEMA']
โ
referee assignments โ 2 rows
โ
L2M games โ 413 rows
shape: (413, 4)
โโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ game_id โ season โ season_type โ label โ
โ --- โ --- โ --- โ --- โ
โ str โ i32 โ str โ str โ
โโโโโโโโโโโโโโชโโโโโโโโโชโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโก
โ 0042300403 โ 2024 โ playoffs โ Celtics 106, Mavericks 99 โ
โ 0042300314 โ 2024 โ playoffs โ Timberwolves 105, Mavericks 10โฆ โ
โ 0042300304 โ 2024 โ playoffs โ Celtics 105, Pacers 102 โ
โ 0042300303 โ 2024 โ playoffs โ Celtics 114, Pacers 111 โ
โ โฆ โ โฆ โ โฆ โ โฆ โ
โ 0022300068 โ 2024 โ regular โ Heat 103, Pistons 102 โ
โ 0022300069 โ 2024 โ regular โ Raptors 97, Timberwolves 94 โ
โ 0022300073 โ 2024 โ regular โ Mavericks 126, Spurs 119 โ
โ 0022300062 โ 2024 โ regular โ Suns 108, Warriors 104 โ
โโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ