sportsdataverse
v3.0.0
Published
Node.js client which retrieves sports data from the ESPN API as well as from the NCAA website, with support for NBA, NFL, NHL, MLB, WNBA, men's and women's college basketball, and college football.
Maintainers
Keywords
Readme
sportsdataverse
sportsdataverse is the SportsDataverse's Node.js client for sports data. As of
v3.0.0 it is a cross-league ESPN client plus a native (non-ESPN) live-API
client with a tidy parser layer:
- 116 ESPN endpoint wrappers generated for 29 leagues (31 namespaces) from a single YAML source of truth — play-by-play, box scores, schedules, rosters, standings, rankings, and more, identical on every league.
- 517 flat-API wrappers across 13 families — the 7 native league APIs (MLB
Stats, Baseball Savant / Statcast, NHL api-web/edge/stats-rest/records, NFL.com
Shield) merged onto their league namespace, and 5 cross-sport providers (The
Odds API, 247Sports, CBS Sports, Fox Sports, Yahoo Sports) on their own
sdv.<provider>.*namespaces. - A tidy parser layer — every wrapper returns raw JSON by default; pass
{ parsed: true }to get a tidy array of flat, snake_cased row objects. - Plus the original hand-written scrapers the package has always shipped
(
sdv.nba.getPlayByPlay(...)etc.), preserved unchanged.
It is the Node.js sister to the sportsdataverse-py
Python package and the SportsDataverse R packages
(hoopR, wehoop, cfbfastR, fastRhockey, …).
📖 Documentation · 🧭 Reference · 🛝 Playground · 🧩 API
Installation
npm install sportsdataverseRequirements: Node ≥ 20.18.1. The package is ESM-only and ships TypeScript declarations.
Usage
Every league is a namespace on the default export. The cross-league ESPN endpoints
follow one naming rule — espn<League><Endpoint> (camelCase). Every method also
has a snake_case alias (espn_nba_scoreboard) for parity with the Python / R packages:
import sdv from "sportsdataverse";
// Today's NBA scoreboard
const board = await sdv.nba.espnNbaScoreboard({});
// A single game summary (box score + plays + win probability + ...)
const game = await sdv.nba.espnNbaSummary({ event_id: 401584793 });
// A team's roster
const roster = await sdv.nfl.espnNflTeamRoster({ team_id: 12 });The same methods exist on every league, so switching sports is a one-token change:
await sdv.nfl.espnNflScoreboard({ week: 1, season_type: 2 });
await sdv.nhl.espnNhlScoreboard({});
await sdv.cfb.espnCfbRankings({}); // NCAA-scoped endpoint
await sdv.wnba.espnWnbaStandings({ season: 2024 });Multi-league sports (soccer, cricket) take an extra league slug:
await sdv.soccer.espnSoccerScoreboard({ league: "eng.1" }); // Premier League
await sdv.soccer.espnSoccerScoreboard({ league: "esp.1" }); // La LigaParameters accept snake_case or camelCase, and every pre-3.0 convenience method is preserved alongside the generated wrappers:
await sdv.nfl.espnNflTeamSchedule({ team_id: 12, season: 2024 });
await sdv.nfl.espnNflTeamSchedule({ teamId: 12, season: 2024 }); // identical
const pbp = await sdv.nba.getPlayByPlay(401584793); // legacy method, still worksTidy rows with { parsed: true }
Every wrapper returns the raw payload by default. Pass { parsed: true } to run
it through a registered parser and get a tidy array of flat, snake_cased row objects
(nested fields flattened) — the JS analog of sportsdataverse-py's return_parsed=True:
const raw = await sdv.nba.espnNbaScoreboard({}); // raw ESPN JSON
const rows = await sdv.nba.espnNbaScoreboard({ parsed: true }); // tidy row objects
// The summary endpoint is a dispatcher — omit `section` for all 21 sub-frames,
// or request one:
const box = await sdv.nba.espnNbaSummary({ event_id: 401584793, parsed: true, section: "boxscore_player" });Native APIs and cross-sport providers
The native league APIs are merged onto their league namespace, so they sit next to the ESPN methods. The provider families live on their own namespaces:
// Native — MLB Stats API + Baseball Savant / Statcast (on sdv.mlb)
await sdv.mlb.mlbApiSchedule({ sport_id: 1, date: "2024-07-04", parsed: true });
await sdv.mlb.mlbStatcastSearch({ season: 2024, player_type: "batter" });
// Native — NHL api-web + NFL.com Shield (token minted automatically, no creds)
await sdv.nhl.nhlApiWebPbp({ game_id: 2023030417, parsed: true });
await sdv.nfl.nflApiWeeklyGameDetails({ season: 2024, week: 1, parsed: true });
// Providers — standalone namespaces (auth varies per provider)
await sdv.odds.oddsApiSports({ api_key: process.env.ODDS_API_KEY, parsed: true });
await sdv.fox.fox_bifrost_scoreboard({ parsed: true }); // public apikey defaultedBrowser callers can import just the parser layer (no node-only HTTP deps) from the
sportsdataverse/parsers subpath export:
import { parseEndpoint } from "sportsdataverse/parsers";
const rows = parseEndpoint("espn", "scoreboard", rawPayload);Introspect the surface
import sdv, { LEAGUES, WRAPPERS } from "sportsdataverse";
LEAGUES.map((l) => l.prefix); // ['nba','wnba',...,'soccer','cricket','ufl',...] (29)
WRAPPERS.length; // generated ESPN wrapper definitions
Object.keys(sdv.nba).filter((k) => k.startsWith("espnNba")); // every NBA wrapperEndpoints are grouped into scopes — universal (every league), ncaa (college),
football (NFL/CFB/UFL), and mlb — so each league gets exactly the endpoints that
apply to it. See the per-league reference
for the full list, or try any call live in the
playground.
Architecture
The library is codegen-driven. tools/codegen/generate.mjs reads the vendored
endpoint YAML in tools/codegen/endpoints/*.yaml and, from that single source of
truth, generates:
- the runtime TypeScript wrapper / league tables under
src/generated/(wrappers.ts,leagues.ts), - the per-league Markdown reference under
docs/docs/reference/, and - the playground metadata
docs/src/playground/endpoints.json.
npm run codegen writes those outputs; npm run codegen:check is the drift gate
that fails CI if the committed output is stale. Generated files are never
hand-edited — you edit the YAML (or the templates) and regenerate.
- ESPN surface — one core, parameterized on
(sport, league)slugs, is wrapped once per URL family (Site v2 / Core v2 / Web v3) and exposed across 29 leagues asespn_<league>_<short>(snake) andespn<League><Short>(camelCase). The per-league extension modules are thin; endpoints carry a scope (universal,ncaa,football,mlb) so each league gets exactly the endpoints that apply. - Flat-API families — non-ESPN, absolute-host live APIs. The 7 native APIs
(MLB Stats, Statcast, NHL ×4, NFL.com) are merged onto their league namespace; the
5 cross-sport providers (Odds / 247 / CBS / Fox / Yahoo) get standalone
sdv.<provider>.*namespaces and their own generated reference page. Auth varies per family — bearer-token mint (NFL.com, automatic),apiKeyquery (Odds), publicapikey+api-version(Fox), caller-suppliedheaders/JWT (247, Yahoo), keyless (CBS). - OpenAPI → YAML transform —
tools/codegen/from-openapi.mjsturns a canonical OpenAPI 3.x spec (thesdv-swaggercollection) into an endpoint-YAML skeleton, which made the provider families largely mechanical to add. - Parser layer —
src/parsers/registers one parser per endpoint.{ parsed: true }runs the raw payload through it → a tidy array of flat, snake_cased row objects (nested fields flattened by the in-housenormalize). The browser-safesportsdataverse/parsersbarrel is esbuild-bundled into the playground so it parses client-side.
TypeScript + ESM-only, dual-case naming, Mocha no-network tests, and a Docusaurus 3 docs site on Vercel with a live playground.
npm run codegen # regenerate from the endpoint YAML
npm run codegen:check # drift gate (fails if the committed output is stale)
npm run bundle:parsers # rebuild the browser parser bundle for the playground
npm run build # compile TypeScript -> dist/
npm test # mocha suite (no network)See CONTRIBUTING.md for the full workflow and
CLAUDE.md for the architecture deep-dive.
Documentation
The full reference is on the docs site: https://js.sportsdataverse.org/.
- Tutorials — guided walkthroughs.
- Reference — every wrapper, by league.
- Playground — run live ESPN calls in the browser.
- API — the full typed module surface (TypeDoc).
- Changelog — release notes.
The SportsDataverse ecosystem
sportsdataverse-js is part of a family of open-source sports-data packages across
Node.js, Python, and R, all under the SportsDataverse
umbrella.
Node.js — js.sportsdataverse.org
sportsdataverse— this package.
Python — py.sportsdataverse.org
| Package | Domain |
|---|---|
| sportsdataverse-py | Cross-sport sister package (NBA/WNBA/NFL/MLB/NHL/MBB/WBB/CFB + odds) |
| collegebaseball | College baseball |
| sportypy | Matplotlib sport field/court/rink plotting |
| nwslpy | NWSL women's soccer |
| Package | Domain |
|---|---|
| hoopR | Men's basketball (NBA / MBB) |
| wehoop | Women's basketball (WNBA / WBB) |
| cfbfastR | College football |
| fastRhockey | Hockey (NHL / PWHL) |
| baseballr | Baseball (MLB / MiLB / college) |
| recruitR | Recruiting |
| oddsapiR | Betting odds (The Odds API) |
| softballR | Softball |
| cfb4th | College football 4th-down models |
| cfbplotR | College football ggplot2 helpers |
| sportyR | ggplot2 sport field/court/rink plotting |
| nflfastR / nflverse | NFL ecosystem |
Our Authors
Citation
To cite the sportsdataverse Node.js package in publications, use:
@misc{gilani_2021_sportsdataverse_js,
author = {Gilani, Saiem},
title = {sportsdataverse-js: The SportsDataverse's Node.js Package for Sports Data.},
url = {https://js.sportsdataverse.org},
year = {2021}
}License
MIT © Saiem Gilani, part of the SportsDataverse.
