Profile
Back to NewsBack
GitHub Trending 7 min
Reader Mode
sportsdataverse/sportsdataverse-py: Tidy sports data in Python: play-by-play, box scores, schedules, rosters and models across 100+ leagues (NFL, NBA, WNBA, MLB, NHL, college sports, soccer, international basketball and hockey). polars-first.

sportsdataverse/sportsdataverse-py: Tidy sports data in Python: play-by-play, box scores, schedules, rosters and models across 100+ leagues (NFL, NBA, WNBA, MLB, NHL, college sports, soccer, international basketball and hockey). polars-first.

7 hours ago

Table of Contents generated with DocToc

- Supported leagues and data sources - Polars / pandas parser layer - Data status - Installation - Standard install (pip) - Modern install (uv — recommended) - Development install - Notes - Errors - Examples and tutorials - Using with AI agents - Companion packages - Follow the SportsDataverse (@SportsDataverse) on X and star this repo - Our authors - Cheat sheet - Citations

sportsdataverse-py

sportsdataverse-py logo

!Lifecycle: beta PyPI</a>PyPI - Downloads !Contributors tests</a> coverage</a> coverage (all, incl. generated)</a>

sportsdataverse-py gives the community free, tidy, analysis-ready sports data in Python. It is the Python member of the SportsDataverse family and deliberately mirrors its R sisters — hoopR (NBA/MBB), wehoop (WNBA/WBB), cfbfastR (CFB), baseballr (MLB), and fastRhockey (NHL/PWHL) — so the function you know in R is the function you call in Python. The NFL module mirrors the nflverse's nflreadpy, and the package plays well with the wider PySport ecosystem. Beyond aggregation and tidying, the project also exists to make open-source expected-points and win-probability models reproducible and benchmarkable, especially for American football.

0.2.0 is in beta. This README and the docs describe 0.2.0, published
on PyPI as the pre-release 0.2.0b1. pip skips pre-releases unless you ask, so install it with
pip install --pre sportsdataverse. Release notes: CHANGELOG.

Supported leagues and data sources

One row per sport group; each links to that sport's page on the docs site, which lists every league and provider. The Getting Started table maps every module to its sources.

| Sport | Leagues | Modules | Sources | |---|---|---|---| | Football | CFB, NFL | sportsdataverse.cfb, .nfl | ESPN, stats.ncaa.org (cfb_ncaa_*), NFL.com API ("Shield"), nflverse loaders (nflreadpy parity), NFL Pro, PFF, Sleeper, On3 + 247Sports recruiting, Fox / Yahoo / CBS | | | UFL, XFL, CFL | sportsdataverse.football | ESPN | | Basketball | NBA, WNBA, NBA G League | sportsdataverse.nba, .wnba, .nbagl | ESPN, stats.nba.com (nba_stats_; nbagl_stats_, 94 G League wrappers), stats.wnba.com (wnba_stats_*), Basketball-Reference, RealGM, public model datasets, Fox Sports | | | MBB, WBB | sportsdataverse.mbb, .wbb | ESPN, stats.ncaa.org (ncaa_mbb_ / ncaa_wbb_, bigballR parity), KenPom, Bart Torvik, Her Hoop Stats, Fox Sports | | | NBA Summer League; NBL, FIBA, Olympics (ESPN) | sportsdataverse.basketball. (nbasl_, nbl, fiba, olympics_mbk / _wbk) | ESPN | | | EuroLeague and 24 international families (Genius Sports, Sportradar Atrium, NBL Australia, ACB, Lega Basket, B.LEAGUE, KBL, CBA, …) | sportsdataverse.basketball. | EuroLeague API and each league's own feed | | Hockey | NHL, PWHL | sportsdataverse.nhl, .pwhl | ESPN, NHL api-web, NHL EDGE, Stats REST, Records, Fox Sports; HockeyTech (PWHL) | | | 19 minor & junior leagues (AHL, ECHL, OHL, WHL, QMJHL, USHL, BCHL, …) | sportsdataverse.hockey. | HockeyTech | | | College hockey (M/W) | sportsdataverse.hockey.mch, .wch | ESPN | | | SIHF and 12 European leagues (DEL, ICEHL, EIHL, Metal Ligaen, ELH, Liiga, SHL, HockeyAllsvenskan, National League, Ligue Magnus, KHL, VHL) | sportsdataverse.hockey. (DEL is hockey.del_) | Each league's own feed | | Baseball | MLB; college baseball & softball | sportsdataverse.mlb, .baseball | ESPN, MLB Stats API, Baseball Savant / Statcast (mlb_statcast_*), stats.ncaa.org, Fox Sports | | Soccer | 12 leagues (EPL, LaLiga, Bundesliga, Serie A, Ligue 1, MLS, Liga MX, UCL, UEL, NWSL, WWC, WC) | sportsdataverse.soccer | ESPN, ASA, FotMob, UEFA, FIFA, MLS and NWSL APIs, Football-Data.co.uk, OpenLigaDB, kloppy open event data | | More sports & sources | Cricket | sportsdataverse.cricket | ESPN + bundled win-probability models | | | Formula 1 | sportsdataverse.f1 | Jolpica | | | Odds & prediction markets | sportsdataverse.odds | The Odds API, Kalshi, Polymarket | | | Cross-sport providers | sportsdataverse.providers. (cbs, fox, yahoo, espn_content, thesportsdb) | CBS Sports, Fox Sports, Yahoo Sports, ESPN content, TheSportsDB |

The big league modules export roughly 270–740 public names each (ESPN wrappers, that league's native-API wrappers, dataset loaders and parsers), and the flat sportsdataverse namespace holds about 9,300 public functions. Fox Sports adds fox__* Bifrost wrappers (pbp / boxscore / odds / roster / stats / standings / leaders) for 8 leagues plus the generated fox_api family (33 endpoints). Yahoo Sports adds 107 multi-sport yahoo_* functions from the generated yahoo_shangrila family and keeps the legacy yahoo_cfb_* season-stats and scoreboard wrappers for college football. CBS Sports adds 82 cbs_napi_* wrappers. sportsdataverse.release ports the sportsdataversedata R release utilities (GitHub-release asset publish / download helpers, including a pure-Python RDS writer).

Polars / pandas parser layer

Parser-backed wrappers return a tidy polars DataFrame by default. Pass return_parsed=False for the raw Dict, or return_as_pandas=True for pandas. Wrappers without a registered parser return the raw Dict.

from sportsdataverse.nba import espn_nba_team_roster

df = espn_nba_team_roster(team_id=13) # → polars (default) raw = espn_nba_team_roster(team_id=13, return_parsed=False) # → Dict pdf = espn_nba_team_roster(team_id=13, return_as_pandas=True) # → pandas

For the NHL and MLB sibling-API wrappers, compose the wrapper with its parser:

from sportsdataverse.nhl import nhl_web_pbp, parse_nhl_web_pbp
df = parse_nhl_web_pbp(nhl_web_pbp(2023030417))                 # 331-row polars frame

See py.sportsdataverse.org/docs/architecture/espn-cross-league and py.sportsdataverse.org/docs/parsers for the full architecture + parser registry.

Data status

The load_() functions read release assets on sportsdataverse-data; most load_nfl_() loaders read the nflverse-data releases instead. The badges below are rebuilt nightly from each producer's latest workflow run and newest release files; idle means the sport is out of season. Full detail: sportsdataverse.org/status.

| Dataset | Data updated | Through | Pipeline | Update workflows | |:--|:--|:--|:--|:--| | College football (ESPN) | cfbfastR-cfb-data data updated</a> | cfbfastR-cfb-data through season</a> | cfbfastR-cfb-data pipeline state</a> | cfbfastR-cfb-data daily_cfb</a> cfbfastR-cfb-data cfb_ratings_cron</a> cfbfastR-cfb-data cfb_fpi_weekly</a> cfbfastR-cfb-data cfb_recruiting_proj_cron</a> cfbfastR-cfb-data cfb_model_pipeline</a> cfbfastR-cfb-data espn_daily_snapshots</a> | | College football play-by-play (CollegeFootballData) | cfbfastR-data data updated</a> | cfbfastR-data through season</a> | cfbfastR-data pipeline state</a> | cfbfastR-data daily_cfb</a> | | College football (stats.ncaa.org) | ncaa-mfb-football-data data updated</a> | ncaa-mfb-football-data through season</a> | ncaa-mfb-football-data pipeline state</a> | ncaa-mfb-football-data daily_ncaa_mfb_data</a> | | NFL (ESPN) | nfl-data data updated</a> | nfl-data through season</a> | nfl-data pipeline state</a> | nfl-data espn_nfl_cron</a> nfl-data nfl_pbp_cron</a> nfl-data nfl_ratings_weekly</a> nfl-data nfl_rosters_players_cron</a> nfl-data nfl_model_pipeline</a> | | NFL Next Gen Stats | nfl-ngs-data data updated</a> | nfl-ngs-data through season</a> | nfl-ngs-data pipeline state</a> | nfl-ngs-data daily_ngs</a> | | Men's college basketball (ESPN) | hoopR-mbb-data data updated</a> | hoopR-mbb-data through season</a> | hoopR-mbb-data pipeline state</a> | hoopR-mbb-data daily_mbb</a> hoopR-mbb-data mbb_models_cron</a> | | Men's college basketball (stats.ncaa.org) | ncaa-mbb-hoops-data data updated</a> | ncaa-mbb-hoops-data through season</a> | ncaa-mbb-hoops-data pipeline state</a> | ncaa-mbb-hoops-data ncaa_mbb_models</a> | | NBA (ESPN) | hoopR-nba-data data updated</a> | hoopR-nba-data through season</a> | hoopR-nba-data pipeline state</a> | hoopR-nba-data daily_nba</a> | | NBA Stats API | hoopR-nba-stats-data data updated</a> | hoopR-nba-stats-data through season</a> | hoopR-nba-stats-data pipeline state</a> | hoopR-nba-stats-data daily_nba_stats</a> hoopR-nba-stats-data nba_models</a> hoopR-nba-stats-data annual_nba_stats_draft</a> | | Women's college basketball (ESPN) | wehoop-wbb-data data updated</a> | wehoop-wbb-data through season</a> | wehoop-wbb-data pipeline state</a> | wehoop-wbb-data daily_wbb</a> wehoop-wbb-data weekly_wbb</a> wehoop-wbb-data wbb_models_cron</a> | | Women's college basketball (stats.ncaa.org) | ncaa-wbb-hoops-data data updated</a> | ncaa-wbb-hoops-data through season</a> | ncaa-wbb-hoops-data pipeline state</a> | ncaa-wbb-hoops-data ncaa_wbb_models</a> | | WNBA (ESPN) | wehoop-wnba-data data updated</a> | wehoop-wnba-data through season</a> | wehoop-wnba-data pipeline state</a> | wehoop-wnba-data daily_wnba</a> wehoop-wnba-data weekly_wnba</a> wehoop-wnba-data annual_wnba_draft</a> | | WNBA Stats API | wehoop-wnba-stats-data data updated</a> | wehoop-wnba-stats-data through season</a> | wehoop-wnba-stats-data pipeline state</a> | wehoop-wnba-stats-data daily_wnba_stats</a> wehoop-wnba-stats-data wnba_models</a> wehoop-wnba-stats-data annual_wnba_stats_draft</a> | | NHL | fastRhockey-nhl-data data updated</a> | fastRhockey-nhl-data through season</a> | fastRhockey-nhl-data pipeline state</a> | fastRhockey-nhl-data daily_nhl_python</a> fastRhockey-nhl-data nhl_model_pipeline</a> | | PWHL | fastRhockey-pwhl-data data updated</a> | fastRhockey-pwhl-data through season</a> | fastRhockey-pwhl-data pipeline state</a> | fastRhockey-pwhl-data daily_pwhl_python</a> fastRhockey-pwhl-data pwhl_xg_cron</a> | | MLB and college baseball | baseballr-data data updated</a> | baseballr-data through season</a> | baseballr-data pipeline state</a> | baseballr-data mlb_models_cron</a> baseballr-data daily_ncaa_baseball</a> |

Installation

The package metadata lives entirely in pyproject.toml (PEP 621 [project] table). There is no setup.py. sportsdataverse needs Python 3.10+ (3.10–3.14 are supported).

Standard install (pip)

0.2.0 ships as the PyPI pre-release 0.2.0b1, so pass --pre; without it pip installs the previous stable release (0.1.4), which this README does not describe.

pip install --pre sportsdataverse

With optional extras (defined in [project.optional-dependencies] in pyproject.toml):

pip install --pre "sportsdataverse[all]"      # everything below EXCEPT mcp
pip install --pre "sportsdataverse[models]"   # no-op (kept so sportsdataverse[models] installs keep working)
pip install --pre "sportsdataverse[tests]"    # adds pytest, mypy, ruff, etc.
pip install --pre "sportsdataverse[nflpro]"   # NFL Pro (pro.nfl.com) Next Gen Stats
pip install --pre "sportsdataverse[pff]"      # Playwright, for the optional PFF Premium (LEGACY) headless login; the PFF Developer API needs no extra
pip install "sportsdataverse[mcp]>=0.2.0b1"  # the sdv-docs MCP server (the pin also upgrades a 0.1.4 install)
pip install --pre "sportsdataverse[soccer]"   # kloppy: soccer event / tracking data (soccer_open_events)
pip install --pre "sportsdataverse[sdvplot]"  # sdvplot: team logos, colors and chart themes
pip install --pre "sportsdataverse[sportypy]" # sportypy: draw pbp / shot coordinates on rulebook fields, rinks, courts (GPL-3.0)

Modern install (uv — recommended)

uv is the fast, drop-in package manager we use day to day. A version specifier that names a pre-release lets uv pick the beta:

# Add to a uv-managed project:
uv add "sportsdataverse>=0.2.0b1"

With extras:

uv add "sportsdataverse[all]>=0.2.0b1"

Or install the latest dev snapshot from GitHub:

uv add "sportsdataverse @ git+https://github.com/sportsdataverse/sportsdataverse-py"

Development install

For contributing or running the test suite:

git clone https://github.com/sportsdataverse/sportsdataverse-py.git
cd sportsdataverse-py

uv (recommended): every extra plus the dev dependency groups, editable

uv sync --all-extras --dev

Plain pip works too if uv isn't available (every extra except mcp, no dev groups):

pip install -e ".[all]"
Note: dev dependencies (test, lint, dev) live in a PEP 735 [dependency-groups] block
beside the PEP 621 [project.optional-dependencies] extras.
CI runs uv sync --all-extras --all-groups, which installs both in one step.

Run the test suite:

uv run pytest                       # offline tests only
SDV_PY_LIVE_TESTS=1 uv run pytest   # include live API tests (slower; hits ESPN / nflverse)

For deeper dev-environment detail (lint, mypy, dep-bumping workflow), see CONTRIBUTING.md.

Notes

  • DataFrame engine: polars 2.x (polars>=2.0,<3). Most loaders accept return_as_pandas=True
if you prefer pandas.
  • NFL caching: loaders cache to memory by default. Set
SDV_PY_NFL_CACHE=filesystem for cross-session reuse, or SDV_PY_NFL_CACHE=off to disable. See sportsdataverse.nfl.config.update_config() for runtime control.
  • stats.nba.com / stats.wnba.com surface (nba_stats_ / wnba_stats_ / nbagl_stats_*):
128 NBA (+ Summer League via league_id), 111 WNBA wrappers and 94 G League wrappers (sportsdataverse.nbagl.nbagl_stats, LeagueID=20 by default) are available: the endpoints a capture sweep confirmed live and not deprecated. The generic parser also handles the family's non-uniform shapes, such as the shot-location endpoints' grouped (2-level) headers and the scoreboardv3 game feed. Live calls to stats.nba.com require the curl_cffi package (TLS fingerprint protection); install it via pip install --pre "sportsdataverse[all]" or pip install curl_cffi separately.

Errors

Three outcomes, never collapsed into one:

  • NoDataError — the fetch SUCCEEDED and there is nothing there (a 404, or ESPN's
200-with-code:404 body). Skip the season.
  • AssetFetchError — the fetch FAILED and the answer is unknown (403, rate limit,
exhausted retries). Surface it; do not record it as an empty season.
  • ValueError — a 400 / 422: the request itself is wrong and retrying cannot help.
From 0.2.0 the hand-written ESPN scrapers and every generated flat-API getter raise instead of returning an error body or an empty dict.

Examples and tutorials

Every public function ships a runnable Example: block in its docstring showing a quick-start call, common parameter combinations, and a one-line pipeline next-step. Regenerate the API reference locally with uv run python tools/codegen/generate.py --docs (then cd docs && yarn build to preview the Docusaurus site) or browse the live docs at py.sportsdataverse.org.

For longer-form walkthroughs, see the intro/intermediate Jupyter notebooks under examples/notebooks/:

| Notebook | Covers | |---|---| | 01_quickstart.ipynb | Cross-sport intro — package layout, polars vs pandas, the download() retry layer | | 02_cfb_intro.ipynb | College football PBP, schedule, teams, espn_cfb_play_participants | | 03_nfl_intro.ipynb | NFL — nflreadpy parity surface, caching layer, current-season helpers | | 04_nba_intro.ipynb | NBA — PBP, schedule, teams, game rosters, shot distribution | | 05_wbb_intro.ipynb | Women's college basketball — PBP, schedule, multi-table player stats | | 06_mbb_intro.ipynb | Men's college basketball — PBP, schedule, conference standings | | 07_nhl_intro.ipynb | NHL — PBP, schedule, teams, shot-event filter | | 08_wnba_intro.ipynb | WNBA — PBP, schedule, rosters, player stats | | 09_mlb_intro.ipynb | MLB — Stats API + Statcast search / leaderboards / gamefeed | | 10_pwhl_intro.ipynb | PWHL — HockeyTech schedule, PBP, shifts, xG | | 11_junior_hockey_intro.ipynb | HockeyTech minor/junior leagues — one family shape across 19 leagues | | 12_odds_intro.ipynb | Odds & betting lines | | 13_soccer_intro.ipynb | ESPN soccer — league-parameterized wrappers | | 14_cricket_intro.ipynb | ESPN cricket + win-probability models | | 15_other_espn_leagues_intro.ipynb | UFL/XFL/CFL, college hockey, college baseball/softball ESPN families | | 16_international_basketball_intro.ipynb | EuroLeague, Genius Sports (SLB), NBL Australia, ACB; a EuroLeague shot chart on a FIBA court (sdvplot) | | 17_european_college_hockey_intro.ipynb | SHL, Liiga, DEL, KHL and NCAA hockey; a DEL shot map, college team colors (sdvplot) | | 18_prediction_markets_intro.ipynb | Kalshi and Polymarket market data: events, markets, order books | | 19_more_sources_intro.ipynb | NBA G League (ESPN), Formula 1, TheSportsDB, ESPN content |

Using with AI agents

  • Context7 indexes these docs (context7.json scopes it to docs/docs/) and the SDV R packages (from their pkgdown llms.txt).
  • llms.txt: links a Markdown copy of every docs page.
  • sdv-docs MCP server: exact answers about returned columns, Python and R functions, provider API endpoints (ESPN, stats.nba.com, NHL, MLB, …) and released datasets.
claude mcp add sdv-docs -- uvx --from 'sportsdataverse[mcp]>=0.2.0b1' sdv-docs

Needs 0.2.0b1 or newer (pip install "sportsdataverse[mcp]>=0.2.0b1"). The server ships in the same wheel but never imports sportsdataverse, so it starts in about 1.5 s instead of the 4-12 s a full league import costs.

The server downloads its index (sdv_docs_v1.sqlite.gz, about 20 MB) from the docs-index release, checking at most once a day, and sends no queries anywhere. Set SDV_DOCS_DB=/path/to/sdv_docs_v1.sqlite to use a local build (uv run python tools/codegen/build_docs_index.py). sdv-docs --version prints the installed version.

Companion packages

sportsdataverse-py is one corner of the broader SportsDataverse ecosystem. The R sister packages cover the same data sources with deeper sport-specific coverage:

For plots and simulation: sdvplot (team logos, wordmarks, headshots and colors for Python plots and tables) and its R and JavaScript counterparts sdvplotR and sdvplot-js (@sportsdataverse/sdvplot, @sportsdataverse/sporty, @sportsdataverse/sdvtables), sportypy (playing surfaces), and cfbseedR (college football season simulation and CFP seeding). The full directory is at sportsdataverse.org/packages.

The NFL submodule is a near drop-in replacement for nflreadpy; the broader nflverse ecosystem is the upstream data source for many of those loaders.

Follow the SportsDataverse (@SportsDataverse) on X and star this repo

X Follow</a>

GitHub stars</a>

Star history of sportsdataverse/sportsdataverse-py

Our authors

@saiemgilani @saiemgilani

Cheat sheet

A printable six-page reference, in four layouts (24 pages in all), for sportsdataverse (Python) — the loaders, the wrapper families, and what each one returns.

📄 Download the sportsdataverse (Python) cheat sheet (PDF)

Browse the other SportsDataverse cheat sheets at sportsdataverse.org/cheatsheets.

Citations

To cite the sportsdataverse-py Python package in publications, use:

BibTeX Citation

@misc{gilani_sdvpy_2021,
  author = {Gilani, Saiem},
  title = {sportsdataverse-py: The SportsDataverse's Python Package for Sports Data.},
  url = {https://py.sportsdataverse.org},
  year = {2021}
}
Chat with me