MLB NHL Schedule Scraper avatar

MLB NHL Schedule Scraper

Pricing

from $1.40 / 1,000 results

Go to Apify Store
MLB NHL Schedule Scraper

MLB NHL Schedule Scraper

Retrieve MLB and NHL schedules for an inclusive date range, with game IDs, season, game type, UTC start time, status, team names, scores, and venue. The Actor maps both leagues into a consistent dataset shape and follows NHL weekly schedule dates as needed.

Pricing

from $1.40 / 1,000 results

Rating

0.0

(0)

Developer

Axiom Works

Axiom Works

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Returns: one row per MLB or NHL game with league, gameId, startTime, status, homeTeam, awayTeam, and tvBroadcasts. Input: {"startDate":"2025-03-01","endDate":"2025-03-02","leagues":["MLB","NHL"],"maxItems":20} Best for: schedule tracking, score analysis, and building game calendars.

{"id":"779129","league":"MLB","gameId":"779129","startTime":"2025-03-01T18:05:00Z","status":"Final","homeTeam":"Baltimore Orioles","awayTeam":"Pittsburgh Pirates","tvBroadcasts":["MASN","SportsNet Pittsburgh","MLBN (out-of-market only)"]}

What does MLB and NHL Games Scraper do?

This MLB and NHL scraper collects game schedules and scores from the public MLB API and NHL schedule API. Give it an inclusive date range, choose either league or both, and it returns one dataset row per game. Each row identifies the league, game, season, game type, scheduled UTC start, status, teams, scores where published, venue, and the exact API URL that supplied the data. It is useful when you need a compact game calendar or a set of historical results without stitching together two different API response formats.

The MLB and NHL APIs have different fields and pagination. This Actor maps the fields into one consistent dataset while preserving each league's game type and status codes. It collects MLB's full requested range with one schedule request. For NHL, it follows the schedule's weekly nextStartDate value until it has covered the requested end date. Games returned outside the requested dates are filtered out. No login is needed for these public endpoints. This Actor is an independent tool and is not affiliated with MLB, NHL, or their teams.

What data can you get?

The dataset contains the following fields. The same shape is used for both leagues, with null values for source fields that were unavailable. NHL team names are assembled from its place name and common name; MLB team names come from its team name fields. The existing startTime stays in UTC. The added localStartTime converts that instant to the requested timezone, using daylight saving rules for that date. It is a wall-clock value without an offset; keep startTime when ordering instants or handling an ambiguous autumn clock change.

FieldDescriptionExample
idStable league game identifier as text, unique within a run779129
leagueSource leagueMLB
gameIdLeague's game identifier as text779129
seasonLeague season value; NHL uses its combined season number2025
gameTypeLeague's game type codeS
startTimeScheduled game start in UTC2025-03-01T18:05:00Z
localStartTimeLocal wall-clock start in the requested timezone2025-07-01T15:07:00
timezoneRequested IANA timezoneAmerica/New_York
statusLeague's current game state or detailed statusFinal
homeTeamHome team nameBaltimore Orioles
awayTeamAway team namePittsburgh Pirates
homeScorePublished home score, or null2
awayScorePublished away score, or null5
venuePublished venue name, or nullEd Smith Stadium
gameDateSchedule calendar date of the game2025-03-01
homeAbbrevHome team abbreviation, or nullBAL
awayAbbrevAway team abbreviation, or nullPIT
homeProbablePitcherAnnounced home probable pitcher (MLB only, otherwise null)Cade Povich
awayProbablePitcherAnnounced away probable pitcher (MLB only, otherwise null)Paul Skenes
homeTeamIdHome team ID from the selected league141
awayTeamIdAway team ID from the selected league147
tvBroadcastsUnique published TV network names, or null["Sportsnet", "YES"]
sourceUrlSchedule API endpoint that returned the gamehttps://statsapi.mlb.com/api/v1/schedule?...

Scores reflect the API at the time of the run. Re-running the same future date range later can fill in scores and update a game's status. A game rescheduled by a league may move to a new date or receive a changed start time. If you store results over time, use league and gameId together as your key and keep the latest run's values. The Actor deduplicates game IDs within each run, including repeated NHL games around the edges of weekly schedule responses. When the MLB range includes both a postponed listing and a later played listing for the same game, the played listing supplies the status, start time, scores, and other fields. A postponed game without a replacement listing keeps its source status and null scores. Resumed games keep the first listing when neither entry is postponed.

TV broadcasts are copied from MLB TV broadcast entries and NHL network entries. Radio entries are excluded, and repeated network names appear once. A network name does not establish viewing availability, streaming rights, subscription access, or availability in your country. Missing broadcast data is null. Historical and future schedules can carry different broadcast details, so refresh the relevant date range when planning coverage.

The new homeTeamId and awayTeamId fields support reliable joins when names or abbreviations change. IDs are strings copied from each league's API. Pair them with league: MLB and NHL have separate identifier namespaces. Existing team names and abbreviations remain available.

How to use

Open the Actor on Apify, enter startDate and endDate as calendar dates in YYYY-MM-DD format, and select the leagues you want. Keep maxItems at the default for a compact result or increase it for a larger date range. Start the run, then open the dataset to review game rows and export the records. The prefilled dates point to past games so a first run produces stable sample results.

The range includes both endpoints. Leagues run in supplied order, MLB first by default. Once maxItems is reached, processing stops before another request. Run each league separately when each needs an independent item limit.

The Actor normally requests the public APIs directly. The optional proxyConfiguration input accepts an Apify proxy configuration if a network blocks one of the endpoints. Transient rate limits, server errors, and block responses trigger retries with backoff and a fresh proxy session when a proxy is configured. The Actor does not solve CAPTCHA challenges. Requests are paced to approximately two per second. If an endpoint stays unavailable, the run reports that condition and returns any games that were already collected from the other league.

Input

Input fieldRequiredDescriptionDefault or prefill
startDateYesFirst included game date, YYYY-MM-DDPrefill 2025-03-01
endDateYesLast included game date, YYYY-MM-DD, on or after startPrefill 2025-03-02
leaguesNoArray containing MLB, NHL, or bothBoth
statusesNoExact source status values, ignoring case, e.g. ["Final", "OFF"]All statuses
teamsNoTeam names, abbreviations, or exact numeric IDs as strings; matches home or awayAll teams
timezoneNoIANA timezone for localStartTime, e.g. America/New_YorkUTC
maxItemsNoExact maximum number of game rows, from 1 to 1000050; prefill 20
proxyConfigurationNoApify proxy settings for blocked networksNo proxy

Here is a request for one week of NHL games. The date values are strings; the league choice is an array. You can omit leagues to request both leagues. You can omit maxItems to use its default. Team names are optional: set teams to keep only games where the home or away team matches any supplied name or abbreviation (case-insensitive substring). The filters are combined with OR: ["Yankees", "TOR"] keeps games involving either team, not only games between them. An unmatched filter succeeds with zero rows.

{
"startDate": "2025-03-01",
"endDate": "2025-03-07",
"leagues": ["NHL"],
"maxItems": 30
}

Invalid date formats, impossible calendar dates, an end date before the start date, unknown league values, and an invalid item limit fail with a clear input message. A valid period with no games ends successfully with zero rows. That difference is useful in automation: you can treat bad configuration as an error while accepting an off-season day as an ordinary empty response. The output order follows the league APIs' schedule order. If you need a particular display order, sort the dataset by startTime after export.

The optional statuses filter compares the original status value exactly, ignoring case. For completed MLB games use ["Final"]; for completed NHL schedules the source commonly uses ["OFF", "FINAL"]. The Actor preserves these original values rather than changing the meaning of status. Multiple entries match with OR. Status filtering combines with the date range and team filtering with AND, and only qualifying games count toward maxItems. An unknown status succeeds with no rows, so check an unfiltered sample when choosing values for live or postponed games.

For example, {"startDate":"2025-07-01","endDate":"2025-07-01","leagues":["MLB"],"teams":["TOR"],"statuses":["Final"],"maxItems":1} selects a completed Toronto game and includes its team IDs and published TV networks. Leave statuses empty to keep the previous behavior. Broadcast information is fetched with the existing MLB schedule request and read from the existing NHL schedule response; this does not add a detail request per game.

The optional timezone input defaults to UTC. For example, {"startDate":"2025-07-01","endDate":"2025-07-01","leagues":["MLB"],"teams":["147"],"timezone":"America/New_York","maxItems":1} selects games involving MLB team 147. Numeric strings match team IDs exactly; names and abbreviations keep their existing substring behavior. IDs are league-specific, so select a league when using them. Invalid timezone names fail input validation before requests begin. The timezone affects only output formatting, not the inclusive schedule date filter.

Output

Each dataset item is a game, not a team or a day. The following real item came from a local run against the MLB schedule API for July 1, 2025. The sourceUrl records the complete endpoint used by that run. id and gameId are both retained: id is the dataset key, while gameId makes the league identifier explicit to downstream code.

{
"id": "777283",
"league": "MLB",
"gameId": "777283",
"season": "2025",
"gameType": "R",
"startTime": "2025-07-01T19:07:00Z",
"localStartTime": "2025-07-01T15:07:00",
"timezone": "America/New_York",
"status": "Final",
"homeTeam": "Toronto Blue Jays",
"awayTeam": "New York Yankees",
"homeScore": 12,
"awayScore": 5,
"venue": "Rogers Centre",
"gameDate": "2025-07-01",
"homeTeamId": "141",
"awayTeamId": "147",
"tvBroadcasts": [
"Sportsnet",
"YES",
"MLBN (out-of-market only)",
"TVA Sports"
],
"homeAbbrev": "TOR",
"awayAbbrev": "NYY",
"homeProbablePitcher": "Kevin Gausman",
"awayProbablePitcher": "Max Fried",
"sourceUrl": "https://statsapi.mlb.com/api/v1/schedule?sportId=1&startDate=2025-07-01&endDate=2025-07-01&hydrate=team,probablePitcher,broadcasts"
}

How much does it cost?

This Actor is charged per result saved to the dataset. The result event is applied once for each game row. Runs with no rows have no result events, and a lower maxItems stops output and result charging at that count. The current rate and billing details are on the Actor's Pricing tab on Apify. Check that tab before a large run because the rate can change. The result count includes only saved game rows.

Use with AI agents (MCP)

Apify's MCP endpoint can expose this Actor to an AI agent. Configure the server URL as https://mcp.apify.com/?tools=axiomworks/mlb-nhl-games-scraper in an MCP client that supports Apify. The exact tool path is axiomworks/mlb-nhl-games-scraper. The agent can submit the same JSON input described above and read the dataset rows as structured results. Keep the date range and desired league explicit in prompts so the agent selects the intended schedule.

Example prompts include “Get NHL games from March 1 to March 7, 2025 and include scores and venues,” “List MLB games on July 1, 2025 with start times and teams,” and “Collect both MLB and NHL games for March 1, 2025 with at most twenty rows.” The agent should use homeScore and awayScore only when those fields are populated. For comparative analysis, ask the agent to group by league and interpret gameType and status within that league's own codes.

Integrations and API

You can run axiomworks/mlb-nhl-games-scraper through Apify's API and then use the default dataset endpoint for JSON, CSV, or another supported export format. Set APIFY_TOKEN in your environment at runtime. Keep tokens outside source control. The examples show a one-day NHL request with a small item limit; adjust the JSON for your workflow.

Python with apify-client:

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('axiomworks/mlb-nhl-games-scraper').call(run_input={
'startDate': '2025-03-01', 'endDate': '2025-03-01',
'leagues': ['NHL'], 'maxItems': 10,
})
for game in client.dataset(run['defaultDatasetId']).iterate_items():
print(game['gameId'], game['homeTeam'], game['awayTeam'])

JavaScript with apify-client:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('axiomworks/mlb-nhl-games-scraper').call({
startDate: '2025-03-01', endDate: '2025-03-01',
leagues: ['NHL'], maxItems: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
process.stdout.write(JSON.stringify(items));

cURL using the synchronous dataset item endpoint:

curl -X POST \
"https://api.apify.com/v2/acts/axiomworks~mlb-nhl-games-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"startDate":"2025-03-01","endDate":"2025-03-01","leagues":["NHL"],"maxItems":10}'

FAQ

Can I request one date? Yes. Set startDate and endDate to the same valid date. The Actor includes games assigned to that date by the source schedule. Timezone boundaries in the source can mean a UTC start falls on an adjacent calendar date; use the schedule date for filtering and startTime for precise time calculations.

Are both leagues always returned? Both are selected by default in MLB then NHL order, but an item limit can be reached while processing the first league. Use ["NHL", "MLB"] to process NHL first. Select NHL only when you need NHL records within a small limit. A separate run for each league gives each an independent item cap.

Why is a score null? A scheduled game may not have started, or the API may omit a score. Null means unavailable in the response. It is different from a published score of zero. Rerun after the game when you need final scores.

Can I use a large range? The MLB endpoint accepts a range in one request, and NHL schedules are read week by week. The Actor respects the result limit and a two-request-per-second pace. Large ranges can take longer and return many records, so set a meaningful maxItems.

What happens if an API is unavailable? A transient block or server response is retried. If one league remains unavailable, the Actor can still return games collected from the other league and logs the failed request. With no games returned, the run suggests choosing dates during the selected league’s season, checking leagues, removing or broadening teams filters, and retrying or configuring proxyConfiguration when an API is unavailable.

The Actor reads public schedule API responses without logging in. Public accessibility does not settle every legal question. League data may be subject to copyright, database rights, website terms, or use restrictions depending on your location and purpose. Review the relevant terms and obtain legal advice for a commercial use that needs it. Respect the source services by running at a modest rate and avoiding unnecessary repeated requests. This Actor is independent and does not claim authorization or affiliation with either league.

Feedback

Report missing fields or changed responses through the Actor’s Apify feedback channel. Include the run input, affected gameId, and sourceUrl so the source response can be checked.