# Sports Data Scraper: 11 Sports, 25 Leagues, One Table (`deriverge/sports-data-scraper`) Actor

\[$3.00 / 1K] Games, live scores, league tables, teams, rosters, schedules and news for MLB, NBA, NHL, NFL, UFC, F1, golf, tennis, soccer, cricket and more, in one schema. Date ranges are split into days so a whole week comes back in one run. Changes only since your last run.

- **URL**: https://apify.com/deriverge/sports-data-scraper.md
- **Developed by:** [deriverge s.r.o.](https://apify.com/deriverge) (community)
- **Categories:** Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 row returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Sports Data Scraper

### What does Sports Data Scraper do?

**Sports Data Scraper** returns games, live scores, league tables, teams, rosters, schedules and news for **11 sports and 25 leagues** in one schema. Baseball, basketball, ice hockey, American football, soccer, tennis, golf, motorsport, MMA, cricket and lacrosse, all as the same table, so a query can be sorted by start time across sports without writing glue code for each one.

No browser, no proxies, no API key. The data comes from a public JSON interface, which keeps runs fast and cheap.

### Every sport, one table

Eleven sports have eleven vocabularies. Baseball counts innings, soccer counts halves, golf counts rounds, an MMA bout has no score at all. This actor normalises them:

| Sport | League keys | One row is |
|---|---|---|
| Baseball | `mlb` | a game |
| Basketball | `nba`, `wnba`, `ncaab`, `gleague` | a game |
| Ice hockey | `nhl` | a game |
| American football | `nfl`, `ncaaf` | a game |
| Soccer | `epl`, `laliga`, `bundesliga`, `seriea`, `ligue1`, `mls`, `ucl` | a game |
| Tennis | `atp`, `wta` | a match inside the tournament |
| Golf | `pga`, `lpga` | a player on the leaderboard |
| Motorsport | `f1`, `indycar` | a race |
| MMA | `ufc`, `pfl` | an event with its fighters |
| Cricket | `cricket-worldcup` | a match |
| Lacrosse | `nll` | a game |

A tennis tournament is not one row with a hundred matches hidden inside it, and a golf tournament is not one row with the whole field hidden inside it. That is the difference between a table you can query and a blob you have to unpack.

### Past the one-day limit

The source answers one day per request. Every other scraper in this category passes that limit on to you, so a week of fixtures means seven runs and seven result sets to merge.

Give this actor a `dateFrom` and a `dateTo` and it splits the range into day-sized queries, runs them all and merges the results, deduplicated by game. Measured on 21 September 2026 for Major League Baseball:

| Query | Rows returned |
|---|---|
| One request, one day | 15 |
| 13 to 14 September as a range | 25 |

Ranges longer than 120 days are cut at 120, so a typo in a date cannot run up a bill.

### Only what changed

Turn on `newOnly`, give the run a watch name or save it as a task, and schedule it. Every run compares its results with the previous snapshot and returns only the rows that are new or whose **status or score moved**. A live-score feed that bills for real changes rather than for re-reading the same finished games.

The `CHANGES` record lists what appeared, what disappeared and what moved. Comparison itself costs nothing.

### Input

```json
{
  "leagues": ["mlb", "nfl"],
  "mode": "scoreboard",
  "dateFrom": "2026-09-13",
  "dateTo": "2026-09-14",
  "statusFilter": "all",
  "includeGameDetail": false,
  "newOnly": true,
  "watchKey": "my-league",
  "maxItems": 2000
}
```

Modes: `scoreboard` for fixtures and results, `standings` for the league table, `teams` for the clubs, `roster` and `schedule` for a team or for every team in the league, `news` for the league feed.

### Output

```json
{
  "key": "espn:nfl:401872963",
  "type": "game",
  "sport": "americanfootball",
  "league": "nfl",
  "leagueName": "National Football League",
  "gameId": "401872963",
  "name": "Philadelphia Eagles at Chicago Bears",
  "startsAt": "2026-09-29T00:15:00.000Z",
  "status": "pre",
  "statusDetail": "Mon, September 28th at 8:15 PM EDT",
  "home": { "name": "Chicago Bears", "shortName": "CHI", "score": 0, "record": "1-1" },
  "away": { "name": "Philadelphia Eagles", "shortName": "PHI", "score": 0, "record": "2-0" },
  "venue": { "name": "Soldier Field", "city": "Chicago", "state": "IL", "country": "USA", "indoor": false },
  "broadcasts": ["ESPN", "ABC"],
  "odds": { "provider": "DraftKings", "details": "PHI -4.5", "overUnder": 43.5, "spread": 4.5 },
  "url": "https://www.espn.com/nfl/game/_/gameId/401872963/eagles-bears"
}
```

Betting lines come with the fixture when the source publishes them, which is normally for games that have not started. Fields a sport does not have are `null`, never a guessed value.

### What it does not collect

No contact details, no email addresses, no social handles, and nothing about private individuals. Athlete rows carry only what the league itself publishes about a professional in their professional role: name, team, shirt number, position, listed height and weight, and the public injury status.

### Pricing

| Event | Price |
|---|---|
| Row returned | $0.003, falling to $0.0015 on higher plans |
| Box score, injuries and last play, only when requested | $0.002 |
| Rows removed by the status filter, rows unchanged in change mode, days that returned nothing | **free** |

No start fee. A run that returns nothing costs nothing.

### Frequently asked questions

**How current is it?** Read live at run time. A game in progress comes back with its current score, period and clock.

**Can I get the full box score?** Turn on `includeGameDetail` and every game gains team statistics, the injury list, headlines and the last play. It costs one extra request per game and is billed as a separate event, so it stays off by default.

**Why does a Formula 1 race have no participants?** The source does not publish the field on the race listing, so the row is the race itself: name, circuit, date and status. Guessing a grid would be worse than leaving it out.

**How do I find a team identifier?** Run the `teams` mode once for the league. Every row has the identifier and the abbreviation, which are what the roster and schedule modes accept.

**Which leagues can I combine in one run?** Any of them. Pass several keys in `leagues` and the results come back in one table with the league on every row.

### How to use Sports Data Scraper

1. Open the actor and pick a league and a mode in the input form, or paste the JSON input from the example above.
2. Click **Start**. The first rows appear in the **Output** tab within seconds; the run summary is in the **Storage** tab under the key `SUMMARY`.
3. Download the results as JSON, CSV or Excel from the Output tab, or read them through the API link shown there.
4. To run it on a schedule, click **Save as a task**, set the input once and add a schedule. Scheduled tasks keep their own change snapshot, so the change mode works without any extra setup.

### Integrations

The actor is available in the Apify apps for **Make**, **Zapier**, **n8n** and **Keboola**, where you pick it by name and map the input fields. It is also exposed to AI agents through the Apify MCP server, and callable from any language through the Apify API; the API tab on this page has ready-made snippets for Node.js, Python and curl. Every run can post its results to a webhook when it finishes.

### Support

Questions and problems go into the **Issues** tab of this actor. Each issue is answered by the maintainer, and fixes ship as new builds without any change on your side.

Built and operated by deriverge s.r.o. Same rules as our other actors: unified schema, honest billing, no charge for what you did not get.

# Actor input Schema

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

Which leagues to read. Use the short key: mlb, nba, wnba, ncaab, gleague, nhl, nfl, ncaaf, pga, lpga, f1, indycar, ufc, pfl, atp, wta, epl, laliga, bundesliga, seriea, ligue1, mls, ucl, cricket-worldcup, nll. Leave empty for the default league of this actor.

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

Games and results is the live and finished fixture list. League table is one row per team with its record. Teams lists the clubs. Rosters and schedules read the teams given below, or every team in the league when none are given.

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

First day of the fixture range. ESPN answers one day per request, so the actor splits the range into days and merges the results. Leave both dates empty for today. You can also give a moving date instead of a fixed one: today, tomorrow, yesterday, or a day offset such as +7 or -3. A saved run or a schedule then keeps returning the current fixtures instead of going empty once the dates pass.

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

Last day of the fixture range, inclusive. Ranges longer than 120 days are cut at 120 so a typo cannot run up a bill. You can also give a moving date instead of a fixed one: today, tomorrow, yesterday, or a day offset such as +7 or -3. A saved run or a schedule then keeps returning the current fixtures instead of going empty once the dates pass.

## `statusFilter` (type: `string`):

Games removed by this filter are never charged.

## `teams` (type: `array`):

Team abbreviations or numeric identifiers for the roster and schedule modes, for example "nyy" or "6". Run the Teams mode once to get the list. Leave empty to read every team in the league.

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

Season for the schedule mode, for example 2026. Leave empty for the current season.

## `includeGameDetail` (type: `boolean`):

Adds team statistics, the injury list, headlines and the last play to every game. Costs one extra request per game and is charged as a separate event, so turn it on only when you need it.

## `newOnly` (type: `boolean`):

Keeps a snapshot per watch name (or per saved task) and returns only rows that are new or whose status or score moved. Schedule it every few minutes and you have a live feed that bills only for real changes.

## `watchKey` (type: `string`):

Name of the snapshot used by the change mode, for example "my-league". Runs from a saved task get a snapshot automatically even without a name.

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

Hard cap on returned rows across all leagues in the run.

## `oddsOnly` (type: `boolean`):

Drops games the source has no betting line for. Lines normally appear one to two days before a game. Dropped rows are never charged.

## Actor input object example

```json
{
  "leagues": [
    "mlb"
  ],
  "mode": "scoreboard",
  "statusFilter": "all",
  "includeGameDetail": false,
  "newOnly": false,
  "maxItems": 2000,
  "oddsOnly": false
}
```

# Actor output Schema

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

One row per game, team, athlete, standing or article, in one schema across every sport.

## `changes` (type: `string`):

Rows that appeared, disappeared or whose status or score moved compared with the previous snapshot of the same watch name or task.

## `summary` (type: `string`):

Per-league request counts, skipped leagues with reasons, and totals.

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

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

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

```

## MCP server setup

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