MLB StatsAPI Baseball Data Scraper
Pricing
Pay per event
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
Maintained by CommunityActor 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
rawpreserves source detail. - Bounded operation: date ranges, result volume, concurrency, retries, and timeouts are limited.
- Integration context: each item includes
sourceUrl,recordType, andfetchedAt.
What MLB data can I extract?
recordType | Dataset rows | Useful fields |
|---|---|---|
schedule | One row per game | gamePk, date, status, home/away teams, scores, venue, inning |
teams | One row per team | Team ID, name, abbreviation, league, division, venue |
roster | One row per roster player | Team/player IDs, name, jersey, position, roster status |
standings | One row per team standing | Wins, losses, percentage, ranks, games back, streak |
players | One row per player | Player ID, name, birth date, age, position, current team |
playerStats | One row per returned stat split | Player, season/date, group, type, team, structured stats |
leagues | One row per league | League ID, name, abbreviation, season, active state |
divisions | One row per division | Division ID, name, abbreviation, parent organization |
venues | One row per venue | Venue 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
- Open the Actor input page.
- Select a
recordType. - Set the season or schedule date range.
- Add team, player, or league IDs when your workflow requires them.
- Keep
maxItemssmall for the first run. - Start the Actor.
- 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
| Field | Type | Default | Description |
|---|---|---|---|
recordType | string | schedule | One of the nine supported output workflows |
season | integer | current UTC year | Season from 1876 through two years beyond the current year |
startDate | YYYY-MM-DD | today for schedules | First schedule date |
endDate | YYYY-MM-DD | start date | Last schedule date; ranges are limited to 366 days |
sportId | integer | 1 | MLB StatsAPI sport ID; 1 is Major League Baseball |
teamIds | string array | empty | Required for rosters; filters schedules, teams, and standings |
playerIds | string array | empty | Required for player stats; enables targeted player lookups |
leagueIds | string array | 103, 104 | Standings leagues; defaults to American and National Leagues |
statGroups | string array | hitting | Hitting, pitching, or fielding statistics |
statTypes | string array | season | Season, advanced, career, or year-by-year statistic scope |
gameTypes | string array | empty | Optional MLB codes such as R, S, or P |
maxItems | integer | 100 | Maximum deduplicated records, from 1 to 10,000 |
maxConcurrency | integer | 5 | Concurrent 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:
| Plan | Price 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 osfrom apify_client import ApifyClientclient = 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().itemsprint(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.
Legal and responsible use
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.
Related Automation Lab Actors
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.