π The NFL with sportsdataverse-py
Welcome to gridiron data! π In a handful of lines you're about to pull standings, rosters, weekly injury reports, NextGen Stats tracking leaderboards, and full play-by-play β straight from the source.
sportsdataverse.nfl leads with the premium api.nfl.com
native endpoints (nfl_standings, nfl_rosters, nfl_injuries, β¦) and the
NextGen Stats tracking API (nfl_ngs_*),
backed by the battle-tested nflverse release
loaders (load_nfl_pbp, load_nfl_player_stats, β¦). ESPN
(espn_nfl_*) rides shotgun as a quick, no-auth secondary path.
Every accessor hands you a tidy polars DataFrame by default β pass
return_as_pandas=True for pandas. If you've used the R packages
nflfastR / nflreadr,
or the Python nflreadpy, you're already
home: the load_* names line up. Let's hike it! π
π§° The toolboxβ
Three data families, one module. The π’ premium rows lead with native
api.nfl.com / NextGen Stats endpoints; the π¦ rows read versioned nflverse
release parquets; ESPN is the π΅ quick secondary path. Click any name for the
full reference.
| Function | What it gives you | Source |
|---|---|---|
nfl_standings | Team standings for a season/week β one row per team | π’ premium (NFL.com) |
nfl_rosters | Season rosters, one row per team (players nested) | π’ premium (NFL.com) |
nfl_injuries | Weekly injury report, one row per player | π’ premium (NFL.com) |
nfl_weeks | The week calendar (bye weeks, date ranges) | π’ premium (NFL.com) |
nfl_weekly_game_details | Rich per-game details for a week (drive charts, standings) | π’ premium (NFL.com) |
nfl_game_summaries | Live game state, one row per game | π’ premium (NFL.com) |
nfl_team | Single-team detail by team_id | π’ premium (NFL.com) |
nfl_ngs_statboard | NextGen Stats season leaderboard (passing/rushing/receiving) | π’ premium (NextGen Stats) |
nfl_ngs_leaders | NextGen top-N highlight boards (speed, YAC over expected, β¦) | π’ premium (NextGen Stats) |
nfl_ngs_league_schedule | NextGen schedule β source of NGS gameIds | π’ premium (NextGen Stats) |
nfl_ngs_gamecenter_overview | Per-game NextGen player splits (passers/rushers/β¦) | π’ premium (NextGen Stats) |
load_nfl_pbp | Full nflfastR play-by-play (370+ columns) | π¦ nflverse release |
load_nfl_player_stats | Weekly player box-score stats | π¦ nflverse release |
load_nfl_nextgen_stats | NextGen Stats back to 2016 (release parquet) | π¦ nflverse release |
load_nfl_rosters | Season rosters with IDs & bios | π¦ nflverse release |
espn_nfl_schedule Β· espn_nfl_scoreboard | ESPN scoreboard/schedule (no auth) | π΅ ESPN (secondary) |
load_nfl_snap_counts | Weekly snap counts & snap-share % per player | π¦ nflverse release |
load_nfl_depth_charts | Weekly depth charts, one row per slotted player | π¦ nflverse release |
load_nfl_schedule | Game results + lines, one row per game | π¦ nflverse release |
load_nfl_draft_picks | Every draft pick + career value, one row per pick | π¦ nflverse release |
get_current_nfl_season Β· most_recent_nfl_season | Season helpers | π’ helper |
π Setupβ
pip install sportsdataverse
No API key needed β the native api.nfl.com wrappers mint a fresh
anonymous token for you, and the NextGen Stats client warms its own browser
cookies. The nflverse loaders just read public release parquets. π
import polars as pl
import sportsdataverse.nfl as nfl
pl.Config.set_tbl_cols(8) # keep wide frames readable in the notebook
polars.config.Config
Native NFL.com / NextGen endpoints and ESPN are live services β great
in-season, occasionally grumpy in the offseason or behind a flaky network. A
tiny safe() helper runs each live call defensively: you get the frame when
the feed is up, and a friendly one-liner when it isn't (never a scary
traceback). π The load_* release parquets are reliable, so we call those
directly.
def safe(label, thunk):
"""Run a live call; return its result, or print a one-liner and return None."""
try:
out = thunk()
print(f"β
{label}")
return out
except Exception as e: # noqa: BLE001 -- demo resilience over network blips
print(f"βοΈ {label}: unavailable right now ({type(e).__name__})")
return None
# 2024 is a complete season with full data everywhere β a safe default to demo.
SEASON = 2024
π’ Premium first: NFL.com native standingsβ
The headliner. nfl_standings
returns one row per team with conference/division records, streaks,
clinch flags, point differentials β the works. Pass season, season_type
("REG"/"POST"/"PRE" β strings, not ESPN's numeric codes) and week.
standings = safe(
"NFL.com standings",
lambda: nfl.nfl_standings(season=SEASON, season_type="REG", week=18),
)
standings.shape if standings is not None else "standings unavailable"
β
NFL.com standings
(32, 53)
cols = [
"team_full_name", "conference_rank", "division_rank",
"overall_wins", "overall_losses", "overall_ties",
"division_wins", "division_losses",
]
(standings.select([c for c in cols if c in standings.columns])
.sort("conference_rank")
.head(10)
if standings is not None else "standings unavailable")
shape: (10, 8)
ββββββββββββββ¬βββββββββββββ¬βββββββββββββ¬ββββββββββββ¬ββββββββββββ¬ββββββββββββ¬ββββββββββββ¬ββββββββββββ
β team_full_ β conference β division_r β overall_w β overall_l β overall_t β division_ β division_ β
β name β _rank β ank β ins β osses β ies β wins β losses β
β --- β --- β --- β --- β --- β --- β --- β --- β
β str β i64 β i64 β i64 β i64 β i64 β i64 β i64 β
ββββββββββββββͺβββββββββββββͺβββββββββββββͺββββββββββββͺββββββββββββͺββββββββββββͺββββββββββββͺββββββββββββ‘
β Detroit β 1 β 1 β 15 β 2 β 0 β 6 β 0 β
β Lions β β β β β β β β
β Kansas β 1 β 1 β 15 β 2 β 0 β 5 β 1 β
β City β β β β β β β β
β Chiefs β β β β β β β β
β Buffalo β 2 β 1 β 13 β 4 β 0 β 5 β 1 β
β Bills β β β β β β β β
β Philadelph β 2 β 1 β 14 β 3 β 0 β 5 β 1 β
β ia Eagles β β β β β β β β
β Baltimore β 3 β 1 β 12 β 5 β 0 β 4 β 2 β
β Ravens β β β β β β β β
β Tampa Bay β 3 β 1 β 10 β 7 β 0 β 4 β 2 β
β Buccaneers β β β β β β β β
β Houston β 4 β 1 β 10 β 7 β 0 β 5 β 1 β
β Texans β β β β β β β β
β Los β 4 β 1 β 10 β 7 β 0 β 4 β 2 β
β Angeles β β β β β β β β
β Rams β β β β β β β β
β Los β 5 β 2 β 11 β 6 β 0 β 4 β 2 β
β Angeles β β β β β β β β
β Chargers β β β β β β β β
β Minnesota β 5 β 2 β 14 β 3 β 0 β 4 β 2 β
β Vikings β β β β β β β β
ββββββββββββββ΄βββββββββββββ΄βββββββββββββ΄ββββββββββββ΄ββββββββββββ΄ββββββββββββ΄ββββββββββββ΄ββββββββββββ
π₯ Rosters & the week calendarβ
nfl_rosters gives one row per
team for a season, with the player list nested under persons (great for a
team directory). nfl_weeks is the
season's week calendar β handy for finding bye weeks and date ranges before
you loop over a slate.
| Function | One row per | Key columns |
|---|---|---|
nfl_rosters | team | team_abbreviation, team_conference_abbr, persons |
nfl_weeks | week | week, week_type, bye_teams, date_begin |
rosters = safe("NFL.com rosters", lambda: nfl.nfl_rosters(season=SEASON))
cols = ["team_abbreviation", "team_full_name", "team_conference_abbr", "team_division_full_name"]
(rosters.select([c for c in cols if c in rosters.columns]).head(8)
if rosters is not None else "rosters unavailable")
β
NFL.com rosters
shape: (8, 4)
βββββββββββββββββββββ¬βββββββββββββββββββββ¬βββββββββββββββββββββββ¬ββββββββββββββββββββββββββ
β team_abbreviation β team_full_name β team_conference_abbr β team_division_full_name β
β --- β --- β --- β --- β
β str β str β str β str β
βββββββββββββββββββββͺβββββββββββββββββββββͺβββββββββββββββββββββββͺββββββββββββββββββββββββββ‘
β ARI β Arizona Cardinals β NFC β NFC West β
β ATL β Atlanta Falcons β NFC β NFC South β
β BAL β Baltimore Ravens β AFC β AFC North β
β BUF β Buffalo Bills β AFC β AFC East β
β CAR β Carolina Panthers β NFC β NFC South β
β CHI β Chicago Bears β NFC β NFC North β
β CIN β Cincinnati Bengals β AFC β AFC North β
β CLE β Cleveland Browns β AFC β AFC North β
βββββββββββββββββββββ΄βββββββββββββββββββββ΄βββββββββββββββββββββββ΄ββββββββββββββββββββββββββ
weeks = safe("NFL.com weeks", lambda: nfl.nfl_weeks(season=SEASON, season_type="REG"))
cols = ["season", "week", "week_type", "date_begin", "date_end", "bye_teams"]
(weeks.select([c for c in cols if c in weeks.columns]).head(8)
if weeks is not None else "weeks unavailable")
β
NFL.com weeks
shape: (8, 6)
ββββββββββ¬βββββββ¬ββββββββββββ¬ββββββ βββββββ¬βββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β season β week β week_type β date_begin β date_end β bye_teams β
β --- β --- β --- β --- β --- β --- β
β i64 β i64 β str β str β str β str β
ββββββββββͺβββββββͺββββββββββββͺβββββββββββββͺβββββββββββββͺββββββββββββββββββββββββββββββββββ‘
β 2024 β 18 β REG β 2025-01-01 β 2025-01-08 β [] β
β 2024 β 17 β REG β 2024-12-24 β 2025-01-01 β [] β
β 2024 β 16 β REG β 2024-12-18 β 2024-12-24 β [] β
β 2024 β 15 β REG β 2024-12-11 β 2024-12-18 β [] β
β 2024 β 14 β REG β 2024-12-04 β 2024-12-11 β [{'id': '10400325-48de-3d6a-beβ¦ β
β 2024 β 13 β REG β 2024-11-27 β 2024-12-04 β [] β
β 2024 β 12 β REG β 2024-11-20 β 2024-11-27 β [{'id': '10400200-f401-4e53-51β¦ β
β 2024 β 11 β REG β 2024-11-13 β 2024-11-20 β [{'id': '10403800-517c-7b8c-65β¦ β
ββββββββββ΄βββββββ΄ββββββββββββ΄βββββββββββββ΄βββββββββββββ΄ββββββββββββββββββββββββββββββββββ
π₯ The weekly injury reportβ
nfl_injuries is the official
weekly injury report β one row per listed player with their
injury_status (Out / Doubtful / Questionable), practice participation, and
team. This is the premium native feed, not a scrape.
inj = safe(
"NFL.com injuries",
lambda: nfl.nfl_injuries(season=SEASON, season_type="REG", week=1),
)
cols = [
"team_full_name", "person_display_name", "position",
"injuries", "injury_status", "practice_status",
]
(inj.select([c for c in cols if c in inj.columns]).head(10)
if inj is not None else "injuries unavailable")
β
NFL.com injuries
shape: (10, 6)
βββββββββββββββββββ¬ββββββββββββββββββ¬βββββββββββ¬ββββββββββββββββββ¬ββββββββββββββββ¬ββββββββββββββββββ
β team_full_name β person_display_ β position β injuries β injury_status β practice_status β
β --- β name β --- β --- β --- β --- β
β str β --- β str β str β str β str β
β β str β β β β β
βββββββββββββββββββͺββββββββββββββββββͺβββββββββββͺββββββββββββββββββͺββββββββββββββββͺββββββββββββββββββ‘
β Atlanta Falcons β Ta'Quon Graham β DE β [] β null β LIMITED β
β Atlanta Falcons β Antonio β CB β ['Groin'] β OUT β DIDNOT β
β β Hamilton β β β β β
β Atlanta Falcons β Grady Jarrett β DT β [] β null β DIDNOT β
β Atlanta Falcons β Nate Landman β LB β [] β null β FULL β
β Atlanta Falcons β Chris Lindstrom β G β ['Evaluated for β null β null β
β β β β a possible heaβ¦ β β β
β Atlanta Falcons β Jake Matthews β T β [] β null β LIMITED β
β Atlanta Falcons β David Onyemata β DT β [] β null β DIDNOT β
β Atlanta Falcons β Kyle Pitts β TE β [] β null β FULL β
β Baltimore β Rasheen Ali β RB β ['Neck'] β DOUBTFUL β LIMITED β
β Ravens β β β β β β
β Baltimore β Adisa Isaac β LB β ['Hamstring'] β OUT β DIDNOT β
β Ravens β β β β β β
βββββββββββββββββββ΄ββββββββββββββββββ΄βββββββββββ΄ββββββββββββββββββ΄ββββββββββββββββ΄ββββββββββββββββββ
π Per-game details for a weekβ
Need the full slate with drive charts, broadcast info and embedded standings?
nfl_weekly_game_details
returns one row per game for a week (toggle the heavy blocks with the
include_* flags). For live in-game state (clock, down & distance, red-zone
flags), reach for
nfl_game_summaries.
wgd = safe(
"NFL.com weekly game details",
lambda: nfl.nfl_weekly_game_details(season=SEASON, season_type="REG", week=1),
)
cols = ["week", "date", "game_type", "away_team_full_name", "home_team_full_name", "status"]
(wgd.select([c for c in cols if c in wgd.columns]).head(8)
if wgd is not None else "weekly game details unavailable")
β
NFL.com weekly game details
shape: (8, 6)
ββββββββ¬βββββββββββββ¬ββββββββββββββ¬βββββββββββββββββββββββ¬ββββββββββββββββββββββ¬ββββββββββββ
β week β date β game_type β away_team_full_name β home_team_full_name β status β
β --- β --- β --- β --- β --- β --- β
β i64 β str β str β str β str β str β
ββββββββͺβββββββββββββͺββββββββββββββͺβββββββββββββββββββββββͺββββββββββββββββββββββͺββββββββββββ‘
β 1 β 2024-09-06 β UNSPECIFIED β Baltimore Ravens β Kansas City Chiefs β SCHEDULED β
β 1 β 2024-09-07 β UNSPECIFIED β Green Bay Packers β Philadelphia Eagles β SCHEDULED β
β 1 β 2024-09-08 β UNSPECIFIED β Pittsburgh Steelers β Atlanta Falcons β SCHEDULED β
β 1 β 2024-09-08 β UNSPECIFIED β Arizona Cardinals β Buffalo Bills β SCHEDULED β
β 1 β 2024-09-08 β UNSPECIFIED β Tennessee Titans β Chicago Bears β SCHEDULED β
β 1 β 2024-09-08 β UNSPECIFIED β New England Patriots β Cincinnati Bengals β SCHEDULED β
β 1 β 2024-09-08 β UNSPECIFIED β Houston Texans β Indianapolis Colts β SCHEDULED β
β 1 β 2024-09-08 β UNSPECIFIED β Jacksonville Jaguars β Miami Dolphins β SCHEDULED β
ββββββββ΄βββββββββββββ΄ββββββββββββββ΄βββββββββββββββββββββββ΄ββββββββββββββββββββββ΄ββββββββββββ
β‘ NextGen Stats: the tracking layerβ
This is where it gets fun. The NFL's NextGen Stats API exposes player-tracking metrics you won't find in a box score β time to throw, completion percentage over expectation (CPOE), separation, ball-carrier top speed. All token-free.
nfl_ngs_statboard is the
season leaderboard. Ask for stat_type "passing", "rushing", or
"receiving".
qb = safe(
"NGS passing statboard",
lambda: nfl.nfl_ngs_statboard(stat_type="passing", season=SEASON, season_type="REG"),
)
cols = [
"playerName", "passerRating", "completionPercentageAboveExpectation",
"avgTimeToThrow", "aggressiveness", "passYards", "passTouchdowns",
]
(qb.select([c for c in cols if c in qb.columns])
.sort("passerRating", descending=True)
.head(10)
if qb is not None else "NGS statboard unavailable")
β
NGS passing statboard
shape: (10, 7)
ββββββββββββββββ¬βββββββββββββββ¬βββββββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬ββββββββββββ¬ββββββββββββββ
β playerName β passerRating β completionPe β avgTimeToTh β aggressiven β passYards β passTouchdo β
β --- β --- β rcentageAbov β row β ess β --- β wns β
β str β f64 β eExpecβ¦ β --- β --- β i64 β --- β
β β β --- β f64 β f64 β β i64 β
β β β f64 β β β β β
ββββββββββββββββͺβββββββββββββββͺβββββββββββββββͺββββββββββββββͺββββββββββββββͺββββββββββββͺββββββββββββββ‘
β Lamar β 119.629044 β -0.194641 β 3.144269 β 10.970464 β 4172 β 41 β
β Jackson β β β β β β β
β Jared Goff β 111.769481 β 5.054879 β 2.787295 β 11.502783 β 4629 β 37 β
β Joe Burrow β 108.537832 β 4.521902 β 2.710951 β 15.797546 β 4918 β 43 β
β Baker β 106.761696 β 2.17107 β 2.6982 β 10.877193 β 4500 β 41 β
β Mayfield β β β β β β β
β Jalen Hurts β 103.687673 β 6.305457 β 3.1313 β 16.34349 β 2903 β 18 β
β Sam Darnold β 102.534404 β 2.799064 β 3.083395 β 13.944954 β 4319 β 35 β
β Justin β 101.703042 β 2.391567 β 2.910539 β 15.873016 β 3870 β 23 β
β Herbert β β β β β β β
β Josh Allen β 101.384576 β 0.781139 β 2.886884 β 16.770186 β 3731 β 28 β
β Tua β 101.362782 β 1.696667 β 2.416476 β 12.280702 β 2867 β 19 β
β Tagovailoa β β β β β β β
β Derek Carr β 101.022999 β 3.222724 β 2.758918 β 11.111111 β 2145 β 15 β
ββββββββββββββββ΄βββββββββββββββ΄βββββββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄ββββββββββββ΄ββββββββββββββ
And nfl_ngs_leaders
serves the highlight-reel top-N boards β each row is the play that earned
the leader their spot. Categories include "speed" (fastest ball carriers),
"yac_season" (yards-after-catch over expected), "completion_season"
(most-improbable completions) and more.
fast = safe(
"NGS fastest ball carriers",
lambda: nfl.nfl_ngs_leaders(category="speed", season=SEASON, season_type="REG"),
)
cols = ["leader_playerName", "leader_teamAbbr", "leader_maxSpeed", "leader_yards", "play_playDescription"]
(fast.select([c for c in cols if c in fast.columns]).head(8)
if fast is not None else "NGS leaders unavailable")
β
NGS fastest ball carriers
shape: (8, 5)
βββββββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββββββ¬βββββββββββββββ¬βββββββββββββ βββββββββββββββ
β leader_playerName β leader_teamAbbr β leader_maxSpeed β leader_yards β play_playDescription β
β --- β --- β --- β --- β --- β
β str β str β f64 β i64 β str β
βββββββββββββββββββββͺββββββββββββββββββͺββββββββββββββββββͺβββββββββββββββͺββββββββββββββββββββββββββββ‘
β KaVontae Turpin β DAL β 22.356818 β 64 β (15:00) (Shotgun) C.Rush β
β β β β β pass β¦ β
β Brian Thomas Jr. β JAX β 22.152273 β 85 β (7:12) (Shotgun) β
β β β β β T.Lawrence paβ¦ β
β Jahmyr Gibbs β DET β 22.029546 β 70 β (4:07) (Shotgun) J.Gibbs β
β β β β β left β¦ β
β Saquon Barkley β PHI β 21.927273 β 55 β (11:04) (No Huddle, β
β β β β β Shotgun) Sβ¦ β
β Saquon Barkley β PHI β 21.906818 β 72 β (2:54) (Shotgun) β
β β β β β S.Barkley lefβ¦ β
β Nico Collins β HOU β 21.886364 β 55 β (12:56) C.Stroud pass β
β β β β β deep midβ¦ β
β James Cook β BUF β 21.845455 β 65 β (8:48) A.Anderson β
β β β β β reported in β¦ β
β KaVontae Turpin β DAL β 21.845455 β 18 β J.Elliott kicks 60 yards β
β β β β β from β¦ β
βββββββββββββββββββββ΄ββββββββββββββββββ΄ββββββββββββββββββ΄βββββββββββββββ΄ββββββββββββββββββββββββββββ
π¦ nflverse loaders: the bulk-data workhorsesβ
For full-season modelling you want the nflverse release parquets β the exact same assets that power nflfastR / nflreadr / nflreadpy. These are versioned, cached releases (very reliable), so we call them directly.
| Function | Rows | Highlights |
|---|---|---|
load_nfl_pbp | ~49k/season | EPA, WP, air yards, 370+ columns |
load_nfl_player_stats | weekly | passing/rushing/receiving box lines |
load_nfl_nextgen_stats | weekly | NGS back to 2016 |
load_nfl_rosters | per player | IDs, bios, draft info |
pbp = nfl.load_nfl_pbp([SEASON])
pbp.shape
(49492, 372)
(pbp
.filter(pl.col("play_type").is_not_null())
.select(["game_id", "qtr", "down", "ydstogo", "posteam", "play_type", "yards_gained", "epa", "desc"])
.head(8))
shape: (8, 9)
ββββββββββββββββββ¬ββββββ¬βββββββ¬ββββββββββ¬ββββ¬ββββββββββββ¬βββββββββββββββ¬ββββββββββββ¬ββββββββββββββββ
β game_id β qtr β down β ydstogo β β¦ β play_type β yards_gained β epa β desc β
β --- β --- β --- β --- β β --- β --- β --- β --- β
β str β f64 β f64 β f64 β β str β f64 β f64 β str β
ββββββββββββββββββͺββββββͺβββββββͺββββββββββͺββββͺββββββββββββͺβββββββββββββββͺββββββββββββͺββββββββββββββββ‘
β 2024_01_ARI_BU β 1.0 β null β 0.0 β β¦ β kickoff β 0.0 β 0.257819 β 2-T.Bass β
β F β β β β β β β β kicks 65 β
β β β β β β β β β yards from Bβ¦ β
β 2024_01_ARI_BU β 1.0 β 1.0 β 10.0 β β¦ β run β 3.0 β -0.200602 β (15:00) β
β F β β β β β β β β 6-J.Conner up β
β β β β β β β β β the middβ¦ β
β 2024_01_ARI_BU β 1.0 β 2.0 β 7.0 β β¦ β pass β 22.0 β 2.028874 β (14:27) β
β F β β β β β β β β 1-K.Murray β
β β β β β β β β β pass short β¦ β
β 2024_01_ARI_BU β 1.0 β 1.0 β 10.0 β β¦ β pass β 9.0 β 0.754242 β (13:43) β
β F β β β β β β β β (Shotgun) β
β β β β β β β β β 1-K.Murray pβ¦ β
β 2024_01_ARI_BU β 1.0 β 2.0 β 1.0 β β¦ β run β 2.0 β -0.029602 β (13:02) β
β F β β β β β β β β 6-J.Conner up β
β β β β β β β β β the middβ¦ β
β 2024_01_ARI_BU β 1.0 β 1.0 β 10.0 β β¦ β run β 2.0 β -0.247749 β (12:26) β
β F β β β β β β β β (Shotgun) β
β β β β β β β β β 6-J.Conner lβ¦ β
β 2024_01_ARI_BU β 1.0 β 2.0 β 8.0 β β¦ β run β 2.0 β -0.530139 β (11:51) β
β F β β β β β β β β 6-J.Conner β
β β β β β β β β β left end toβ¦ β
β 2024_01_ARI_BU β 1.0 β 3.0 β 6.0 β β¦ β pass β 8.0 β 1.6808 β (11:08) β
β F β β β β β β β β (Shotgun) β
β β β β β β β β β 1-K.Murray pβ¦ β
ββββββββββββββββββ΄ββββββ΄βββββββ΄ββββββββββ΄ββββ΄ββββββββββββ΄βββββββββββββββ΄ββββββββββββ΄ββββββββββββββββ
ngs_release = nfl.load_nfl_nextgen_stats([SEASON], stat_type="passing")
(ngs_release
.filter(pl.col("week") == 0) # week 0 == season totals in this release
.select(["player_display_name", "team_abbr", "attempts", "pass_yards",
"completion_percentage_above_expectation", "passer_rating"])
.sort("passer_rating", descending=True)
.head(8))
shape: (8, 6)
βββββββββββββββββββββββ¬ββββββββββββ¬βββββββββββ¬βββββββββββββ¬βββββββββββββββββββββββββ¬ββββββββββββββββ
β player_display_name β team_abbr β attempts β pass_yards β completion_percentage_ β passer_rating β
β --- β --- β --- β --- β above_exβ¦ β --- β
β str β str β i32 β i32 β --- β f64 β
β β β β β f64 β β
βββββββββββββββββββββββͺββββββββββββͺβββββββββββͺβββββββββββββͺβββββββββββββββββββββββββͺββββββββββββββββ‘
β Lamar Jackson β BAL β 474 β 4172 β -0.194641 β 119.629044 β
β Jared Goff β DET β 539 β 4629 β 5.054879 β 111.769481 β
β Joe Burrow β CIN β 652 β 4918 β 4.521902 β 108.537832 β
β Baker Mayfield β TB β 570 β 4500 β 2.17107 β 106.761696 β
β Jalen Hurts β PHI β 361 β 2903 β 6.305457 β 103.687673 β
β Sam Darnold β MIN β 545 β 4319 β 2.799064 β 102.534404 β
β Justin Herbert β LAC β 504 β 3870 β 2.391567 β 101.703042 β
β Josh Allen β BUF β 483 β 3731 β 0.781139 β 101.384576 β
βββββββββββββββββββββββ΄ββββββββββββ΄βββββββββββ΄βββββββββββββ΄βββββββββββββββββββββββββ΄ββββββββββββββββ
π΅ Secondary path: ESPN (quick & no-auth)β
When you just want a fast scoreboard without minting a token, ESPN is right
there. espn_nfl_schedule
returns a tidy schedule frame; pass dates=YYYYMMDD for a single day. (There's
also a raw espn_nfl_scoreboard
if you want the unparsed JSON.)
espn_sched = safe("ESPN schedule", lambda: nfl.espn_nfl_schedule(dates=20240908))
cols = ["id", "away_display_name", "home_display_name", "away_score", "home_score", "status_type_description"]
(espn_sched.select([c for c in cols if c in espn_sched.columns]).head(8)
if espn_sched is not None else "ESPN schedule unavailable")
β
ESPN schedule
shape: (8, 6)
βββββββββββββ¬βββββββββββββββββββββ¬ββββββββββββββββββββ¬βββββββββββββ¬βββββββββββββ¬ββββββββββββββββββββ
β id β away_display_name β home_display_name β away_score β home_score β status_type_descr β
β --- β --- β --- β --- β --- β iption β
β str β str β str β str β str β --- β
β β β β β β str β
βββββββββββββͺβββββββββββββββββββββͺββββββββββββββββββββͺβββββββββββββͺβββββββββββββͺββββββββββββββββββββ‘
β 401671744 β Pittsburgh β Atlanta Falcons β 18 β 10 β Final β
β β Steelers β β β β β
β 401671617 β Arizona Cardinals β Buffalo Bills β 28 β 34 β Final β
β 401671719 β Tennessee Titans β Chicago Bears β 17 β 24 β Final β
β 401671628 β New England β Cincinnati β 16 β 10 β Final β
β β Patriots β Bengals β β β β
β 401671861 β Houston Texans β Indianapolis β 29 β 27 β Final β
β β β Colts β β β β
β 401671849 β Jacksonville β Miami Dolphins β 17 β 20 β Final β
β β Jaguars β β β β β
β 401671734 β Carolina Panthers β New Orleans β 10 β 47 β Final β
β β β Saints β β β β
β 401671712 β Minnesota Vikings β New York Giants β 28 β 6 β Final β
βββββββββββββ΄βββββββββββββββββββββ΄ββββββββββββββββββββ΄βββββββββββββ΄βββββββββββββ΄ββββββββββββββββββββ
π³ Cookbook: common NFL tasksβ
A full dozen recipes you'll reach for constantly β leaderboards, splits, team-level efficiency, snap-share workhorses, play-by-play slices, a schedule scan, and a quick hop into pandas. Each one leans on the premium native/NextGen feeds or the rock-solid nflverse release parquets, and every live call is wrapped so a network blip never breaks your run. Recipes 1β4 use the live NFL.com / NextGen endpoints; 5β12 build on the cached release parquets, so they run anywhere, anytime. π
Recipe 1 β This week's "Out" list πβ
Filter the official injury report down to players ruled Out β exactly what you'd check before setting a lineup.
rep = safe(
"injury report",
lambda: nfl.nfl_injuries(season=SEASON, season_type="REG", week=1),
)
if rep is not None and rep.height and "injury_status" in rep.columns:
out = (
rep.filter(pl.col("injury_status").str.to_lowercase() == "out")
.select([c for c in ["team_full_name", "person_display_name", "position", "injuries"]
if c in rep.columns])
.head(15)
)
else:
out = "injury report unavailable"
out
β
injury report
shape: (5, 4)
ββββββββββββββββββββ¬ββββββββββββββββββββββ¬βββββββββββ¬ββββββββββββββββββββββββββββββββββ
β team_full_name β person_display_name β position β injuries β
β --- β --- β --- β --- β
β str β str β str β str β
ββββββββββββββββββββͺββββββββββββββββββββββͺβββββββββββͺββββββββββββββββββββββββββββββββββ‘
β Atlanta Falcons β Antonio Hamilton β CB β ['Groin'] β
β Baltimore Ravens β Adisa Isaac β LB β ['Hamstring'] β
β Baltimore Ravens β Kyle Van Noy β LB β ['gameday concussion protocol β¦ β
β Buffalo Bills β Taron Johnson β CB β ['Forearm'] β
β Buffalo Bills β Javon Solomon β DE β ['Oblique'] β
ββββββββββββββββββββ΄ββββββββββββββββββββββ΄βββββββββββ΄ββββββββββββββββββββββββββββββββββ
Recipe 2 β CPOE leaderboard from NextGen Stats π―β
Who's beating expectation as a passer? Rank qualified QBs by completion percentage above expectation straight off the NextGen statboard.
board = safe(
"NGS passing board",
lambda: nfl.nfl_ngs_statboard(stat_type="passing", season=SEASON, season_type="REG"),
)
if board is not None and board.height and "completionPercentageAboveExpectation" in board.columns:
cpoe = (
board.filter(pl.col("attempts") >= 200)
.select(["playerName", "attempts", "completionPercentage",
"completionPercentageAboveExpectation", "passerRating"])
.sort("completionPercentageAboveExpectation", descending=True)
.head(10)
)
else:
cpoe = "NGS board unavailable"
cpoe
β
NGS passing board
shape: (10, 5)
ββββββββββββββββββ¬βββββββββββ¬βββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββ¬βββββββββββββββ
β playerName β attempts β completionPercentage β completionPercentageAboveExpec β passerRating β
β --- β --- β --- β β¦ β --- β
β str β i64 β f64 β --- β f64 β
β β β β f64 β β
ββββββββββββββββββͺβββββββββββͺβββββββββββββββββββββββͺβββββββββββββββββββββββββββββββββͺβββββββββββββββ‘
β Jalen Hurts β 361 β 68.698061 β 6.305457 β 103.687673 β
β Jared Goff β 539 β 72.356215 β 5.054879 β 111.769481 β
β Joe Burrow β 652 β 70.552147 β 4.521902 β 108.537832 β
β Geno Smith β 578 β 70.415225 β 3.854464 β 93.202134 β
β Kirk Cousins β 453 β 66.887417 β 3.442009 β 88.61755 β
β Derek Carr β 279 β 67.741935 β 3.222724 β 101.022999 β
β Drake Maye β 338 β 66.568047 β 2.986893 β 88.079389 β
β Brock Purdy β 455 β 65.934066 β 2.983077 β 96.076007 β
β Sam Darnold β 545 β 66.238532 β 2.799064 β 102.534404 β
β Justin Herbert β 504 β 65.873016 β 2.391567 β 101.703042 β
ββββββββββββββββββ΄βββββββββββ΄βββββββββββββββββββββββ΄βββββββββββββββββββββββββββββββββ΄βββββββββββββββ
Recipe 3 β Standings β division winners πβ
Take the premium standings and pull the team that tops each division. One group-by and you've got your playoff-seeding cheat sheet.
st = safe(
"standings",
lambda: nfl.nfl_standings(season=SEASON, season_type="REG", week=18),
)
if st is not None and st.height and {"division_rank", "team_full_name"}.issubset(st.columns):
div_col = next((c for c in ["team_division_full_name", "division_full_name", "division"] if c in st.columns), None)
keep = [c for c in [div_col, "team_full_name", "overall_wins", "overall_losses"] if c]
winners = (
st.filter(pl.col("division_rank") == 1)
.select(keep)
.sort(div_col) if div_col else st.filter(pl.col("division_rank") == 1).select(keep)
)
else:
winners = "standings unavailable"
winners
β
standings
shape: (8, 3)
ββββββββββββββββββββββββ¬βββββββββββββββ¬βββββββββββββββββ
β team_full_name β overall_wins β overall_losses β
β --- β --- β --- β
β str β i64 β i64 β
ββββββββββββββββββββββββͺβββββββββββββββͺβββββββββββββββββ‘
β Baltimore Ravens β 12 β 5 β
β Buffalo Bills β 13 β 4 β
β Detroit Lions β 15 β 2 β
β Houston Texans β 10 β 7 β
β Kansas City Chiefs β 15 β 2 β
β Los Angeles Rams β 10 β 7 β
β Philadelphia Eagles β 14 β 3 β
β Tampa Bay Buccaneers β 10 β 7 β
ββββββββββββββββββββββββ΄βββββββββββββββ΄βββββββββββββββββ
Recipe 4 β A game's NextGen passer splits π¬β
Grab an NGS gameId from the schedule, then pull
nfl_ngs_gamecenter_overview
to see each side's primary passer with tracking-derived splits.
sched = safe(
"NGS schedule",
lambda: nfl.nfl_ngs_league_schedule(season=SEASON, season_type="REG", week=1),
)
if sched is not None and sched.height and "gameId" in sched.columns:
gid = sched["gameId"][0]
ov = safe(f"NGS gamecenter {gid}",
lambda: nfl.nfl_ngs_gamecenter_overview(game_id=gid, group="passers"))
if ov is not None and ov.height:
out = ov.select([c for c in ["side", "teamAbbr", "playerName", "position",
"completions", "attempts", "passYards", "touchdowns"]
if c in ov.columns])
else:
out = "gamecenter unavailable"
else:
out = "NGS schedule unavailable"
out
β
NGS schedule
β
NGS gamecenter 2024090500
shape: (2, 8)
βββββββββββ¬βββββββββββ¬βββββββββββββββββ¬βββββββββββ¬ββββββββββββββ¬ββββ βββββββ¬ββββββββββββ¬βββββββββββββ
β side β teamAbbr β playerName β position β completions β attempts β passYards β touchdowns β
β --- β --- β --- β --- β --- β --- β --- β --- β
β str β str β str β str β i64 β i64 β i64 β i64 β
βββββββββββͺβββββββββββͺβββββββββββββββββͺβββββββββββͺββββββββββββββͺβββββββββββͺββββββββββββͺβββββββββββββ‘
β home β KC β Patrick β QB β 20 β 28 β 291 β 1 β
β β β Mahomes β β β β β β
β visitor β BAL β Lamar Jackson β QB β 26 β 41 β 273 β 1 β
βββββββββββ΄βββββββββββ΄βββββββββββββββββ΄βββββββββββ΄ββββββββββββββ΄ββββββββββ β΄ββββββββββββ΄βββββββββββββ
Recipe 5 β Season rushing leaders πβ
Roll the weekly box scores in load_nfl_player_stats up to season totals and crown the ground-game kings (β₯150 carries).
ps = nfl.load_nfl_player_stats()
rush_cols = {"season", "season_type", "carries", "rushing_yards"}
if rush_cols.issubset(ps.columns):
rush_lb = (
ps.filter((pl.col("season") == SEASON) & (pl.col("season_type") == "REG"))
.group_by(["player_display_name", "recent_team"])
.agg(
pl.col("carries").sum().alias("carries"),
pl.col("rushing_yards").sum().alias("rush_yds"),
pl.col("rushing_tds").sum().alias("rush_td"),
pl.col("rushing_epa").sum().round(1).alias("rush_epa"),
)
.filter(pl.col("carries") >= 150)
.sort("rush_yds", descending=True)
.head(10)
)
else:
rush_lb = "player_stats schema changed β rushing columns missing"
rush_lb
shape: (10, 6)
βββββββββββββββββββββββ¬ββββββββββββββ¬ββββββββββ¬βββββββββββ¬ββββββββββ¬βββββββ ββββ
β player_display_name β recent_team β carries β rush_yds β rush_td β rush_epa β
β --- β --- β --- β --- β --- β --- β
β str β str β i32 β f64 β i32 β f64 β
βββββββββββββββββββββββͺββββββββββββββͺββββββββββͺβββββββββββͺββββββββββͺβββββββββββ‘
β Saquon Barkley β PHI β 345 β 2005.0 β 13 β 34.1 β
β Derrick Henry β BAL β 325 β 1921.0 β 16 β 40.6 β
β Bijan Robinson β ATL β 304 β 1456.0 β 14 β 16.9 β
β Jonathan Taylor β IND β 303 β 1431.0 β 11 β -21.0 β
β Jahmyr Gibbs β DET β 250 β 1412.0 β 16 β 35.1 β
β Josh Jacobs β GB β 301 β 1329.0 β 15 β -18.3 β
β Kyren Williams β LA β 316 β 1299.0 β 14 β -23.5 β
β Chuba Hubbard β CAR β 250 β 1195.0 β 10 β 9.7 β
β Aaron Jones β MIN β 255 β 1138.0 β 5 β -13.4 β
β Bucky Irving β TB β 207 β 1122.0 β 8 β 20.9 β
βββββββββββββββββββββββ΄ββββββββββββββ΄ββββββββββ΄βββββββββββ΄ββββββββββ΄βββββββββββ
Recipe 6 β The most efficient offenses (EPA/play) πβ
Expected points added is the modeller's favourite efficiency yardstick. Average epa over every run/pass in load_nfl_pbp to rank offenses.
pbp = nfl.load_nfl_pbp([SEASON])
if {"epa", "posteam", "play_type"}.issubset(pbp.columns):
epa_off = (
pbp.filter(pl.col("play_type").is_in(["run", "pass"]))
.group_by("posteam")
.agg(
pl.col("epa").mean().round(3).alias("epa_per_play"),
pl.len().alias("plays"),
)
.filter(pl.col("posteam").is_not_null())
.sort("epa_per_play", descending=True)
.head(10)
)
else:
epa_off = "pbp schema changed β epa/posteam columns missing"
epa_off
shape: (10, 3)
βββββββββββ¬βββββββββββββββ¬ββββββββ
β posteam β epa_per_play β plays β
β --- β --- β --- β
β str β f64 β u32 β
βββββββββββͺβββββββββββββββͺββββββββ‘
β BAL β 0.219 β 1167 β
β BUF β 0.19 β 1202 β
β DET β 0.165 β 1164 β
β WAS β 0.132 β 1308 β
β TB β 0.129 β 1128 β
β PHI β 0.119 β 1341 β
β CIN β 0.09 β 1069 β
β GB β 0.071 β 1081 β
β SF β 0.069 β 1014 β
β ARI β 0.067 β 1031 β
βββββββββββ΄βββββββββββββββ΄ββββββββ
Recipe 7 β Third-down conversion kings πβ
Move-the-chains efficiency: keep only 3rd-down run/pass snaps and divide conversions by attempts per offense β a classic play-by-play split.
if {"down", "third_down_converted", "posteam"}.issubset(pbp.columns):
third = (
pbp.filter((pl.col("down") == 3) & (pl.col("play_type").is_in(["run", "pass"])))
.group_by("posteam")
.agg(
pl.col("third_down_converted").sum().alias("conversions"),
pl.len().alias("attempts"),
)
.filter(pl.col("posteam").is_not_null())
.with_columns((pl.col("conversions") / pl.col("attempts") * 100).round(1).alias("conv_pct"))
.sort("conv_pct", descending=True)
.head(10)
)
else:
third = "pbp schema changed β third-down columns missing"
third
shape: (10, 4)
βββββββββββ¬ββββββββββββββ¬βββββββββββ¬βββββββββββ
β posteam β conversions β attempts β conv_pct β
β --- β --- β --- β --- β
β str β f64 β u32 β f64 β
βββββββββββͺββββββββββββββͺβββββββββββͺβββββββββββ‘
β BAL β 109.0 β 214 β 50.9 β
β TB β 115.0 β 226 β 50.9 β
β KC β 123.0 β 255 β 48.2 β
β DET β 101.0 β 213 β 47.4 β
β CIN β 100.0 β 214 β 46.7 β
β BUF β 107.0 β 237 β 45.1 β
β WAS β 118.0 β 262 β 45.0 β
β ARI β 83.0 β 192 β 43.2 β
β SF β 84.0 β 196 β 42.9 β
β PHI β 114.0 β 278 β 41.0 β
βββββββββββ΄ββββββββββββββ΄βββββββββββ΄βββββββββββ
Recipe 8 β Red-zone touchdown efficiency π―β
Filter the play-by-play to snaps inside the opponent's 20 (yardline_100 β€ 20) and see which offenses actually punch it in instead of settling for three.
if {"yardline_100", "touchdown", "posteam"}.issubset(pbp.columns):
redzone = (
pbp.filter((pl.col("yardline_100") <= 20) & (pl.col("play_type").is_in(["run", "pass"])))
.group_by("posteam")
.agg(
pl.col("touchdown").sum().alias("rz_tds"),
pl.len().alias("rz_plays"),
)
.filter((pl.col("posteam").is_not_null()) & (pl.col("rz_plays") >= 80))
.with_columns((pl.col("rz_tds") / pl.col("rz_plays") * 100).round(1).alias("td_pct"))
.sort("td_pct", descending=True)
.head(10)
)
else:
redzone = "pbp schema changed β red-zone columns missing"
redzone
shape: (10, 4)
βββββββββββ¬βββββββββ¬βββββββββββ¬βββββββββ
β posteam β rz_tds β rz_plays β td_pct β
β --- β --- β --- β --- β
β str β f64 β u32 β f64 β
βββββββββββͺβββββββββͺβββββββββββͺβββββββββ‘
β BAL β 55.0 β 178 β 30.9 β
β TB β 47.0 β 175 β 26.9 β
β BUF β 55.0 β 232 β 23.7 β
β DEN β 36.0 β 157 β 22.9 β
β DET β 54.0 β 239 β 22.6 β
β GB β 43.0 β 195 β 22.1 β
β SEA β 27.0 β 125 β 21.6 β
β NO β 25.0 β 120 β 20.8 β
β NYJ β 31.0 β 150 β 20.7 β
β WAS β 52.0 β 255 β 20.4 β
βββββββββββ΄βββββββββ΄βββββββββββ΄ βββββββββ
Recipe 9 β Snap-share workhorse running backs π΄β
load_nfl_snap_counts carries offense_pct per game β average it to find the backs their teams simply would not take off the field.
snaps = nfl.load_nfl_snap_counts([SEASON])
if {"position", "offense_pct", "player"}.issubset(snaps.columns):
workhorses = (
snaps.filter(pl.col("position") == "RB")
.group_by(["player", "team"])
.agg(
(pl.col("offense_pct").mean() * 100).round(1).alias("avg_snap_pct"),
pl.len().alias("games"),
)
.filter(pl.col("games") >= 10)
.sort("avg_snap_pct", descending=True)
.head(10)
)
else:
workhorses = "snap_counts schema changed β offense_pct/position missing"
workhorses
shape: (10, 4)
βββββββββββββββββββ¬βββββββ¬βββββββββββββββ¬ββββββββ
β player β team β avg_snap_pct β games β
β --- β --- β --- β --- β
β str β str β f64 β u32 β
βββββββββββββββββββͺβββββββͺβββββββββββββββͺββββββββ‘
β Kyren Williams β LA β 87.2 β 18 β
β Jonathan Taylor β IND β 80.3 β 14 β
β Chuba Hubbard β CAR β 77.3 β 15 β
β Bijan Robinson β ATL β 75.4 β 17 β
β Saquon Barkley β PHI β 75.1 β 20 β
β Breece Hall β NYJ β 72.4 β 16 β
β Alvin Kamara β NO β 70.9 β 14 β
β Tony Pollard β TEN β 67.8 β 16 β
β D'Andre Swift β CHI β 66.8 β 17 β
β Aaron Jones β MIN β 63.7 β 18 β
βββββββββββββββββββ΄βββββββ΄βββββββββββββββ΄ββββββββ
Recipe 10 β Receiving leaders, then a hop into pandas πΌβ
Aggregate the receiving box lines, .to_pandas(), and add derived columns (yards-per-catch, catch rate) with familiar pandas syntax β the polarsβpandas handoff is one method call.
rec_cols = {"receptions", "receiving_yards", "targets", "season", "season_type"}
if rec_cols.issubset(ps.columns):
rec = (
ps.filter((pl.col("season") == SEASON) & (pl.col("season_type") == "REG"))
.group_by(["player_display_name", "recent_team"])
.agg(
pl.col("receptions").sum().alias("rec"),
pl.col("receiving_yards").sum().alias("rec_yds"),
pl.col("targets").sum().alias("tgt"),
)
.filter(pl.col("rec") >= 70)
)
pdf = rec.to_pandas() # <-- polars -> pandas in one call
pdf["yards_per_rec"] = (pdf["rec_yds"] / pdf["rec"]).round(1)
pdf["catch_rate"] = (pdf["rec"] / pdf["tgt"] * 100).round(1)
rec_out = pdf.sort_values("rec_yds", ascending=False).head(10)[
["player_display_name", "recent_team", "rec", "rec_yds", "yards_per_rec", "catch_rate"]
].reset_index(drop=True)
else:
rec_out = "player_stats schema changed β receiving columns missing"
rec_out
player_display_name recent_team rec rec_yds yards_per_rec catch_rate
0 Ja'Marr Chase CIN 127 1708.0 13.4 72.6
1 Justin Jefferson MIN 103 1533.0 14.9 66.9
2 Brian Thomas JAX 87 1282.0 14.7 65.4
3 Drake London ATL 100 1271.0 12.7 63.3
4 Amon-Ra St. Brown DET 115 1263.0 11.0 81.6
5 Jerry Jeudy CLE 90 1229.0 13.7 62.1
6 Malik Nabers NYG 109 1204.0 11.0 64.1
7 CeeDee Lamb DAL 101 1194.0 11.8 66.4
8 Brock Bowers LV 112 1194.0 10.7 73.2
9 Ladd McConkey LAC 82 1149.0 14.0 73.2
Recipe 11 β Who gets open? NextGen separation π°οΈβ
The receiving statboard exposes a tracking-only metric box scores can't: average separation at the catch point. Rank qualified targets (β₯80) to find the route-runners defenders can't shadow.
sepboard = safe(
"NGS receiving statboard",
lambda: nfl.nfl_ngs_statboard(stat_type="receiving", season=SEASON, season_type="REG"),
)
if sepboard is not None and sepboard.height and "avgSeparation" in sepboard.columns:
sep = (
sepboard.filter(pl.col("targets") >= 80)
.select([c for c in [
"player_displayName", "player_position", "avgSeparation",
"avgYACAboveExpectation", "catchPercentage", "yards",
] if c in sepboard.columns])
.sort("avgSeparation", descending=True)
.head(10)
)
else:
sep = "NGS receiving statboard unavailable"
sep
β
NGS receiving statboard
shape: (10, 6)
βββββββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββββ¬βββββββββββββββββββ¬ββββββββββββββββββ¬ββββββββ
β player_displayNam β player_position β avgSeparation β avgYACAboveExpec β catchPercentage β yards β
β e β --- β --- β tation β --- β --- β
β --- β str β f64 β --- β f64 β i64 β
β str β β β f64 β β β
βββββββββββββββββββββͺββββββββββββββββββͺββββββββββββββββͺβββββββββββββββββββͺββββββββββββββββββͺββββββββ‘
β Khalil Shakir β WR β 4.253744 β 1.420359 β 76.0 β 821 β
β Demario Douglas β WR β 4.010062 β 0.298947 β 75.862069 β 621 β
β Zay Flowers β WR β 3.9155 β 1.636763 β 63.793103 β 1059 β
β Xavier Worthy β WR β 3.773458 β 0.445979 β 60.204082 β 638 β
β Zach Ertz β TE β 3.631374 β -0.207435 β 72.527473 β 654 β
β George Kittle β TE β 3.582076 β 2.110873 β 82.978723 β 1106 β
β Sam LaPorta β TE β 3.529115 β 1.433347 β 72.289157 β 726 β
β Brock Bowers β TE β 3.515527 β 0.982977 β 73.202614 β 1194 β
β Trey McBride β TE β 3.511888 β 0.637703 β 75.510204 β 1146 β
β Jonnu Smith β TE β 3.49632 β 0.848143 β 79.279279 β 884 β
βββββββββββββββββββββ΄ββββββββββββββββββ΄ββββββββββββββββ΄βββββββββββββββββββ΄ββββββββββββββββββ΄ββββββββ
Recipe 12 β The nail-biters: closest games of the season π¬β
load_nfl_schedule carries the final result (home margin). Take its absolute value and sort ascending to surface the one-score thrillers β built-in betting lines ride along too.
sched = nfl.load_nfl_schedule([SEASON])
if {"result", "game_type", "home_team", "away_team"}.issubset(sched.columns):
scored = (
sched.filter((pl.col("game_type") == "REG") & pl.col("result").is_not_null())
.with_columns(pl.col("result").abs().alias("margin"))
)
want = [
"week", "away_team", "away_score", "home_team", "home_score",
"margin", "spread_line", "total_line",
]
nailbiters = (
scored.select([c for c in want if c in scored.columns])
.sort("margin")
.head(10)
)
else:
nailbiters = "schedule schema changed β result/team columns missing"
nailbiters
shape: (10, 8)
ββββββββ¬ββββββββββββ¬βββββββββββββ¬ββββββββββββ¬βββββββββββββ¬βββββββββ¬ββββββββββββββ¬βββββββββββββ
β week β away_team β away_score β home_team β home_score β margin β spread_line β total_line β
β --- β --- β --- β --- β --- β --- β --- β --- β
β i32 β str β i32 β str β i32 β i32 β f64 β f64 β
ββββββββͺββββββββββββͺββββ βββββββββͺββββββββββββͺβββββββββββββͺβββββββββͺββββββββββββββͺβββββββββββββ‘
β 2 β CIN β 25 β KC β 26 β 1 β 6.5 β 47.5 β
β 2 β ATL β 22 β PHI β 21 β 1 β 5.5 β 46.5 β
β 4 β DEN β 10 β NYJ β 9 β 1 β 7.5 β 39.5 β
β 5 β ARI β 24 β SF β 23 β 1 β 7.0 β 48.5 β
β 8 β ARI β 28 β MIA β 27 β 1 β 4.0 β 46.5 β
β 9 β NO β 22 β CAR β 23 β 1 β -7.0 β 43.5 β
β 10 β CIN β 34 β BAL β 35 β 1 β 6.0 β 53.0 β
β 10 β PIT β 28 β WAS β 27 β 1 β 1.5 β 45.0 β
β 11 β GB β 20 β CHI β 19 β 1 β -6.0 β 41.0 β
β 11 β IND β 28 β NYJ β 27 β 1 β 4.0 β 43.0 β
ββββββββ΄ββββββββββββ΄βββββββββββββ΄ββββββββββββ΄βββββββββββββ΄βββββββββ΄ββββββββββββββ΄βββββββββββββ
ποΈ Season helpersβ
Handy when you want "the current/most-recent season" instead of hard-coding a
year. get_current_nfl_season() / get_current_nfl_week() track the live
calendar; most_recent_nfl_season() gives the latest season with data.
{
"current_season": nfl.get_current_nfl_season(),
"current_week": nfl.get_current_nfl_week(),
"most_recent_season": nfl.most_recent_nfl_season(),
}
{'current_season': 2025, 'current_week': 22, 'most_recent_season': 2025}
π Where to nextβ
- Premium native API β the full
nfl_*endpoint set:docs/docs/nfl/reference/nfl_api.md - NextGen Stats & loaders β
nfl_ngs_*andload_nfl_*:docs/docs/nfl/reference/additional.mdanddocs/docs/nfl/reference/loaders.md - ESPN secondary path β every
espn_nfl_*wrapper:docs/docs/nfl/reference/site.md - Pass
return_as_pandas=Truefor a pandas frame, orreturn_parsed=False(native API) for raw JSON. - R user? The same data lives in nflfastR / nflreadr; Python parity is nflreadpy.
Now go build something great β may your EPA be ever positive! ππ