MLB Ticket Availability Scraper
Pricing
from $1.50 / 1,000 results
MLB Ticket Availability Scraper
Read MLB box-office inventory off mlb.tickets.com: one row per section and price level still on sale, with availableSeats, maxContiguousSeats, face value in price, the checkout allInPrice and the serviceCharge between them. Name a club and it finds its own home games. 18 of 30 clubs.
Pricing
from $1.50 / 1,000 results
Rating
0.0
(0)
Developer
String
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
What does the MLB Ticket Availability Scraper do?
Every other ticket scraper on the Apify Store reads a resale marketplace, where the number on the
screen is a reseller's ask. This one reads the primary market — the seat map an MLB club publishes
on mlb.tickets.com, which is the box office's own inventory at the club's own face value.
Name a club, say red-sox, and the Actor reads that club's current home schedule itself, then
fetches the seat map for each upcoming game. You get one row per section and price level that still
has seats: how many are left, the longest run of adjacent seats in that block, the face value, the
all-in checkout price, and the per-ticket fee that is the gap between the two.
Event ids on this platform roll over every season, which is why the club is the durable input. A
saved run keyed on red-sox still works after the fixtures change; one keyed on an event id stops
working within months. Explicit ids are still accepted for anyone who already holds them.
- No account, session cookie or API key, at any point in the run
- One request per game, plus one per club to read its schedule
- Face value and checkout price on the same row, with the fee named rather than implied
- Values arrive typed from the venue's own feed —
174, not"$174.00"
What data does it extract?
One row per event x section x price level that has seats on sale. In a measured batch across three clubs, ten games produced 574 rows, roughly 57 per game.
| Field | Type | Description |
|---|---|---|
eventId | string | The club's own event id, stable within a season. Use it to de-duplicate or re-poll one game |
eventName | string | The event as the club names it, e.g. Giants at Red Sox |
eventDateTime | string | Start time, ISO 8601, carrying the ballpark's own UTC offset |
eventCode | string | The club's internal code for the event |
team | string | The club slug you asked for. null when the event came in as a bare id |
orgId | number | The club's tenant id on the platform. null on a bare id, for the same reason |
venueName | string | Ballpark name, e.g. Fenway Park |
venueCity | string | Venue city |
venueState | string | Two-letter state code |
sectionId | string | The venue's section id |
sectionName | string | Section as printed, e.g. LOGE BOX-LEFT FIELD |
sectionCode | string | The short public code for the section |
priceLevelId | string | The price-scale id the seats sit on |
priceLevelName | string | Price scale as the club names it, e.g. Loge Box |
priceLevelCode | string | The club's short code for that price scale |
availableSeats | number | Seats on sale in that section at that price level |
maxContiguousSeats | number | Largest block sold together — what a group of four needs |
sectionCapacity | number | The section's total size |
sectionAvailableSeats | number | The section's total on sale, across all its price levels |
price | number | Face value, as a number |
allInPrice | number | What the checkout charges once fees are added |
serviceCharge | number | allInPrice minus price, computed and stated |
currency | string | Currency of both price fields |
inventoryAsOf | string | The venue's own timestamp on the seat count |
sourceUrl | string | The seat-map URL the row was read from |
collectedAt | string | ISO timestamp of the run |
The unit is a section at a price level, not an individual seat. Seat numbers live behind a separate and much heavier request that this Actor does not make.
Why scrape MLB ticket availability?
Resale data tells you what a reseller hopes to get. Box-office data tells you what the club is still selling and at what price, and the two together are the actual arbitrage picture. Only one of them is hard to obtain, and it is this one.
Re-running a club on a schedule and diffing availableSeats per section gives a demand curve for a
game as it approaches: which parts of the ballpark drain first, how fast, and whether a promotion
moved anything. maxContiguousSeats answers a question the totals cannot — a section with 40 seats
left in ones and twos is useless to a group of four, and the field separates those cases.
price next to allInPrice puts a number on the fee load per price scale, which is otherwise
something a buyer only discovers at checkout. And because priceLevelName comes straight from the
club's own scale, you can compare how clubs tier an identical ballpark geometry across a homestand
or across the league on the same weekend.
How to use it
- Start from this page: Try for free, or save the Actor to your Apify account.
- Put club slugs in the Clubs field, one per line —
red-sox,cubs,dodgers. A club's numeric tenant id works too. - Optionally set From date and To date as
YYYY-MM-DDto bound the games by their own local date. - Set Events per club for how deep into each schedule to read, and Maximum results for a hard ceiling on rows.
- Click Start, then export from the Dataset tab as JSON, CSV or Excel.
- Check the run's
SUMMARYrecord: anything that could not be fetched is listed underfailureswith the reason.
Supply teams, eventIds, or both. An id that arrives twice — once directly, once because it is
also on a club's schedule — is fetched once, and keeps the club and date the schedule gave it.
Input
| Field | Type | Default | Description |
|---|---|---|---|
teams | array of strings | — | Club slugs whose home schedule to read, up to 40. A numeric tenant id also works |
eventIds | array of strings | — | Specific event ids, or event URLs carrying a pid. Up to 200, fetched without reading a schedule |
startDate | string | — | Skip games before this local date, YYYY-MM-DD |
endDate | string | — | Skip games after this local date, YYYY-MM-DD |
maxEventsPerTeam | integer | 10 | Events to read per club, 1 to 200. One event is one request |
maxItems | integer | 1000 | Ceiling on dataset rows, 1 to 50000 |
concurrency | integer | 3 | Targets fetched in parallel, 1 to 5 |
At least one of teams or eventIds must be non-empty; a run with neither is rejected before it
fetches anything.
{"teams": ["red-sox", "cubs"],"startDate": "2026-09-01","endDate": "2026-09-30","maxEventsPerTeam": 10,"maxItems": 1000,"concurrency": 3}
Output
One row per section and price level with seats on sale. The shape below is illustrative — it shows the fields and their types, not a captured run.
{"eventId": "9681705","eventName": "Giants at Red Sox","eventDateTime": "2026-09-12T19:10:00-04:00","eventCode": "26RS0912","team": "red-sox","orgId": 23,"venueName": "Fenway Park","venueCity": "Boston","venueState": "MA","sectionId": "1420","sectionName": "LOGE BOX-LEFT FIELD","sectionCode": "LB157","priceLevelId": "12","priceLevelName": "Loge Box","priceLevelCode": "LB","availableSeats": 18,"maxContiguousSeats": 4,"sectionCapacity": 132,"sectionAvailableSeats": 26,"price": 174,"allInPrice": 201.35,"serviceCharge": 27.35,"currency": "USD","inventoryAsOf": "2026-09-05T14:31:00-04:00","sourceUrl": "https://mlb.tickets.com/api/pvodc/v1/events/navmap/availability/?pid=9681705&agency=MLB_MPV&supportsVoucherRedemption=true&accessible=false","collectedAt": "2026-09-05T14:36:22.114Z"}
A sold-out game returns no rows rather than a wall of zeroes. The venue's response describes every section of the ballpark whatever its state, so emitting all of them would bill several hundred empty rows for a game with nothing to sell.
What it covers, and what it does not
Eighteen of the thirty MLB clubs sell through this platform: angels, astros, brewers,
cardinals, cubs, dodgers, guardians, marlins, nationals, phillies, pirates,
rangers, rays, red-sox, reds, royals, tigers, twins. The other twelve are on
Ticketmaster and have no box office on this host at all. A club that is not on the list is reported
under failures immediately rather than fetched, so it costs nothing.
Home games only. A club's schedule here is what that club sells, so an away game belongs to the host club's feed, not this one.
Some clubs list non-baseball events on the same schedule. Parking passes, stadium tours and
museum entry appear alongside the games — the Cardinals' schedule runs to roughly 110 entries, most
of them exactly that. They return as ordinary rows and are billed as ordinary rows. eventName is
what tells them apart, so filter on it (or set a tight date window) if you only want ballgames.
inventoryAsOf runs a few minutes behind live. That is the venue's own snapshot timestamp, not
our latency. It is fine for trend work and comparison against resale; it is the wrong feed to sit
behind a real-time booking flow.
Seat-by-seat detail, resale listings, holds, season-ticket inventory and anything requiring a login are all out of scope.
How much does it cost?
Pricing is per event: one charge for each result row written to the dataset. A club or event that fails produces no rows and costs nothing. The current rate is in the pricing panel at the top of this page.
What drives the total is rows per game, and that number is large — roughly 57 in our measured batch,
because a ballpark has many sections and most of them have something on sale. Bound it with
maxEventsPerTeam and maxItems before running a wide sweep, and remember that the non-baseball
entries described above are charged the same as games.
Runs started from an Apify free plan stop at 250 requests and 250 results, reported in the run's
status message; any paid plan runs the full input and whatever maxItems you set. The cap is there
because this Actor fetches through String's own infrastructure, which Apify does not reimburse on
free-plan runs, and it binds on requests as well as rows so a long club list cannot spend those
fetches on rows the run will not return.
Using it with the Apify API
import { ApifyClient } from "apify-client";const client = new ApifyClient({ token: "<YOUR_APIFY_TOKEN>" });const run = await client.actor("usestring/mlb-tickets").call({teams: ["red-sox", "cubs"],startDate: "2026-09-01",endDate: "2026-09-30",maxEventsPerTeam: 5});const { items } = await client.dataset(run.defaultDatasetId).listItems();// Sections that can still seat a group of four together, cheapest first.const groupsOfFour = items.filter((row) => row.maxContiguousSeats >= 4).sort((a, b) => a.allInPrice - b.allInPrice);console.log(groupsOfFour.slice(0, 10));const summary = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord("SUMMARY");console.log(summary?.value);
Is it legal to scrape MLB ticket availability?
The Actor reads the same public inventory a club's own ticketing page loads for a logged-out visitor. There is no account, no session cookie, no paywall and no access control being stepped around. Collecting information from a page published to the open web is lawful in the US and the EU under current case law; what invites trouble is circumventing a login, and that does not happen here.
Nothing collected is personal data. Every row describes a section of a ballpark and a price — no buyers, no ticket holders, no names of any kind. Prices and seat counts are facts rather than creative work, though a club's event descriptions and section naming are its own, so treat the text as source material for analysis rather than something to republish. Ticketing terms of service and your own reselling obligations are yours to check against what you intend to do with the data. This is not legal advice.
Related actors
No other String Actor reads ticketing, so these are neighbours rather than substitutes:
- Spotify Artist Scraper - Listeners & Followers — monthly listeners and follower counts, for anyone modelling live-event demand from audience size.
- Yahoo Finance Quote Scraper — quotes and fundamentals, useful alongside inventory data on publicly listed sports and media groups.
- TikTok Profile Scraper — follower and engagement counts, another attention signal to line up against a demand curve.
- Etsy Listings Scraper - Price, Shop & Badges — a second pass-through Actor built the same way, if you want to see the pattern on a marketplace.
FAQ
Is this resale prices or box-office prices?
Box office. price is the club's face value and allInPrice is what the checkout charges once fees
are added. Neither is a reseller's ask.
Do I need an account, API key or cookies? No. It reads the public inventory a logged-out visitor's browser loads, and never signs in.
Do I have to know the event id? No, and you should not have to — ids roll over every season. Give it a club slug and, if you like, a date window. Ids remain available as an input for anyone who already has them.
Which clubs work? The eighteen listed above. The other twelve sell through Ticketmaster and are rejected up front, without a fetch, rather than returning an empty schedule.
Is it seat by seat? No. A row is a section at a price level: how many seats are on sale there and the largest adjacent block. Individual seat numbers need a different and far heavier request.
How fresh are the counts?
inventoryAsOf carries the venue's own timestamp on the snapshot, which in our sampling ran a few
minutes behind live.
Why is team sometimes null?
Because that event came in as a bare id, so there was no club to attribute it to. orgId is null
for the same reason. Every other field on the row is unaffected.
Why did a run return parking or a stadium tour?
Because the club lists those on the same schedule the games are on. They come back as normal rows;
filter on eventName to drop them.
Do I get anything for a sold-out game?
No rows, deliberately. An event id that does not resolve at all is different again — it lands in
SUMMARY.failures with the site's own message rather than becoming a row of nulls.
How fast is it? A seat map took a median of 7.6 seconds at concurrency 3 in our measurements, and 2.2 seconds run sequentially; the difference is solver work happening in parallel, not the origin slowing down.
Feedback
If a club fails, a game returns nothing you expected, or a price looks wrong, open an issue from the
Issues tab on this Actor's Store page and include the club slug and the eventId.