# ESPN Sports Data Scraper — Scores, Standings, Rosters, News (`teodor_banea/espn-sports-data-scraper`) Actor

Live scores and results, team schedules, standings, teams, rosters, athlete season stats and news from ESPN for 40+ leagues (NBA, NFL, MLB, NHL, college, Premier League, La Liga, Champions League, UFC and more). Flat typed rows, no login

- **URL**: https://apify.com/teodor_banea/espn-sports-data-scraper.md
- **Developed by:** [Banea Teodor](https://apify.com/teodor_banea) (community)
- **Security:** Limited permissions
- **Stats:** 1 total users, 1 monthly users, 97.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## ESPN Sports Data Scraper — Scores, Standings, Rosters, News

One Actor for ESPN's sports data: **live scores and results, team schedules, standings,
teams, rosters, athlete season stats and news** for 40+ leagues — NBA, NFL, MLB, NHL, WNBA,
college football and basketball, MLS, Premier League, LaLiga, Bundesliga, Serie A, Ligue 1,
Champions League, Liga MX, UFC, F1 and more. Every row is flat and typed, so it drops
straight into a spreadsheet, a database or a model.

### What does ESPN Sports Data Scraper do?

Pick a mode and the leagues, and get one row per game, standings entry, team, player, stat
line or article. No ESPN account, no API key, no proxy — the Actor reads ESPN's public JSON
endpoints directly, which makes it fast and cheap enough to schedule every few minutes.

| Mode | One row per | Typical input |
|---|---|---|
| `scores` | game on a date (up to 62 days per run) | leagues + `dateFrom`/`dateTo` |
| `schedule` | game on a team's schedule | league + `teamIds` (+ `season`) |
| `standings` | team (or F1 driver) in the table | leagues (+ `season`, `standingsLevel`) |
| `teams` | team in the league | leagues |
| `rosters` | player on a roster | league + `teamIds` (or every team) |
| `athleteStats` | stat category × season for an athlete | league + `athleteIds` |
| `news` | article | leagues (or `teamIds`) |

### Why use this Actor?

- **Seven data types, 40+ leagues, one row shape per type.** Scores carry teams, scores,
  period scores, records, status, venue, broadcasts, top performers and odds. Standings carry
  wins, losses, points, streaks, home/away splits and every extra ESPN stat.
- **Odds included.** Pre-game spreads, totals and moneylines on scheduled games; closing lines,
  officials and venue details on finished games with `includeGameDetails`.
- **Reliable and cheap.** ESPN's API answers plain HTTP with no rate limiting observed;
  a 1,000-row scores run is ~70 requests.
- **Honest reporting.** The status message says exactly why a league came back short:
  no more games in the range, league not found, not supported by ESPN for the mode, news cap.
- **Stacks with our Sofascore actor.** Same `statusType` vocabulary, `startTime`,
  `homeScore`/`awayScore` and decimal `homeOdds`/`drawOdds`/`awayOdds`.

### How much does it cost?

**$0.50 per 1,000 rows.** No per-run fee, compute included.

| Run | Rows | Cost |
|---|---|---|
| Today's NBA scoreboard (default input) | ~10 | $0.005 |
| A full NBA regular season of results | ~1,230 | $0.62 |
| Premier League table | 20 | $0.01 |
| Every NFL roster (32 teams) | ~2,400 | $1.20 |

### Input

| Field | Type | Description |
|---|---|---|
| `mode` | string | `scores` (default), `schedule`, `standings`, `teams`, `rosters`, `athleteStats` or `news`. |
| `leagues` | array | League slugs from the list (default `["basketball/nba"]`). |
| `customLeagues` | array | Any other ESPN slug as `sport/league`, e.g. `soccer/ger.2`. |
| `dateFrom` / `dateTo` | string | Game days for `scores` (`YYYY-MM-DD`, up to 62 days). Defaults to today. ESPN game days are US/Eastern. |
| `includeGameDetails` | boolean | +1 request per game for closing odds, officials and venue details. Default `false`. |
| `season` | integer | ESPN season year (2026 = 2025-26 NBA). Defaults to the current season. |
| `seasonType` | string | `1` preseason, `2` regular season, `3` postseason. |
| `teamIds` | array | ESPN team ids for schedules, rosters and news (one league). Empty = every team. |
| `standingsLevel` | string | `default` (conferences), `league` (one table) or `division`. |
| `includeTeamDetails` | boolean | +1 request per team in `teams` mode (record, venue, next game). Default `true`. |
| `athleteIds` | array | ESPN athlete ids for `athleteStats` (one league). Find them with `rosters`. |
| `maxItems` | integer | Row cap, split evenly across leagues/teams/athletes. Default 100; `0` = unlimited (capped at 10,000). |
| `maxConcurrency` / `maxRequestsPerMinute` | integer | Default 5 / 120. |

Example input:

```json
{
    "mode": "scores",
    "leagues": ["basketball/nba", "soccer/eng.1"],
    "dateFrom": "2026-04-01",
    "dateTo": "2026-04-07",
    "includeGameDetails": true,
    "maxItems": 500
}
```

### Output

A game row (`recordType: "game"`):

```json
{
    "recordType": "game",
    "title": "Raptors 101 @ Celtics 115",
    "sport": "basketball",
    "league": "nba",
    "leagueName": "National Basketball Association",
    "url": "https://www.espn.com/nba/game/_/gameId/401810987/raptors-celtics",
    "scrapedAt": "2026-10-08T14:30:00.000Z",
    "runId": "abc123",
    "eventId": "401810987",
    "uid": "s:40~l:46~e:401810987",
    "name": "Toronto Raptors at Boston Celtics",
    "shortName": "TOR @ BOS",
    "seasonYear": 2026,
    "seasonType": 2,
    "seasonTypeName": "regular-season",
    "week": null,
    "startTime": "2026-04-05T19:30:00.000Z",
    "neutralSite": false,
    "conferenceGame": false,
    "groupName": null,
    "seriesSummary": null,
    "note": null,
    "headline": "Tatum and Brown carry Celtics to 115-101 win over Raptors",
    "source": "scoreboard",
    "statusType": "finished",
    "statusDescription": "Final",
    "statusState": "post",
    "completed": true,
    "period": 4,
    "displayClock": "0:00",
    "liveMinute": null,
    "winner": "home",
    "homeTeamId": "2",
    "homeTeamName": "Boston Celtics",
    "homeTeamShortName": "Celtics",
    "homeTeamAbbreviation": "BOS",
    "homeTeamLogo": "https://a.espncdn.com/i/teamlogos/nba/500/scoreboard/bos.png",
    "homeTeamColor": "008348",
    "homeScore": 115,
    "homeScoreDisplay": "115",
    "homePeriodScores": [26, 28, 26, 35],
    "homeRecord": "53-25",
    "homeRank": null,
    "homeForm": null,
    "homeTopPerformer": "Jaylen Brown — 26 Pts",
    "awayTeamId": "28",
    "awayTeamName": "Toronto Raptors",
    "awayTeamShortName": "Raptors",
    "awayTeamAbbreviation": "TOR",
    "awayTeamLogo": "https://a.espncdn.com/i/teamlogos/nba/500/scoreboard/tor.png",
    "awayTeamColor": "ce1141",
    "awayScore": 101,
    "awayScoreDisplay": "101",
    "awayPeriodScores": [20, 30, 25, 26],
    "awayRecord": "30-48",
    "awayRank": null,
    "awayForm": null,
    "awayTopPerformer": "Scottie Barnes — 22 Pts",
    "venueId": "1824",
    "venueName": "TD Garden",
    "venueCity": "Boston",
    "venueState": "MA",
    "venueCountry": null,
    "venueIndoor": true,
    "attendance": 19156,
    "broadcasts": ["NBC Sports BO", "Sportsnet", "NBA TV"],
    "oddsProvider": "DraftKings",
    "oddsDetails": "BOS -9.5",
    "homeSpread": -9.5,
    "overUnder": 221.5,
    "homeMoneyline": -425,
    "awayMoneyline": 330,
    "drawMoneyline": null,
    "homeOdds": 1.235,
    "drawOdds": null,
    "awayOdds": 4.3,
    "oddsSource": "summary",
    "officials": ["James Williams", "Che Flores", "Mark Lindsay"],
    "venueCapacity": null,
    "venueGrass": false,
    "boxscoreUrl": "https://www.espn.com/nba/boxscore/_/gameId/401810987"
}
```

Standings rows carry `rank`, `groupName`/`subgroupName`, `recordSummary`, `wins`, `losses`,
`ties`, `points`, `winPercent`, `gamesBehind`, `streakDisplay`, `homeRecord`, `awayRecord`,
`noteDescription` (e.g. "Champions League") and `extraStats` with every other ESPN stat.
Team rows carry ids, names, colors, logo, record, venue and next game. Roster rows carry
jersey, position, height/weight, age, birthplace, college, experience, injury status and
headshot. Athlete stat rows carry one `stats` object per category and season (labels in
`statsLabels`) plus a career-total row. News rows carry headline, description, byline,
published date, image and tags.

Every row has `recordType`, `title`, `sport`, `league`, `leagueName`, `url`, `scrapedAt`
and `runId`. ESPN ids are strings.

### Tips and tricks

- **Daily results backfill:** schedule `scores` with `dateFrom`/`dateTo` = yesterday for the
  leagues you follow; one row per game, `statusType: "finished"`.
- **ESPN game days are US/Eastern.** A European evening kick-off belongs to the US date;
  games are de-duplicated by `eventId`, so overlapping ranges never double-count.
- **Find ids:** run `teams` for team ids and `rosters` for athlete ids.
- **Custom leagues:** any ESPN slug works in `customLeagues` (`soccer/tur.1`, `soccer/sco.1`,
  `basketball/nbl`). Unknown slugs are reported in `ERRORS`, not silently skipped.
- **College:** `basketball/mens-college-basketball` and `football/college-football` return
  the full Division I / FBS slate (the Actor adds ESPN's `groups` parameter for you).
- **Tennis, golf and F1** have no two-team games; use `standings` (F1 drivers/constructors) or
  `news` for them.
- **News is capped at 50 articles** per league or team request by ESPN.
- **Athlete stats** exist for nba, wnba, nfl, nhl and mlb; soccer athletes return current-season
  splits from ESPN's overview endpoint; college athletes have none.
- **Stacking with Sofascore:** ESPN says `soccer`/`football`/`hockey` where Sofascore says
  `football`/`american-football`/`ice-hockey`.

### Integrations

Export the dataset as JSON, CSV or Excel from the Apify Console, or pull it through the API:

```
https://api.apify.com/v2/datasets/<datasetId>/items?format=csv
```

Connect the Actor to Google Sheets, Zapier, Make, Slack or a webhook with Apify integrations,
or call it from your own code with the Apify API client (JavaScript/Python) and schedule it
to run every few minutes during game time.

# Changelog

This Actor's version history is a separate document: https://apify.com/teodor_banea/espn-sports-data-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Select the data type. Each row in the dataset is one game, standings entry, team, roster player, athlete stat line or article.

## `leagues` (type: `array`):

Select one or more leagues. Use customLeagues for any other ESPN league slug.

## `customLeagues` (type: `array`):

Any other ESPN league as sport/league, e.g. soccer/ger.2, soccer/tur.1, basketball/nbl. Find the slug in the URL of ESPN's league pages.

## `dateFrom` (type: `string`):

First game day to fetch (YYYY-MM-DD). Defaults to today. ESPN game days are US/Eastern.

## `dateTo` (type: `string`):

Last game day to fetch (YYYY-MM-DD, inclusive). Defaults to dateFrom.

## `includeGameDetails` (type: `boolean`):

One extra request per game: closing odds for finished games, officials and venue details. The price is per row and does not change; the extra requests run in parallel inside each scoreboard page.

## `season` (type: `integer`):

ESPN season year for schedules, standings and athlete stats. For seasons spanning two years use the ending year (2026 = 2025-26 NBA). Defaults to the current season.

## `seasonType` (type: `string`):

Select the part of the season for schedules and athlete stats.

## `teamIds` (type: `array`):

ESPN team ids (e.g. 13 for the Lakers) for schedules, rosters and news. Leave empty for every team of the league. Use the teams mode to list ids. One league only.

## `standingsLevel` (type: `string`):

Select how standings are grouped.

## `includeTeamDetails` (type: `boolean`):

In teams mode, one extra request per team for record, venue, standing summary and next game (~30 requests for a pro league).

## `athleteIds` (type: `array`):

ESPN athlete ids for the athleteStats mode (e.g. 3975 for Stephen Curry). Use the rosters mode to find ids. One league only.

## `maxItems` (type: `integer`):

Stop after this many rows in total (split evenly across leagues, teams or athletes). 0 = unlimited (capped at 10,000).

## `maxConcurrency` (type: `integer`):

Parallel requests to ESPN.

## `maxRequestsPerMinute` (type: `integer`):

Rate limit for the queued requests (scoreboards, standings, lists, rosters, schedules, news). Detail requests (game and team details) run in parallel at the concurrency above instead.

## Actor input object example

```json
{
  "mode": "scores",
  "leagues": [
    "basketball/nba",
    "football/nfl"
  ],
  "customLeagues": [
    "soccer/ger.2"
  ],
  "includeGameDetails": false,
  "teamIds": [
    "13"
  ],
  "standingsLevel": "default",
  "includeTeamDetails": true,
  "athleteIds": [
    "3975"
  ],
  "maxItems": 50,
  "maxConcurrency": 5,
  "maxRequestsPerMinute": 120
}
```

# Actor output Schema

## `rows` (type: `string`):

Game rows (teams, scores, status, venue, broadcasts, odds), standings rows, team rows, roster players, athlete stat rows or news articles, depending on the mode.

## `rowsCsv` (type: `string`):

The same rows as a CSV download for spreadsheets.

## `errors` (type: `string`):

Leagues, teams, athletes or days that could not be fetched (target, URL, HTTP status, error, timestamp). Only present when something failed; the run's status message reports the shortfall per target.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "leagues": [
        "basketball/nba",
        "football/nfl"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("teodor_banea/espn-sports-data-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "leagues": [
        "basketball/nba",
        "football/nfl",
    ],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("teodor_banea/espn-sports-data-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "leagues": [
    "basketball/nba",
    "football/nfl"
  ],
  "maxItems": 50
}' |
apify call teodor_banea/espn-sports-data-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,teodor_banea/espn-sports-data-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/7DQ7PHnwhVGDbskD8/builds/PddUDv6gmmeo11YmL/openapi.json
