← Back to blog

ESPN NBA Summary API: summary?event= Endpoint in Python

espn nba api python sports-data tutorial

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:

  1. Fetch the NBA scoreboard for a date.
  2. Read each row's id.
  3. 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 reading

Get ZenHodl Weekly

One weekly email with live results, one model insight, and product updates.

Tuesday mornings. No spam.

Want to build this yourself?

The ZenHodl course teaches you to build a complete prediction market bot in 6 notebooks.

Join the community

Discuss strategies, share results, get help.

Join Discord