MLB StatsAPI Baseball Data Scraper avatar

MLB StatsAPI Baseball Data Scraper

Pricing

Pay per event

Go to Apify Store
MLB StatsAPI Baseball Data Scraper

MLB StatsAPI Baseball Data Scraper

Extract official MLB schedules, scores, teams, rosters, standings, players, statistics, leagues, divisions, and venues from StatsAPI.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Stas Persiianenko

Stas Persiianenko

Maintained by Community

Actor stats

0

Bookmarked

25

Total users

6

Monthly active users

15 days ago

Last modified

Categories

Share

Extract normalized baseball data from MLB's public StatsAPI without a browser, login, or API key.

Use one Actor to retrieve:

  • schedules, games, statuses, venues, and scores;
  • MLB teams and team rosters;
  • division and league standings;
  • players and player statistics;
  • leagues, divisions, and venues.

Every result includes a recordType discriminator, a stable MLB ID, the exact source request URL, a fetch timestamp, useful flattened fields, and the retained source record.

What does this MLB data scraper do?

The Actor sends bounded HTTPS requests to https://statsapi.mlb.com/api/v1 and converts the responses into integration-ready dataset items.

Choose one recordType per run so the default dataset has a predictable purpose.

The Actor supports Major League Baseball by default with sportId: 1. Other StatsAPI sport IDs can be requested where the selected endpoint supports them.

It does not scrape presentation pages, run a browser, or silently switch to a paid proxy.

Who is it for?

Fantasy and betting analysts

Refresh schedules, completed scores, active rosters, standings, and season statistics for research models.

Sports-data products

Feed dashboards and internal databases with stable MLB IDs and source request context.

Newsrooms and creators

Monitor daily games, statuses, venues, and score lines for editorial workflows.

Researchers

Collect consistent historical seasons and date ranges for reproducible analysis.

Baseball operations teams

Resolve teams, players, leagues, divisions, and venues into normalized records for enrichment jobs.

Why use this Actor?

  • Official structured source: data comes from MLB StatsAPI JSON routes.
  • No credentials: ordinary supported requests need no account or API key.
  • No browser or proxy cost: the implementation uses direct HTTP only.
  • Multiple baseball datasets: cover daily and historical workflows from one input contract.
  • Stable identifiers: keep gamePk, team, player, league, division, and venue IDs.
  • Useful normalization: common fields are flattened while raw preserves source detail.
  • Bounded operation: date ranges, result volume, concurrency, retries, and timeouts are limited.
  • Integration context: each item includes sourceUrl, recordType, and fetchedAt.

What MLB data can I extract?

recordTypeDataset rowsUseful fields
scheduleOne row per gamegamePk, date, status, home/away teams, scores, venue, inning
teamsOne row per teamTeam ID, name, abbreviation, league, division, venue
rosterOne row per roster playerTeam/player IDs, name, jersey, position, roster status
standingsOne row per team standingWins, losses, percentage, ranks, games back, streak
playersOne row per playerPlayer ID, name, birth date, age, position, current team
playerStatsOne row per returned stat splitPlayer, season/date, group, type, team, structured stats
leaguesOne row per leagueLeague ID, name, abbreviation, season, active state
divisionsOne row per divisionDivision ID, name, abbreviation, parent organization
venuesOne row per venueVenue ID, name, city, state, country

Source payload fields can vary by endpoint, season, game state, and MLB coverage. Inspect raw when you need a field that is not flattened.

Getting started

  1. Open the Actor input page.
  2. Select a recordType.
  3. Set the season or schedule date range.
  4. Add team, player, or league IDs when your workflow requires them.
  5. Keep maxItems small for the first run.
  6. Start the Actor.
  7. Open the default dataset or export it as JSON, CSV, Excel, or another Apify-supported format.

A working daily schedule input is:

{
"recordType": "schedule",
"season": 2025,
"startDate": "2025-07-04",
"endDate": "2025-07-04",
"gameTypes": ["R"],
"maxItems": 20
}

Input parameters

FieldTypeDefaultDescription
recordTypestringscheduleOne of the nine supported output workflows
seasonintegercurrent UTC yearSeason from 1876 through two years beyond the current year
startDateYYYY-MM-DDtoday for schedulesFirst schedule date
endDateYYYY-MM-DDstart dateLast schedule date; ranges are limited to 366 days
sportIdinteger1MLB StatsAPI sport ID; 1 is Major League Baseball
teamIdsstring arrayemptyRequired for rosters; filters schedules, teams, and standings
playerIdsstring arrayemptyRequired for player stats; enables targeted player lookups
leagueIdsstring array103, 104Standings leagues; defaults to American and National Leagues
statGroupsstring arrayhittingHitting, pitching, or fielding statistics
statTypesstring arrayseasonSeason, advanced, career, or year-by-year statistic scope
gameTypesstring arrayemptyOptional MLB codes such as R, S, or P
maxItemsinteger100Maximum deduplicated records, from 1 to 10,000
maxConcurrencyinteger5Concurrent roster/stat requests, from 1 to 10

IDs are entered as strings in the Apify list editor, for example "147". The Actor validates and converts them to positive numeric IDs.

Filtering behavior

Schedule requests apply season, dates, game types, sport, and optional team IDs.

Team IDs filter schedule rows when either the home or away team matches.

The same team IDs filter team and standings results.

Roster runs require at least one team ID and fetch each selected team's roster.

Player runs fetch a season-wide sport list unless playerIds is supplied.

Player-stat runs require player IDs and apply the selected season, groups, and stat types to every player.

Standings use leagues 103 and 104 unless leagueIds is supplied.

Output example

This shortened real schedule record was produced for July 4, 2025:

{
"recordType": "schedule",
"recordId": 777245,
"name": "Boston Red Sox at Washington Nationals",
"season": "2025",
"officialDate": "2025-07-04",
"status": "Final",
"homeTeamId": 120,
"homeTeamName": "Washington Nationals",
"homeScore": 2,
"awayTeamId": 111,
"awayTeamName": "Boston Red Sox",
"awayScore": 11,
"venueName": "Nationals Park",
"sourceUrl": "https://statsapi.mlb.com/api/v1/schedule?sportId=1&season=2025&startDate=2025-07-04&endDate=2025-07-04&hydrate=team%2Cvenue%2Clinescore",
"fetchedAt": "2026-07-26T00:00:00.000Z",
"raw": { "gamePk": 777245 }
}

raw is abbreviated above. Actual rows retain the complete endpoint record returned for that entity.

Output field notes

recordType tells downstream consumers which adapter produced the row.

recordId is the stable source identifier. Composite IDs are used where a row belongs to a team or stat scope.

name is a human-readable entity or matchup label.

season may be a number or string because StatsAPI route shapes differ.

Entity-specific flattened fields appear only where applicable.

sourceUrl records the exact public request, including filters.

fetchedAt is the UTC extraction timestamp.

raw retains source fidelity for advanced integrations.

How much does it cost to extract MLB baseball records?

The Actor uses pay per event with a $0.005 start fee plus one item event for each useful, deduplicated record saved.

Current per-record prices are tiered by Apify plan:

PlanPrice per MLB record
Free$0.000065743
Bronze$0.000057168
Silver$0.000044591
Gold$0.000034301
Platinum$0.000022867
Diamond$0.000016007

Including the start fee at Free-tier item pricing, 20 game rows cost about $0.0063, 100 records cost about $0.0116, and 1,000 records cost about $0.0707.

A Yankees roster returning 52 rows costs about $0.0084 on Free tier.

Runs that return no useful rows emit no item charge but still incur the one-time start fee. Apify may also account for platform usage according to your account terms.

Daily schedule workflow

Run once per game day with the same date in startDate and endDate.

Store results by recordId (gamePk) and update rows as games move from scheduled to live to final.

Use status, homeScore, awayScore, and currentInning to drive dashboards or notifications.

Do not assume an unfinished game's score is final.

Team and roster workflow

First run recordType: "teams" to discover current team IDs.

Then pass selected IDs to a roster run:

{
"recordType": "roster",
"season": 2025,
"teamIds": ["147"],
"maxItems": 60
}

Join roster records to teams with teamId and to other datasets with playerId.

Player statistics workflow

Use known player IDs for focused and inexpensive extraction:

{
"recordType": "playerStats",
"season": 2025,
"playerIds": ["592450"],
"statGroups": ["hitting"],
"statTypes": ["season"],
"maxItems": 10
}

The example uses Aaron Judge's MLB player ID.

Advanced, career, and year-by-year responses can return different split shapes. Use statGroup, statType, and raw when building long-term tables.

API usage with cURL

Replace YOUR_APIFY_TOKEN with an Apify API token:

curl -X POST \
"https://api.apify.com/v2/acts/automation-lab~mlb-statsapi-baseball-data-scraper/runs?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"recordType":"schedule","startDate":"2025-07-04","endDate":"2025-07-04","maxItems":20}'

Use the returned run's defaultDatasetId to fetch results after the run succeeds.

API usage with JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/mlb-statsapi-baseball-data-scraper').call({
recordType: 'roster',
season: 2025,
teamIds: ['147'],
maxItems: 60,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

API usage with Python

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/mlb-statsapi-baseball-data-scraper').call(run_input={
'recordType': 'standings',
'season': 2025,
'leagueIds': ['103', '104'],
'maxItems': 30,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)

Use with Apify MCP

Add the Actor to Claude Code:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=automation-lab/mlb-statsapi-baseball-data-scraper"

Claude Desktop, Cursor, and VS Code setup

Use the same HTTP MCP configuration in Claude Desktop, Cursor, or VS Code:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/mlb-statsapi-baseball-data-scraper"
}
}
}

Example prompts:

  • “Get the MLB schedule and scores for July 4, 2025.”
  • “Fetch the 2025 Yankees roster using team ID 147.”
  • “Return Aaron Judge's 2025 season hitting statistics.”
  • “Export 2025 American and National League standings as JSON.”

Integrations

Send datasets to Google Sheets for editorial planning.

Load JSON or CSV exports into BigQuery, Snowflake, PostgreSQL, or a data lake.

Trigger webhooks when a run finishes, then upsert records by recordType and recordId.

Use Make, Zapier, n8n, or custom code to schedule daily refreshes.

Treat source timestamps and statuses as facts at fetch time, not immutable history.

Limits and responsible API use

Date ranges are limited to 366 days.

A run saves at most 10,000 items.

Concurrency is capped at 10 and defaults to 5.

Requests time out after 30 seconds and retry transient timeout, HTTP 429, and server errors up to three attempts with backoff.

Deterministic 4xx responses and invalid inputs are not blindly retried.

There is no proxy or browser fallback.

MLB can change undocumented route behavior or fields. The Actor fails on invalid status/content type rather than returning misleading empty success.

Naturally empty filters succeed with zero rows and zero item events.

Use the Actor only for lawful purposes and comply with MLB terms, applicable database rights, privacy law, and your Apify agreement.

The Actor retrieves publicly accessible structured data and does not bypass login controls.

Baseball statistics, names, marks, and logos can carry separate rights. Public technical access does not grant permission for every redistribution, branding, betting, or commercial use.

Minimize request volume, cache stable reference data, and avoid needlessly refreshing historical records.

This Actor is an independent data-extraction tool and is not affiliated with or endorsed by MLB.

Troubleshooting

Why did my roster run fail?

roster requires at least one positive value in teamIds. Enter IDs as strings, such as "147".

Why did my player-stat run fail?

playerStats requires playerIds. Confirm the player exists and that the requested group/type is meaningful for that player and season.

Why did the run return zero records?

The filters may be valid but naturally empty. Check season, date, game type, team, league, and player IDs. Schedule team filters are applied after retrieving that date range.

Why are some flattened fields absent?

Different record types and game states expose different data. Inspect raw for the complete source record.

What happens during an MLB outage or rate limit?

The Actor retries bounded transient failures. If the source remains unavailable, the run fails non-zero so monitoring systems can retry later.

Can I request every historical season at once?

No. Run bounded seasons or date ranges separately. This keeps runs predictable and reduces load on the public service.

FAQ

Does this Actor require an MLB API key?

No. The supported StatsAPI routes are accessed anonymously.

Does it use Apify Proxy?

No. Requests go directly to the public JSON API.

Does it provide live scores?

Schedule rows reflect the status and scores available when fetched. Refresh during games for updated states; no continuous stream is promised.

Can I get Minor League data?

You may supply another valid sportId where StatsAPI supports the selected route. Coverage and fields can differ from Major League Baseball.

How are duplicates handled?

Rows are deduplicated within a run by recordType plus stable recordId before charging and saving.

Can I cap costs?

Yes. Set maxItems and use focused dates, team IDs, or player IDs. Charges are emitted only for saved records.

For a parallel live-sports workflow, see Cricbuzz Live Match Scores Scraper.

It covers cricket rather than baseball and can complement multi-sport score dashboards.

Support

When reporting an issue, include the run URL, redacted input, selected recordType, season/date filters, and the expected entity.

Do not include API tokens or private downstream credentials.

For schema changes, pin your downstream mapping to documented fields and retain raw as a compatibility fallback.