# MLB Stats Scraper — Players, Teams, Scores & Standings (`zapticx/mlb-stats-scraper`) Actor

Extract structured MLB player statistics, team rosters, game schedules, scores, standings, and game details. Eight extraction modes with flexible filters and clean JSON output.

- **URL**: https://apify.com/zapticx/mlb-stats-scraper.md
- **Developed by:** [Zapticx](https://apify.com/zapticx) (community)
- **Categories:** Developer tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 mlb records

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

## ⚾ MLB Stats Scraper — Players, Teams, Scores & Standings

Get Major League Baseball data as clean, structured records: player statistics, team rosters, game schedules and final scores, standings, and box-score game details. Choose one of eight modes, add a few filters, and export to JSON, CSV or Excel, or feed the results into your own tools through the Apify API.

No API key, no code and no browser automation are needed. A typical small run finishes in seconds.

### Pricing

You pay only for the records delivered to your dataset.

| Apify plan | Price per 1,000 records | Price per record |
|---|---:|---:|
| Free | $4.00 | $0.0040 |
| Bronze, Silver | $3.50 | $0.0035 |
| Gold and above | $3.00 | $0.0030 |

There is no start fee, and platform usage is included. You are never charged for failed requests, retries, duplicates, or records past your limit. Set **Maximum results** or Apify's maximum cost per run, and the run stops there.

The default run returns current standings: 30 records, about $0.12 on the Free plan. New to Apify? The [Free plan](https://console.apify.com/sign-up?fpr=1h3gvi) includes $5 of monthly credit to spend in the Store.

### What can you extract?

| Mode | You get one record per | Main fields |
|---|---|---|
| **Standings** (`standings`) | team | Division rank, wins, losses, winning percentage, games back, wild-card games back, home, away and last-ten records, streak, runs scored and allowed, clinch status |
| **Teams** (`teams`) | team and season | Team ID, name, abbreviation, league, division, venue, first year of play, active status |
| **Rosters** (`rosters`) | player on a roster | Player ID and name, jersey number, position, bats, throws, roster status |
| **Players** (`players`) | player | Name, primary position, current team, bats, throws, birth date and country, height, weight, MLB debut, active status |
| **Batting stats** (`batting_stats`) | stat line | G, PA, AB, R, H, 2B, 3B, HR, RBI, BB, SO, HBP, SB, CS, AVG, OBP, SLG, OPS, BABIP |
| **Pitching stats** (`pitching_stats`) | stat line | G, GS, W, L, SV, HLD, IP, H, R, ER, HR, BB, SO, ERA, WHIP, K/9, BB/9, opponents' AVG |
| **Schedules & results** (`schedules`) | game | Game ID, local and UTC dates, game type, status, teams, scores, winner, venue, doubleheader details, series, winning, losing and save pitchers, probable pitchers |
| **Game details** (`game_details`) | game | Line score by inning, runs, hits and errors, batting lineups, starting pitchers, team batting and pitching totals, decisions, attendance, duration |

### Key features

- **Search by name.** Use `NYY`, `Yankees`, `New York Yankees` or team ID `147`. Look up players as `Aaron Judge` or by ID. If a name matches more than one player, all matches are returned and the run summary lists them.
- **Numbers ready for analysis.** Rates such as `.331` arrive as the number `0.331`, so spreadsheets and models work straight away.
- **Correct innings pitched.** Baseball notation is kept and converted properly, so totals add up.
- **Traded players handled properly.** Each club's line and the season total are separate rows, so nothing is merged or counted twice.
- **Season, career or year-by-year stats,** for the regular season or postseason.
- **Efficient.** Whole teams and groups of players are fetched in single requests, so runs stay small and fast.
- **Clear run results.** Every run saves a `RUN_SUMMARY` listing what was delivered, skipped, not found or failed.

### How to use it

1. Open the Actor and choose what you want under **What to get**.
2. Add filters, such as seasons, teams, players or dates. Filters that don't apply to your mode are ignored, and the log says so.
3. Set **Maximum results**.
4. Click **Start**, then open the matching view in the Output tab or export your data.

### Input parameters

| Parameter | Type | Used by | Description |
|---|---|---|---|
| `mode` | string | all | `standings` (default), `teams`, `rosters`, `players`, `batting_stats`, `pitching_stats`, `schedules` or `game_details` |
| `seasons` | array | most modes | Season years, such as `["2025"]`. Up to 30 per run. Empty means the latest season. |
| `teams` | array | teams, rosters, stats, schedules, game details | Team ID, abbreviation or name. Empty means all teams. |
| `playerIds` | array | players, stats | MLB player IDs, such as `592450`. |
| `playerNames` | array | players, stats | Player names, such as `Aaron Judge`. |
| `statType` | string | stats | `season` (default), `career` or `yearByYear`. Career and year-by-year need players. |
| `statsGameType` | string | stats | `R` regular season (default) or `P` postseason. |
| `playerPool` | string | stats league tables | `qualified` (default) or `all`. |
| `rosterType` | string | rosters | `active` (default), `40Man` or `fullSeason`. |
| `startDate`, `endDate` | string | schedules, game details | Dates as `YYYY-MM-DD`. Up to 366 days, or 31 days for game details. |
| `gameIds` | array | game details | MLB game IDs (gamePk), such as `813024`. |
| `gameTypes` | array | schedules, game details | `R`, `F`, `D`, `L`, `W`, `S`, `A`, `E`. Empty means all games. |
| `gameStatus` | string | schedules | `all` (default), `completed` or `upcoming`. |
| `maxResults` | integer | all | Default 100, maximum 5,000. Game details maximum 250. |

#### How player and team filters work

In the stats modes, the filters you give decide the kind of result:

- **Players given:** each player's lines. A traded player gets one row per team plus a total row. If you give both players and teams, players take precedence.
- **Teams given, no players:** each player's line **for that team only**.
- **Neither given:** a league table of `qualified` or `all` players. A traded player appears once, as a season total with no team name.

Check `splitType` in each record: `team` is one club's line and `total` is a traded player's combined line. Add up only one kind, or you will double-count.

### Input examples

Latest standings:

```json
{ "mode": "standings" }
```

A team's pitching staff for one season:

```json
{ "mode": "pitching_stats", "seasons": ["2024"], "teams": ["NYY"], "maxResults": 100 }
```

Players' batting lines:

```json
{ "mode": "batting_stats", "seasons": ["2025"], "playerIds": ["592450", "660271"] }
```

A player's career totals:

```json
{ "mode": "batting_stats", "statType": "career", "playerIds": ["592450"] }
```

One team's games and scores for a week:

```json
{ "mode": "schedules", "teams": ["NYY"], "startDate": "2025-09-01", "endDate": "2025-09-07" }
```

Box-score details for specific games:

```json
{ "mode": "game_details", "gameIds": ["813024"] }
```

### Output examples

These are real records, shortened to their main fields. Every record also carries `recordType`, `dedupKey`, `source`, `sourceEndpoint` and `scrapedAt`.

**Batting stats**

```json
{
  "recordType": "batting_stats",
  "season": 2025,
  "statType": "season",
  "gameType": "R",
  "playerId": 592450,
  "playerName": "Aaron Judge",
  "splitType": "team",
  "teamId": 147,
  "teamName": "New York Yankees",
  "gamesPlayed": 152,
  "plateAppearances": 679,
  "atBats": 541,
  "runs": 137,
  "hits": 179,
  "homeRuns": 53,
  "rbi": 114,
  "avg": 0.331,
  "obp": 0.457,
  "slg": 0.688,
  "ops": 1.145
}
```

**Pitching stats**

```json
{
  "recordType": "pitching_stats",
  "season": 2024,
  "statType": "season",
  "playerName": "Michael Tonkin",
  "splitType": "team",
  "teamName": "New York Yankees",
  "gamesPlayed": 39,
  "wins": 3,
  "losses": 2,
  "era": 3.38,
  "inningsPitched": "56.0",
  "inningsPitchedOuts": 168,
  "inningsPitchedDecimal": 56.0,
  "strikeOuts": 57,
  "whip": 1.16,
  "saves": 2,
  "holds": 1
}
```

**Schedules & results**

```json
{
  "recordType": "game",
  "gamePk": 776489,
  "officialDate": "2025-09-02",
  "gameDateUtc": "2025-09-03T00:10:00Z",
  "gameTypeName": "Regular season",
  "statusDetailed": "Final",
  "awayTeamName": "New York Yankees",
  "awayScore": 7,
  "homeTeamName": "Houston Astros",
  "homeScore": 1,
  "venueName": "Daikin Park",
  "doubleHeader": "N",
  "winningPitcherName": "Max Fried",
  "losingPitcherName": "Framber Valdez",
  "savePitcherName": null
}
```

**Game details**

```json
{
  "recordType": "game_detail",
  "gamePk": 813024,
  "officialDate": "2025-11-01",
  "statusDetailed": "Final",
  "venueName": "Rogers Centre",
  "awayTeamName": "Los Angeles Dodgers",
  "awayRuns": 5,
  "awayHits": 11,
  "awayErrors": 0,
  "homeTeamName": "Toronto Blue Jays",
  "homeRuns": 4,
  "homeHits": 14,
  "homeErrors": 0,
  "inningsPlayed": 11,
  "awayStartingPitcherName": "Shohei Ohtani",
  "homeStartingPitcherName": "Max Scherzer",
  "winningPitcherName": "Yoshinobu Yamamoto",
  "lineScore": [{ "inning": 1, "awayRuns": 0, "homeRuns": 0 }],
  "awayLineup": [{ "battingOrder": 1, "playerId": 660271, "playerName": "Shohei Ohtani", "position": "DH" }],
  "awayPitching": { "inningsPitched": "11.0", "inningsPitchedOuts": 33, "earnedRuns": 4, "strikeOuts": 12 },
  "attendance": 44713,
  "gameDuration": "4:07"
}
```

### Historical data

Add earlier years to `seasons` for teams, rosters, standings, schedules and stats. Year-by-year stats go back through a player's whole career. The input accepts seasons back to 1876. Older seasons can have fewer fields, because the source recorded less, and such fields come back as `null`.

### How baseball statistics are formatted

- **Innings pitched** counts outs after the point, not tenths: `106.2` means 106⅔ innings. You get three fields:
  - `inningsPitched`: the published text, `"106.2"`
  - `inningsPitchedOuts`: outs recorded, `320`. Use this for adding up.
  - `inningsPitchedDecimal`: a true decimal, `106.667`
- **Rates** such as AVG, OBP, SLG, OPS, ERA and WHIP are numbers.
- **Missing values** are `null`, never `0`. A rate with no denominator, published as `.---` or `-.--`, is `null`.
- **Published values are kept.** The source prints `.000` for some 0-for-0 batting lines, and that stays `0`.
- **Games back:** `gamesBack` keeps the published text (`-` for the leader) and `gamesBackNum` gives a number (`0` for the leader). In `wildCardGamesBack`, `+9.5` means 9.5 games ahead of the cut line.
- **Dates:** `officialDate` is the local game date and `gameDateUtc` is the start time in UTC.
- **Jersey numbers** are text, so `00` stays `00`.

### Errors and limits

- **Invalid input** stops the run before any data is requested, with a message saying what to fix.
- **Temporary source errors** are retried a limited number of times, with pauses between attempts.
- **Partial failures:** if one team or batch fails, the run continues and lists the failure in `RUN_SUMMARY`. If everything fails, the run is marked as failed.
- **Access refusals** end the run. The Actor does not use proxies or try to get around restrictions.
- **No matches:** a valid search with no results succeeds with 0 records and explains why, and you are not charged.
- **Limits per run:** 5,000 records (250 for game details), 30 seasons, 366 days of dates (31 for game details by date), and 600 source requests.
- **Past rosters:** for past seasons the source returns the full-season roster, even if you ask for `active` or `40Man`. `rosterTypeReturned` shows what came back.
- **Postponed games** can appear on both the original and the new date.

### Use cases

- **Fantasy baseball:** track rosters, player lines and schedules.
- **Sports analytics:** build multi-season datasets for models and research.
- **Dashboards and reporting:** refresh standings and scores on a schedule.
- **Sports media and newsletters:** pull tables and game summaries without manual entry.
- **Data science projects:** get consistent, typed baseball data for study.

### API and automation

Schedule runs in Apify, or connect the Actor to Make, Zapier, n8n or your own code.

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("zapticx/mlb-stats-scraper").call(
    run_input={"mode": "standings", "seasons": ["2025"]}
)
for record in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(record["teamName"], record["wins"], record["losses"])
```

**JavaScript**

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('zapticx/mlb-stats-scraper').call({
    mode: 'schedules',
    teams: ['NYY'],
    startDate: '2025-09-01',
    endDate: '2025-09-07',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**cURL**

```bash
curl -X POST "https://api.apify.com/v2/acts/zapticx~mlb-stats-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode": "standings"}'
```

### FAQ

**Do I need an MLB account or API key?** No.

**Is this live play-by-play?** No. Scores and game data come from the source at the time of your run. Live play-by-play is not included, and fielding stats are not included in this version.

**How fresh is the data?** It follows the source, which can be cached for a few minutes. Don't rely on it for time-critical decisions.

**Why did my player search return two people?** Some players share a name. Both are included; use `playerIds` to pick one.

**Why does my team's stats run not show a traded player's season total?** Team results show that player's line for that team. Use `playerIds` to get the total.

**Why did I get 0 records?** Your filters may not match any games or players. For example, there are no regular-season games in December. Check the status message and `RUN_SUMMARY`.

**Is this an official MLB product?** No. See below.

### Data source, usage limits and disclaimer

Data comes from the MLB Stats API (statsapi.mlb.com) and is © MLB Advanced Media, L.P. This Actor is an independent tool. It is not affiliated with, endorsed by or sponsored by Major League Baseball, MLB Advanced Media or any team. Team and league names are used only to identify the data.

MLB Advanced Media's published notice governs use of its materials, including limits on commercial and bulk use. You are responsible for making sure that your use of the data complies with it and with applicable law. Zapticx does not guarantee the accuracy or completeness of the data.

### Support

Found a problem or need a feature? Open a ticket in the **Issues** tab of this Actor, and include your run ID and input.

### About Zapticx

Zapticx builds reliable data tools and automation. See more of our Actors on our [Apify Store profile](https://apify.com/zapticx) or visit [zapticx.com](https://www.zapticx.com/).

# Actor input Schema

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

<b>Teams</b>: all clubs of a season. <b>Rosters</b>: players on each team. <b>Players</b>: player profiles by ID or name. <b>Batting / Pitching stats</b>: stat lines by player, by team, or a league table. <b>Schedules</b>: games and final scores. <b>Standings</b>: division tables. <b>Game details</b>: box score, line score, lineups and starting pitchers.

## `seasons` (type: `array`):

One or more season years, e.g. 2025. Leave empty for the latest season. Up to 30 seasons; data goes back to 1876.

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

Team ID (147), abbreviation (NYY) or name (Yankees, New York Yankees). Leave empty for all teams. Used by Teams, Rosters, stats, Schedules and Game details.

## `playerIds` (type: `array`):

MLB player IDs, e.g. 592450 (Aaron Judge) or 660271 (Shohei Ohtani). Used by Players and the stats modes.

## `playerNames` (type: `array`):

Player names to look up, e.g. Aaron Judge. Every player matching a name is included; the run summary lists names that matched more than one player.

## `statType` (type: `string`):

Season lines, career totals, or one line per season (year by year). Career and year-by-year need Player IDs or names.

## `statsGameType` (type: `string`):

Which games the stat lines cover.

## `playerPool` (type: `string`):

When no players or teams are given, the stats modes return a league table. Qualified = players with enough plate appearances or innings to qualify; All = everyone.

## `rosterType` (type: `string`):

Active (26-man), 40-man, or everyone who played for the team that season. For past seasons the API returns the full-season roster; each record says which roster was returned.

## `startDate` (type: `string`):

First game date (YYYY-MM-DD) for Schedules and Game details. Overrides Seasons in Schedules mode.

## `endDate` (type: `string`):

Last game date (YYYY-MM-DD). Up to 366 days after the start date (31 days for Game details). Defaults to the start date.

## `gameIds` (type: `array`):

MLB game IDs (gamePk), e.g. 776440, for Game details. When given, the date range is ignored.

## `gameTypes` (type: `array`):

Limit Schedules and Game details to these game types. Leave empty for all games, including the postseason.

## `gameStatus` (type: `string`):

All games, only completed games, or only games that have not started.

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

Stop after this many records (max 5000; Game details max 250).

## Actor input object example

```json
{
  "mode": "standings",
  "statType": "season",
  "statsGameType": "R",
  "playerPool": "qualified",
  "rosterType": "active",
  "gameStatus": "all",
  "maxResults": 100
}
```

# Actor output Schema

## `records` (type: `string`):

All records of this run. Pick the view that matches the mode in the Output tab.

## `runSummary` (type: `string`):

Records written, duplicates skipped, failed and not-found items, notes, warnings and API request counts.

# 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 = {
    "mode": "standings"
};

// Run the Actor and wait for it to finish
const run = await client.actor("zapticx/mlb-stats-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 = { "mode": "standings" }

# Run the Actor and wait for it to finish
run = client.actor("zapticx/mlb-stats-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 '{
  "mode": "standings"
}' |
apify call zapticx/mlb-stats-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zapticx/mlb-stats-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/3g9AbZjLMYrp6ssSQ/builds/y76Y77bYH5tXTNgSW/openapi.json
