If you searched for ESPN's NBA summary URL, this is the endpoint:
https://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary?event={event_id}
It is an undocumented JSON endpoint that powers ESPN game pages. You pass an ESPN event_id, and the response returns the detailed game payload: header data, competitors, box score, leaders, plays, odds, and win probability fields when ESPN exposes them for that game.
Scoreboard vs Summary
Use the scoreboard endpoint to discover games:
https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard?dates=YYYYMMDD
Use the summary endpoint after you know the event ID:
https://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary?event=401585601
The flow is simple:
- Fetch the NBA scoreboard for a date.
- Read each row's
id. - Call
summary?event={id}for the full game detail.
Python Example
import requests
SCOREBOARD_URL = "https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard"
SUMMARY_URL = "https://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary"
def get_nba_event_ids(date_yyyymmdd: str) -> list[str]:
resp = requests.get(SCOREBOARD_URL, params={"dates": date_yyyymmdd}, timeout=15)
resp.raise_for_status()
data = resp.json()
return [event["id"] for event in data.get("events", [])]
def fetch_nba_summary(event_id: str) -> dict:
resp = requests.get(SUMMARY_URL, params={"event": event_id}, timeout=15)
resp.raise_for_status()
return resp.json()
for event_id in get_nba_event_ids("20261225"):
summary = fetch_nba_summary(event_id)
header = summary.get("header", {})
competition = (header.get("competitions") or [{}])[0]
teams = competition.get("competitors", [])
print(event_id, [team.get("team", {}).get("abbreviation") for team in teams])
Useful Fields
The response shape can vary by game status, but these are the fields to check first:
| Field | What it usually contains |
|---|---|
header |
Game metadata, competitors, status, venue, season, links |
boxscore |
Team and player box score tables |
leaders |
Team leaders for points, rebounds, assists, and related stats |
plays |
Play-by-play events with clock, period, score, and text |
winprobability |
ESPN win probability snapshots when available |
odds |
Available sportsbook line metadata when ESPN includes it |
Always code defensively. ESPN does not guarantee this API, and fields may be missing for future games, postponed games, or leagues with lighter coverage.
Extract Home and Away Teams Safely
Do not assume competitor order. Use homeAway:
def extract_teams(summary: dict) -> tuple[dict | None, dict | None]:
competition = (summary.get("header", {}).get("competitions") or [{}])[0]
home = away = None
for competitor in competition.get("competitors", []):
side = competitor.get("homeAway")
if side == "home":
home = competitor
elif side == "away":
away = competitor
return home, away
Common Gotchas
The event parameter is required. Calling /summary without ?event= usually returns an error or an empty response.
The scoreboard date format is YYYYMMDD. Use 20261225, not 2026-12-25.
Future games have fewer fields. Box score, plays, and win probability data appear only once ESPN has the underlying game feed.
The API is unofficial. Treat this as a practical endpoint, not a contract. Add timeouts, retries, schema checks, and alerts around parser failures.
Related Guides
- ESPN API Python tutorial - scoreboard endpoints across sports.
- NBA win probability model in Python - using this endpoint as model training input.
- Sports Odds API comparison - when to use ESPN, The Odds API, Polymarket, or Kalshi.