# ESPN Scraper (`mlg14/espn-scraper`) Actor

Collect public ESPN scores, schedules, game statistics, odds, standings, teams, rosters, news, and rankings across sports leagues.

- **URL**: https://apify.com/mlg14/espn-scraper.md
- **Developed by:** [MLG Data](https://apify.com/mlg14) (community)
- **Categories:** MCP servers, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 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 Scraper

Scrape ESPN scores, schedules, odds, standings, game summaries, team rosters, rankings, and news from public sports pages. Export ESPN data to JSON, CSV, or a spreadsheet with one record per game, team, player, article, or poll entry. This is an ESPN data API alternative for public information across several major sports and soccer leagues.

The actor uses structured public data endpoints. It does not need a login or a browser session. Scoreboard requests are split by date, so a date range works even though the underlying endpoint accepts one day per request. Every record identifies its type and league, making it possible to keep separate tables or join data by game, team, and player IDs.

### What data can you extract from ESPN?

The selected mode controls the dataset rows. Scoreboard mode produces games and scores. Game mode produces one detailed summary per requested event. Odds mode emits a game with a flattened published line. Standings, Teams, Roster, Schedule, News, and Rankings modes each emit their corresponding record type. Fields tied to a particular sport or game state may be absent or null. For example, a scheduled game has no final score and many completed games have no current betting line.

| Field | Description | Example |
|---|---|---|
| `type` | Record kind: game, gameSummary, oddsLine, standing, team, player, scheduleGame, article, or ranking | `game` |
| `league` | Requested league key | `college-football` |
| `leagueName` | Full league name | `NCAA - Football` |
| `gameId` | ESPN event ID | `401856704` |
| `date` | Game start time | `2026-09-26T16:00Z` |
| `name` | Event display name | `Texas Longhorns at Tennessee Volunteers` |
| `shortName` | Short event name | `TEX @ TENN` |
| `status` | State, detail, completion, period, and clock | `{"state":"in","period":2}` |
| `homeTeam` | Home team name | `Tennessee Volunteers` |
| `homeTeamId` | Home team ID | `2633` |
| `homeAbbr` | Home team abbreviation | `TENN` |
| `homeScore` | Home score | `3` |
| `homeLogo` | Home logo URL | `https://a.espncdn.com/...` |
| `homeRecord` | Home team record | `3-0` |
| `awayTeam` | Away team name | `Texas Longhorns` |
| `awayTeamId` | Away team ID | `251` |
| `awayAbbr` | Away team abbreviation | `TEX` |
| `awayScore` | Away score | `10` |
| `awayLogo` | Away logo URL | `https://a.espncdn.com/...` |
| `awayRecord` | Away team record | `3-0` |
| `odds` | Primary sportsbook odds or full summary lines | `{"spread":-7.0,...}` |
| `venue` | Venue name, location, and indoor flag | `{"name":"Neyland Stadium",...}` |
| `broadcasts` | Broadcast network names | `["TV network"]` |
| `leaders` | Published game leaders | `[...]` |
| `tickets` | Public ticket summary | `null` |
| `situation` | Live game situation | `{"down":2,...}` |
| `competitors` | Competitors and published statistics | `[...]` |
| `url` | ESPN page URL | `https://www.espn.com/...` |
| `scrapedAt` | UTC collection time | `2026-09-26T17:05:51Z` |
| `gameDetails` | Optional game summary attached to a scoreboard row | `{"type":"gameSummary",...}` |
| `provider` | Sportsbook name | `sportsbook.example.com` |
| `details` | Line summary | `home -7` |
| `spread` | Current home point spread | `-7.0` |
| `overUnder` | Current total points line | `50.5` |
| `homeMoneyLine` | Current home money line | `-345` |
| `awayMoneyLine` | Current away money line | `275` |
| `openSpread` | Opening home point spread | `-2.5` |
| `openOverUnder` | Opening total points line | `48.5` |
| `openHomeMoneyLine` | Opening home money line | `-142` |
| `openAwayMoneyLine` | Opening away money line | `120` |
| `spreadMovement` | Current spread minus opening spread | `-4.5` |
| `totalMovement` | Current total minus opening total | `2.0` |
| `homeSpreadPrice` | Current home spread price | `-115` |
| `awaySpreadPrice` | Current away spread price | `-105` |
| `overPrice` | Current over price | `-102` |
| `underPrice` | Current under price | `-118` |
| `betUrl` | Betting line link | `https://sportsbook.example.com/...` |
| `teamStats` | Team box scores and statistics | `[...]` |
| `playerStats` | Player box scores and statistics | `[...]` |
| `winProbability` | Published win probability feed | `[...]` |
| `seasonSeries` | Season head-to-head information | `[...]` |
| `injuries` | Published injuries | `[...]` |
| `officials` | Game officials | `[...]` |
| `attendance` | Game attendance | `18997` |
| `plays` | Optional play-by-play records | `[...]` |
| `season` | Season year | `2026` |
| `group` | Conference or division | `Eastern Conference` |
| `teamId` | Team ID | `13` |
| `team` | Team name | `Los Angeles Lakers` |
| `abbreviation` | Team abbreviation | `LAL` |
| `logo` | Team logo URL | `https://a.espncdn.com/...` |
| `stats` | Named standings statistics | `{"wins":"41",...}` |
| `wins` | Wins | `41` |
| `losses` | Losses | `29` |
| `rank` | Standing or poll rank | `1` |
| `playerId` | Player ID | `5113969` |
| `position` | Player position | `SG` |
| `jersey` | Jersey number | `7` |
| `age` | Player age | `21` |
| `height` | Height in inches | `77` |
| `weight` | Weight in pounds | `184` |
| `college` | College name where published | `null` |
| `salary` | Salary where published | `null` |
| `location` | Team location | `Los Angeles` |
| `slug` | Team URL slug | `los-angeles-lakers` |
| `color` | Team color | `552583` |
| `record` | Team record | `41-29` |
| `standingSummary` | Team standing summary | `Pacific Division` |
| `nextEvent` | Next scheduled event | `[...]` |
| `forTeamId` | Team whose schedule was requested | `13` |
| `forTeamResult` | W when that team won a completed game | `W` |
| `articleId` | Article ID | `50034054` |
| `headline` | Article headline | `Public sports headline` |
| `description` | Article summary | `Article summary` |
| `publishedAt` | Article publication time | `2026-09-26T12:00Z` |
| `updatedAt` | Article update time | `2026-09-26T13:00Z` |
| `categories` | Article topic tags | `[...]` |
| `poll` | Poll name | `AP Top 25` |
| `pollDate` | Poll date | `2026-09-20T07:00Z` |
| `week` | Poll week | `Week 4` |
| `previousRank` | Previous poll rank | `2` |
| `points` | Poll points | `1706` |
| `providers` | All available provider lines returned for this game | `[{"spread":-7.0,...}]` |

The game fields are deliberately stable across sports. A soccer event may contain individual competitors or extra status details in `competitors`, while a basketball game commonly has team scores and period information. The original nested arrays are kept when they carry useful sport-specific detail. `status`, `venue`, and `odds` are compact nested objects; they remain objects when exported as JSON and may be serialized as text in flat formats.

### How to scrape ESPN

1. Pick a mode. Start with Scoreboard if you want the games on a date, or Standings if you want a current league table.
2. Enter one or more supported league keys. For a single game, use `eventIds`. For a roster or team schedule, use `teamIds`. You can also paste supported page URLs into `startUrls`.
3. Set `dates` for Scoreboard or Odds. Use a single calendar day, a relative day, or a range up to 32 days inclusive. Set `maxResults` to cap the number of records charged and returned.
4. Start the run. When it finishes, download the dataset in JSON, CSV, or spreadsheet format. Repeat with a different mode if you need a different table.

A typical workflow collects a scoreboard first, reads its `gameId` values, and then requests Game mode for selected events. Another workflow fetches a team directory, reads `teamId`, and then requests rosters or schedules. The ID fields preserve these joins without comparing names, which can vary by league or season.

### Input

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `scoreboard` | Scoreboard, game, odds, standings, teams, roster, schedule, news, or rankings. |
| `leagues` | string array | `nba` in the form | League keys for league-wide modes. |
| `dates` | string | Today if blank | `YYYYMMDD`, `YYYY-MM-DD`, `today`, `yesterday`, `tomorrow`, or `YYYYMMDD-YYYYMMDD`. |
| `eventIds` | string array | Empty | Game IDs prefixed by league, such as `nfl/401872953`. |
| `teamIds` | string array | Empty | Team numeric IDs or abbreviations prefixed by league, such as `nba/13` or `nba/LAL`. |
| `startUrls` | string array | Empty | ESPN game, standings, scoreboard, or team URLs. |
| `enrichGameDetails` | boolean | `false` | Fetch and attach a summary for each scoreboard game. |
| `includePlayByPlay` | boolean | `false` | Include play records in Game mode or attached game details. |
| `enrichTeamDetails` | boolean | `false` | Fetch full team profiles instead of only the directory entries. |
| `season` | string | Current source season | Year for standings, schedules, or rankings. |
| `seasonType` | string | Source default | Schedule season type: 1 preseason, 2 regular season, 3 postseason. |
| `groups` | string | None | Source group ID for college scoreboard filtering. |
| `maxResults` | integer | `200` | Overall record cap. |
| `maxConcurrency` | integer | `5` | Maximum concurrent requests, capped at 10. |
| `proxyConfiguration` | object | Enabled | Proxy configuration for endpoint requests. |

```json
{
  "mode": "scoreboard",
  "leagues": ["college-football"],
  "dates": "20260926",
  "groups": "80",
  "maxResults": 65
}
```

Supported league keys include `nfl`, `college-football`, `ncaaf`, `ufl`, `nba`, `wnba`, `ncaam`, `ncaaw`, `mlb`, `nhl`, `epl`, `la-liga`, `serie-a`, `bundesliga`, `ligue-1`, `mls`, `ucl`, `uel`, `liga-mx`, `world-cup`, `nwsl`, `f1`, `ufc`, and `pga`. These are key mappings, not a guarantee that every mode has records for every league. Polls, for instance, are published in selected sports. Empty dates during an off-season normally produce no scoreboard rows.

### Output example

This trimmed item came from a live scoreboard run for 26 September 2026. The run returned 65 games with game ID, date, teams, and URL filled on every row. Live scores and the clock can change between runs.

```json
{
  "type": "game",
  "league": "college-football",
  "leagueName": "NCAA - Football",
  "gameId": "401856704",
  "date": "2026-09-26T16:00Z",
  "name": "Texas Longhorns at Tennessee Volunteers",
  "status": {"state": "in", "detail": "12:07 - 2nd Quarter", "completed": false, "period": 2, "clock": "12:07"},
  "homeTeam": "Tennessee Volunteers",
  "homeTeamId": "2633",
  "homeScore": 3,
  "awayTeam": "Texas Longhorns",
  "awayTeamId": "251",
  "awayScore": 10,
  "venue": {"name": "Neyland Stadium", "city": "Knoxville", "state": "TN", "id": "3853", "indoor": false},
  "odds": null,
  "url": "https://www.espn.com/college-football/game?gameId=401856704"
}
```

### Use cases

- A sports results archive can collect completed games by date and join details through `gameId`.
- A live display can refresh one league's scoreboard and show status, clock, teams, and score.
- A standings report can track wins, losses, and the source's full named statistics for each club.
- A roster workflow can combine player IDs, positions, measurements, and public team identifiers.
- A schedule calendar can use event dates and venue details, then mark completed results.
- A betting analysis table can compare a published current spread or total with its opening figure where both exist.

### How much does it cost to scrape ESPN?

The current event price is **$0.001 per dataset result**, or **$1 per 1,000 results**. A run with 100 output rows costs $0.10 in result charges; 1,000 rows cost $1; 5,000 rows cost $5. Set `maxResults` to keep the maximum number of result charges predictable. A run can also consume platform resources such as compute and proxy traffic, depending on the account and configuration. The current run price shown before starting a task is authoritative if pricing changes.

A scoreboard game, a standing row, and a player row each count as one result when written to the dataset. Fetching a game summary to attach to a scoreboard row adds a request but does not create an additional result by itself. Odds mode only emits games that have a published line, so a league can produce fewer paid results than its total number of scheduled games.

### Tips for best results

Use a date that falls in the league's season. `today` is convenient for recurring tasks, while an explicit date gives reproducible historical queries. When comparing live scores, save successive datasets with their `scrapedAt` value; a new run can contain changed scores. This actor does not maintain cross-run memory or output only changes.

For large historical windows, run several ranges of at most 32 days. The actor expands each range into daily scoreboard calls and deduplicates repeated game IDs within a run. `maxResults` stops output across all requested leagues and dates. Put the most important leagues first when the limit is smaller than the expected combined volume.

Use numeric team IDs when possible. Abbreviations are resolved through the league team directory, which adds a request. A full team profile also adds one request for each selected team. `enrichGameDetails` adds a summary request for each scoreboard game; use it only when the box score, injuries, or probability feed is needed. Play-by-play records can be large, so leave `includePlayByPlay` off for compact exports.

For college football, `groups` can narrow the scoreboard to a subdivision. The golden case used group `80` and produced 65 games for its date. Other group IDs may yield different records. If a league unexpectedly returns no games, check the season, calendar date, and group filter before increasing limits.

### Limits

The source's scoreboard accepts a single day per request. Its response did not honor a very high `limit` consistently: a request with `limit=1000` yielded 25 games for the golden date, while `limit=200` yielded 65. The actor uses 200 and splits date ranges into daily calls. Ranges longer than 32 days are rejected so a typo does not cause a large request burst.

Odds are context dependent. The scheduled NFL sample returned lines for 14 games; a live college football sample had no primary odds in its scoreboard response. The tested game summary supplied one provider line. `providers` therefore contains the available line or lines; it does not promise every sportsbook on the market. When the source omits a provider label but includes a betting link, `provider` contains the link host. Opening lines and movement remain null when their source values are absent.

Game summaries for future events can have empty player statistics and no final score. A standalone summary may also omit an exact ISO game date even though its scoreboard counterpart has one. Team rosters and article feeds depend on what the league publishes. Rankings are only meaningful where polls exist; a ranking team name may require a directory lookup. The actor does not scrape restricted articles or require a login. Only public metadata is included for news.

### Automated workflows

A client can request “Get tomorrow's NFL games with scores and published odds” by using Scoreboard mode, `nfl`, and `tomorrow`. Another can request “Get the current college football standings and a team roster” as two tasks, one for Standings and one for Roster. The resulting JSON has stable IDs and a `type` value, so the records can be routed into separate tables without inspecting every nested field.

### FAQ

**Is this an official ESPN service?** No. It collects public data and has no affiliation with the source. Use the data in line with the source's terms and applicable law, including rules on personal data and downstream redistribution.

**Do I need proxies or an account on the target site?** The observed public JSON endpoints worked without a target-site login or browser challenge. Proxy configuration is available if an endpoint blocks a particular run. A target account is not required for the supported public modes.

**How fast is a run?** A scoreboard request for a single day needs one source call per league. Detail enrichment makes one extra call per game, and a date range makes one scoreboard call per day and league. Actual duration also includes startup, network response time, and output writes.

**Can I schedule it or monitor changes?** You can run the same input on a schedule and compare `gameId`, scores, status, odds, and `scrapedAt` across datasets. The actor does not store a cross-run change ledger or suppress unchanged records.

**Can I export to a spreadsheet?** Yes. Download the dataset in JSON or CSV and open the CSV in a spreadsheet. Nested fields such as `odds` and `stats` are easiest to inspect in JSON.

**Why is a field empty?** The site may not publish it for that game state, sport, league, or season. A future game has no final score; an event without a betting market has no odds. Some roster fields, including college and salary, are not universal.

**Why are there fewer Odds rows than Scoreboard games?** Odds mode deliberately skips events without a line. Scoreboard mode keeps those games with `odds: null`, preserving the full schedule and scores.

### Integrations

Use the dataset endpoint for downstream pipelines or export the results after each run. Scheduled runs can feed webhooks, spreadsheet imports, reporting jobs, and other automation systems. The stable `league`, `gameId`, `teamId`, `playerId`, and `articleId` fields help keep updates aligned across recurring extracts.

### Support

Open an issue on the actor's Issues tab with the mode, league, date, and a sample missing field. That context makes it possible to reproduce a source change or add a useful field.

# Actor input Schema

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

Choose scores, game details, odds, standings, teams, rosters, schedules, news, or rankings.

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

League keys such as nfl, nba, mlb, nhl, college-football, epl, or ucl.

## `dates` (type: `string`):

One date in YYYYMMDD or YYYY-MM-DD format, today/yesterday/tomorrow, or a YYYYMMDD-YYYYMMDD range up to 32 days.

## `eventIds` (type: `array`):

Game mode: league/id values, such as nfl/401872953.

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

Teams, roster, or schedule mode: league/numeric ID values, such as nba/13.

## `startUrls` (type: `array`):

ESPN game, scoreboard, standings, or team URLs to route automatically.

## `enrichGameDetails` (type: `boolean`):

Fetch each scoreboard game summary and attach box scores, injuries, and probability when available.

## `includePlayByPlay` (type: `boolean`):

Include the large play-by-play array in game detail records.

## `enrichTeamDetails` (type: `boolean`):

Open each team profile in Teams mode to include its record and next event.

## `season` (type: `string`):

Optional season year for standings, schedules, and rankings.

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

Optional schedule season type: 1 preseason, 2 regular season, 3 postseason.

## `groups` (type: `string`):

Optional scoreboard group, such as 80 for top-division college football.

## `maxResults` (type: `integer`):

Stop after this many records across the run.

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

Maximum concurrent requests to public data endpoints.

## `proxyConfiguration` (type: `object`):

Proxy setting for fetching public data.

## Actor input object example

```json
{
  "mode": "scoreboard",
  "leagues": [
    "nba"
  ],
  "dates": "20260927",
  "enrichGameDetails": false,
  "includePlayByPlay": false,
  "enrichTeamDetails": false,
  "maxResults": 200,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All records in the default dataset.

# 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": [
        "nba"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/espn-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": ["nba"] }

# Run the Actor and wait for it to finish
run = client.actor("mlg14/espn-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": [
    "nba"
  ]
}' |
apify call mlg14/espn-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mlg14/espn-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/V71xH2FAriUkhpvbP/builds/SRzSbPbFArK0MMFEj/openapi.json
