# Nhl Stats Scraper (`real-estate-api/nhl-stats-scraper`) Actor

NHL Stats Scraper is a Python tool designed to extract real-time and historical National Hockey League data, including player statistics, game box scores, team standings, and schedules. It exports structured hockey data into clean CSV or JSON formats for sports analytics and fantasy league modeling.

- **URL**: https://apify.com/real-estate-api/nhl-stats-scraper.md
- **Developed by:** [real-estate-api](https://apify.com/real-estate-api) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## NHL Stats Scraper: NHL Standings, Schedules, and Players

<p align="center">
  <img src="https://imgur.com/imWeob4.png" alt="NHL Stats Scraper" width="800" />
</p>

Collect structured NHL standings, weekly schedules, and current team rosters. Export team rankings, points, goal statistics, game times, scores, player positions, and other available fields into a dataset.

No login or access key is required for the supported public data sources. Export results as JSON, CSV, or Excel, and schedule runs to keep your files up to date.

The actor relies on publicly accessible NHL data resources. These resources are not a documented, stable product interface, so fields and response formats may change.

### Use Cases

- **Standings updates:** Collect conference and division rankings, points, wins, and goal statistics for a selected date.
- **Schedule tracking:** Retrieve games for a week and continue through subsequent weeks until the configured item limit is reached.
- **Roster checks:** Export current forwards, defensemen, and goalies for a selected team.
- **Spreadsheet exports:** Move structured NHL data into Excel or other compatible data analysis tools.
- **Scheduled monitoring:** Refresh standings, schedules, or rosters and retain source references and collection timestamps.

### Input

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `standings` | Operation: `standings`, `schedule`, or `roster`. |
| `date` | string | `2026-01-15` | Date in `YYYY-MM-DD` format for standings and schedule modes. |
| `team` | string | `TOR` | Team abbreviation for roster mode. |
| `maxItems` | integer | `100` | Maximum number of saved records, from 1 to 1,000. |
| `timeoutSecs` | integer | `300` | Overall run time limit in seconds. |
| `requestTimeoutSecs` | integer | `30` | Timeout for an individual request, in seconds. |

### Example Inputs

#### Standings

```json
{
  "mode": "standings",
  "date": "2026-01-15",
  "team": "TOR",
  "maxItems": 100,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30
}
```

#### Current Team Roster

```json
{
  "mode": "roster",
  "team": "TOR",
  "maxItems": 100
}
```

#### Weekly Schedule

```json
{
  "mode": "schedule",
  "date": "2026-10-10",
  "maxItems": 100
}
```

### What Data Does This Actor Extract?

The output structure depends on the selected mode:

- **Standings:** One record per team, including conference and division positions, points, wins, losses, and goal statistics.
- **Schedule:** One record per game, including participating teams, scores, game state, start time, and venue when available.
- **Roster:** One record per player, including player ID, name, position, jersey number, and headshot URL when available.

If the date or mode is invalid, or the source returns an unusable response, the actor records an error row rather than necessarily failing the entire run.

Example standings record:

```json
{
  "conferenceAbbrev": "W",
  "conferenceName": "Western",
  "conferenceSequence": 1,
  "date": "2026-01-15",
  "divisionAbbrev": "C",
  "divisionName": "Central",
  "divisionSequence": 1,
  "gameTypeId": 2,
  "gamesPlayed": 45,
  "goalDifferential": 79,
  "goalDifferentialPctg": 1.755556,
  "goalAgainst": 103,
  "goalFor": 182,
  "goalsForPctg": 4.044444,
  "teamAbbrev": "COL",
  "teamNameText": "Colorado Avalanche",
  "points": 74,
  "wins": 33,
  "scrapedAt": "2026-10-12T00:00:00+00:00"
}
```

### Output Fields

The fields below cover the supported standings, schedule, roster, and error records. Fields depend on the selected mode and the data returned by the source.

| Field | Type | Description |
|---|---|---|
| `conferenceAbbrev` | string | Conference abbreviation. |
| `conferenceHomeSequence` | integer | Conference position based on home performance. |
| `conferenceL10Sequence` | integer | Conference position based on the last 10 games. |
| `conferenceName` | string | Conference name. |
| `conferenceRoadSequence` | integer | Conference position based on road performance. |
| `conferenceSequence` | integer | Overall conference position. |
| `date` | string | Standings or game date. |
| `divisionAbbrev` | string | Division abbreviation. |
| `divisionHomeSequence` | integer | Division position based on home performance. |
| `divisionL10Sequence` | integer | Division position based on the last 10 games. |
| `divisionName` | string | Division name. |
| `divisionRoadSequence` | integer | Division position based on road performance. |
| `divisionSequence` | integer | Overall division position. |
| `gameTypeId` | integer | Game type identifier. |
| `gamesPlayed` | integer | Games played. |
| `goalDifferential` | integer | Goals scored minus goals conceded. |
| `goalDifferentialPctg` | number | Goal differential per game, as reported by the source. |
| `goalAgainst` | integer | Goals conceded. |
| `goalFor` | integer | Goals scored. |
| `goalsForPctg` | number | Goals scored per game, as reported by the source. |
| `homeGamesPlayed` | integer | Home games played. |
| `homeGoalDifferential` | integer | Home goal differential. |
| `homeGoalsAgainst` | integer | Home goals conceded. |
| `homeGoalsFor` | integer | Home goals scored. |
| `homeLosses` | integer | Home losses. |
| `teamAbbrev` | string | Team abbreviation. |
| `teamNameText` | string | Team name. |
| `points` | integer | Standings points. |
| `wins` | integer | Wins. |
| `losses` | integer | Losses. |
| `otLosses` | integer | Overtime losses. |
| `gameId` | integer | Game identifier. |
| `gameDate` | string | Scheduled game date. |
| `startTimeUTC` | string | Game start time in UTC. |
| `gameState` | string | Game state code. |
| `awayTeamAbbrev` | string | Away team abbreviation. |
| `homeTeamAbbrev` | string | Home team abbreviation. |
| `awayScore` | integer | Away team score, when available. |
| `homeScore` | integer | Home team score, when available. |
| `venueName` | string | Arena or venue name, when available. |
| `playerId` | integer | Player identifier. |
| `firstNameText` | string | Player's first name. |
| `lastNameText` | string | Player's last name. |
| `positionCode` | string | Player position code. |
| `sweaterNumber` | integer | Jersey number. |
| `team` | string | Roster team abbreviation. |
| `headshotUrl` | string | Player headshot URL, when available. |
| `scrapedAt` | string | UTC timestamp when the row was saved. |
| `error` | string | Explanation of an input or processing error. |
| `input` | object | Input details attached to an error record. |

### How It Works

1. The actor reads the selected mode, date, and team abbreviation.
2. It retrieves the corresponding standings, schedule, or current roster data from the public NHL data source.
3. Requests are spaced at least one second apart. HTTP `429` responses, server errors, and timeouts are retried up to three times, with delays of 2, 4, and 8 seconds or longer when a `Retry-After` value requires it.
4. In schedule mode, the actor follows the next available start date to retrieve additional weeks when the item limit exceeds the first week's results.
5. Duplicate team records, game IDs, and player IDs are skipped.
6. The actor stops at `maxItems` or the overall timeout and saves the collected records.

### Limits and Data Use

- **Request pacing:** Requests are spaced at least one second apart.
- **Retries:** Temporary rate limits, server errors, and request timeouts are retried within the configured behavior.
- **Maximum records:** Up to 1,000 records per run.
- **Standings:** A single response normally contains the full standings table. The item limit can reduce the number of saved rows.
- **Schedule:** Additional weeks are retrieved when needed, subject to the item limit and available schedule data.
- **Roster:** The actor retrieves the current roster for the selected team.
- **Source changes:** The source data structure may change without notice because it is not a documented, stable product interface.

NHL game data, team names, logos, and other marks may be subject to copyright or trademark protections. Use exported data responsibly, respect applicable terms and licensing requirements, and do not present NHL-owned material as your own.

### FAQ

#### Why did I receive an error row instead of standings?

The date may not use `YYYY-MM-DD` format, the selected mode may be invalid, or the source may have returned an unusable response or an HTTP error after retries.

#### How many teams are included in standings?

A standings response normally contains the full table, typically 32 teams. The `maxItems` setting limits the number of records saved.

#### Can schedule mode retrieve more than one week?

Yes. When `maxItems` exceeds the number of games available in the initial week, the actor follows the next available start date until it reaches the cap or encounters a stopping condition.

#### Can I schedule regular exports?

Yes. Schedule the actor in Apify to collect updated standings, upcoming games, or current rosters at your preferred interval.

### Trademark Notice

NHL and related names, logos, and trademarks belong to their respective owners. Their use in this documentation is solely to identify the source of the data and does not imply affiliation, sponsorship, endorsement, or partnership.

### Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, sponsored by, or otherwise officially associated with the NHL or its owners.

### Is Web Scraping Legal?

Collecting information that is already public is generally legal. Scraping is not the same thing as hacking, and there is no single law that bans it. The limits are the usual ones: do not break into accounts, do not take private or confidential data, and be careful with personal data and copyrighted works. A site's terms can also restrict how you access it. Facts such as a public name, price, or rating are not the same thing as republishing someone's article or photo.

This actor collects information from public pages. It does not log in and it does not bypass access controls.

For a longer explanation, see Apify's article [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/).

# Actor input Schema

## `mode` (type: `string`):

Which public NHL feed to read. standings returns the table for a date. schedule returns games in the week that contains that date, then later weeks if the item cap is still open. roster returns the current skaters and goalies for one team.

## `date` (type: `string`):

Calendar date in YYYY-MM-DD. Used by standings and schedule. Ignored for roster.

## `team` (type: `string`):

Three-letter NHL team abbreviation, such as TOR, BOS, or COL. Used only in roster mode.

## `maxItems` (type: `integer`):

Maximum records to save this run. Free cap, hard max 1000.

## `timeoutSecs` (type: `integer`):

Overall time limit for the run, in seconds. The actor stops fetching when this elapses and keeps rows already saved.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for a single NHL API response before retrying or recording an error.

## `proxyConfiguration` (type: `object`):

Optional proxy for NHL requests. Leave Apify Proxy off unless the source blocks your IP. Datacenter proxies are faster. Residential proxies are harder to block.

## Actor input object example

```json
{
  "mode": "standings",
  "date": "2026-01-15",
  "team": "TOR",
  "maxItems": 100,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Default dataset with standings, schedule, or roster rows.

## `datasetItems` (type: `string`):

JSON items from the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "date": "2026-01-15",
    "team": "TOR",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("real-estate-api/nhl-stats-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "date": "2026-01-15",
    "team": "TOR",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("real-estate-api/nhl-stats-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "date": "2026-01-15",
  "team": "TOR",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call real-estate-api/nhl-stats-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,real-estate-api/nhl-stats-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/opoKfaPDjItHxuREQ/builds/Oe6RGcvTq9b7gPAmf/openapi.json
