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.
- 532 flat-API wrappers across 15 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 7 cross-sport providers (The
Odds API, 247Sports, CBS Sports, Fox Sports, Yahoo Sports, HockeyTech/LeagueStat,
BartTorvik/T-Rank) 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
npm install sportsdataverseRequirements: Node ≥ 20.18.1. The package is ESM-only and ships TypeScript declarations.
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 worksEvery 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" });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.mlbSchedule({ 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_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);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.
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
7 cross-sport providers (Odds / 247 / CBS / Fox / Yahoo / HockeyTech /
BartTorvik) get standalone
sdv.<provider>.*namespaces and their own generated reference page.sdv.hockeytech.*(PWHL + AHL/OHL/WHL/QMJHL) is league-parameterized;sdv.torvik.*is men's college-basketball T-Rank analytics. Auth varies per family — bearer-token mint (NFL.com, automatic),apiKeyquery (Odds), publicapikey+api-version(Fox), caller-suppliedheaders/JWT (247, Yahoo), keyless (CBS, HockeyTech, BartTorvik). A family that needs non-JSON bodies or custom request shaping (HockeyTech's JSONP, BartTorvik's browser-UA CSV/JSON) supplies its own getter runtime viaGETTER_OVERRIDES. - 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.
The full reference is on the docs site: https://js.sportsdataverse.org/.
- Guides — getting-started recipes (quickstart + per-sport + providers) with live RunCell cells you can edit and run inline.
- Tutorials — guided walkthroughs.
- Reference — every wrapper, by league. The sidebar is grouped by sport (with a Providers group).
- Playground — run live ESPN + native-API calls in the browser.
- API — the full typed module surface (TypeDoc).
- Changelog — release notes.
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 |
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}
}MIT © Saiem Gilani, part of the SportsDataverse.
