MLB Stats Scraper & Stat Change Monitor - Hitting, Pitching avatar

MLB Stats Scraper & Stat Change Monitor - Hitting, Pitching

Pricing

from $3.65 / 1,000 stat line returneds

Go to Apify Store
MLB Stats Scraper & Stat Change Monitor - Hitting, Pitching

MLB Stats Scraper & Stat Change Monitor - Hitting, Pitching

For fantasy baseball, betting models and analytics: season hitting, pitching and fielding from the official MLB Stats API - 4,223 stat lines for 2026 (732 hitting, 848 pitching, 2,643 fielding). Innings pitched are handled as thirds, not decimals. Monitoring returns only lines that changed.

Pricing

from $3.65 / 1,000 stat line returneds

Rating

0.0

(0)

Developer

NeverEmpty

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

MLB Stats Scraper & Stat Change Monitor — Hitting, Pitching, Fielding

Built for fantasy baseball, betting models and season-long analytics: every MLB season stat line from the official MLB Stats API as one flat row — the player, team, league, position, the rank the API assigns, and every stat it publishes for that group.

A whole season, not a sample. For 2026 the API held 732 hitting, 848 pitching and 2,643 fielding lines — 4,223 lines in all — and this Actor pages through the entire group, 100 at a time, until the API's own total is reached. The player pool is yours to choose: 2026 hitting holds 732 lines under ALL but the 2025 group holds 145 under QUALIFIED, so leaving a default in place quietly shows you a fraction of the league.

The two things that silently ruin baseball data are fixed here. Innings are thirds, not decimals — 20.1 is 20 innings and one out, so every innings figure comes back three ways ("20.1", 61 outs, 20.3333). And a rate the API could not compute (.---) comes back as null, never 0: on the 2026 pitching fixture 39 of 60 lines had at least one.

Turn monitoring on and every later run returns only the stat lines that have actually changed, so you are never charged for the same line twice. Run it daily through the season and pay only for the players who played. Export as JSON, CSV or Excel.

Unofficial Actor. Not affiliated with or endorsed by MLB. It reads MLB's public Stats API — no key, no login, no HTML parsing.

What it does

  • Three stat groups. Hitting, pitching and fielding. For the 2026 season the API held 732 hitting, 848 pitching and 2,643 fielding lines.
  • 🔁 Change monitoring. The remembered key is the player plus the group plus every number in their line, so a player comes back only when a stat actually moved. Run it daily during the season and pay only for the players who played.
  • 👥 The player pool matters, and you choose it. The 2026 hitting group holds 732 lines under ALL; the 2025 group holds 145 under QUALIFIED — the pool changes the answer by roughly a factor of five. An Actor that leaves the default in place quietly shows you a fraction of the league.
  • 📄 Full pagination. Reads through the whole group, 100 at a time, and stops when the API's own total is reached.

🔴 Two things this Actor gets right that are easy to get wrong

1. Innings are thirds, not decimals. In baseball 20.1 means 20 innings and one out — 20⅓ — not 20.1. Summing or averaging the raw number is silently wrong. Every innings figure is returned three ways:

ColumnValue for 20.1
inningsPitchedRaw"20.1" (exactly as the API prints it)
inningsPitchedOuts61
inningsPitchedDecimal20.3333

The same applies to fielding innings. If the API ever prints a first decimal above 2, that is not a thirds notation, and the Actor returns null rather than guessing.

2. Unavailable rates are not zero. When a rate cannot be computed, the API prints .--- or -.--. Turning that into 0 invents a fact — a pitcher with no stolen-base attempts against him is not a pitcher with a 0% rate. Those come back as null, with the original text kept in a …Raw column. On the 2026 pitching fixture, 39 of 60 lines had at least one.

What this Actor refuses to guess

The MLB API answers HTTP 200 with an empty stats array for a stat group it does not know — which looks exactly like "this player has no stats". Only the three verified groups are accepted, and an unknown one is refused with an explanation rather than reported as an empty result.

A season that has not been played returns a genuine zero (2030 gives totalSplits: 0), and that is reported as the API's own answer. Empty seasons, unknown groups, filters that matched nothing and unreadable responses each come back as their own row with the reason, and none are charged.

What you get in every row

FieldWhat it is
season, statGroup, playerPoolWhat was asked for, on every row
playerId, playerName, firstName, lastNameThe player and their MLB id
teamId, teamName, leagueId, leagueNameWhere they played
position, positionAbbreviation, positionTypeTheir position
statRankThe rank the API assigns within the group
teamsPlayedForMore than 1 means they were traded mid-season
(the stats)Every stat the API publishes, flattened: homeRuns, avg, ops, era, whip, assists, putOuts
…RawKept whenever a value could not be turned into a number
statKeyChanges when any stat changes — this is what monitoring compares

Configure the run

{ "statGroups": ["hitting"], "season": 2026, "playerPool": "ALL", "maxPlayers": 200 }

Follow one team through the season, paying only for changes:

{ "statGroups": ["hitting", "pitching"], "teams": ["Dodgers"], "monitoringMode": true }

Qualified hitters only, top 50 by the API's rank:

{ "statGroups": ["hitting"], "playerPool": "QUALIFIED", "maxRank": 50 }

Input reference

Every field is optional; the defaults read 2026 hitting for all players.

FieldTypeDefaultWhat it does
statGroupsarray["hitting"]Which stat groups to read. The MLB API answers HTTP 200 with an empty stats array for a group it does not know, which looks exactly like 'this player has no stats',…
seasoninteger2026Which season to read. Seasons that have not been played return zero rows, which is the API's own honest answer and is reported as such rather than as a failure.
playerPoolstringALLWhich players are included. This changes the result a lot: for 2026 hitting the API returned 732 players for ALL but only 140 for QUALIFIED (players who reached the…
maxPlayersinteger200How many rows to return. One row is one player in one stat group. You are charged for the rows you actually receive. For reference, 2026 held 732 hitting, 848…
monitoringModebooleanfalseOff = return every line for the groups you picked. On = remember the exact numbers already returned and, on later runs, return a player's line again only when one of…
resetMonitoringStatebooleanfalseClear the remembered lines before this run, so everything counts as new again.
teamsarray[]Keep a line only if the team name contains one of these (case-insensitive, partial). Example: Yankees, Dodgers.
playersarray[]Keep a line only if the player's full name contains one of these (case-insensitive, partial). Example: Ohtani, Judge.
positionsarray[]Keep a line only if the position or its abbreviation contains one of these (case-insensitive, partial). Example: Pitcher, P, Catcher, C.
leaguesarray[]Keep a line only if the league name contains one of these. Example: American League, National League.
minGamesPlayedinteger0Keep a line only if the player appeared in at least this many games. 0 = no limit. Lines with no games-played figure are kept, because unknown is not the same as zero.
maxRankinteger0The API assigns each line a rank within the group. 0 = no limit. Lines with no rank are kept.
keywordsarray[]Keep a line only if one (Any) or all (All) of these appear in the player, team, position, league or group name.
keywordMatchstringanyAny = at least one keyword. All = every keyword.
excludeKeywordsarray[]Drop a line if any of these appear in the same fields.
useProxybooleanfalseOff by default: the official MLB Stats API answered 200 from a plain Apify datacentre address when this Actor was built (2026-09-06). If it starts answering 403, 429…

Pricing

Pay per result: you are charged for the stat lines you actually receive. Rows that only explain why there is nothing (no-results, no-such-group, unreadable, no-filter-match, no-stat-change) are never charged.

Every number in this README is checked

The fixtures in test/fixtures/ are the real responses this Actor was built from (2026-09-06). The test suite re-counts every figure quoted above — 60, 732, 848, 2643, 145, 39, 20.1, 61, 20.3333 — so if the API changes, the tests fail rather than the data going quietly wrong.