Skip to main content

Fetch PWHL game schedules from the HockeyTech API

Project description

CI

pwhl-client

Fetch PWHL game schedules from the HockeyTech API. A Python library and CLI tool for developers who want structured, validated schedule data from the Professional Women's Hockey League without dealing with raw API responses.


Install

pip install pwhl-client

Quick start — library

Single date (defaults to today):

from pwhl_client import get_schedule

games = get_schedule()
print(games.to_dict())

Specific date:

from datetime import date
from pwhl_client import get_schedule

games = get_schedule(start=date(2026, 3, 15))
print(games.to_dict())

Date range with timezone:

from datetime import date
from zoneinfo import ZoneInfo
from pwhl_client import get_schedule

games = get_schedule(
    start=date(2026, 3, 15),
    end=date(2026, 3, 22),
    tz=ZoneInfo("America/New_York"),
)
for game in games.games:
    print(game.home_team, "vs", game.visiting_team, "@", game.game_datetime)

Quick start — CLI

# Today's games
pwhl-client

# Specific date
pwhl-client 2026-03-15

# Specific date with timezone
pwhl-client 2026-03-15 --tz America/New_York

Configuration

PWHL_API_KEY defaults to the current known public value embedded in the PWHL website's JavaScript. You only need to set it if the key rotates.

# .env file (recommended)
PWHL_API_KEY=your_new_key_here

# or shell export
export PWHL_API_KEY=your_new_key_here

PWHL_CLIENT_CODE is hardcoded as "pwhl" — it is a fixed league identifier on the HockeyTech platform and is not user-configurable.


Output shape

ScheduleResult.to_dict() returns:

{
  "fetched_at": "2026-03-15T19:00:00+00:00",
  "game_count": 1,
  "games": [
    {
      "game_id": "12345",
      "game_status": "scheduled",
      "home_team": "Boston Fleet",
      "home_team_id": "1",
      "visiting_team": "Minnesota Frost",
      "visiting_team_id": "2",
      "venue": "Tsongas Center",
      "city": "Lowell",
      "game_datetime": "2026-03-15T19:00:00-04:00",
      "game_date": "2026-03-15",
      "home_goal_count": null,
      "visiting_goal_count": null
    }
  ]
}

game_status is one of "scheduled", "in_progress", "completed", or "unknown". game_datetime is always timezone-aware and stored in the timezone passed to get_schedule(). game_date is the calendar date the game is played, taken directly from the API's local game date — independent of timezone conversion. home_goal_count and visiting_goal_count are null for pre-game entries.


Exceptions

pwhl-client raises the following exceptions:

  • PWHLAPIError — raised on network failure, timeout, or a non-2xx HTTP response from the HockeyTech API.
  • PWHLParseError (subclass of PWHLAPIError) — raised when the API returns a response that cannot be parsed or does not match the expected shape.
  • ValueError — raised when start is after end.

Catch PWHLAPIError to handle both API and parse failures in one place:

from pwhl_client import get_schedule, PWHLAPIError

try:
    result = get_schedule()
except PWHLAPIError as e:
    print(f"Could not fetch schedule: {e}")

Known bugs and fixes

python -m pwhl_client.cli silently returned no output (v0.1.0)

Symptom: Running python -m pwhl_client.cli <date> exited with code 0 but printed nothing, even when games existed.

Root cause: cli.py defined main() but had no if __name__ == "__main__": main() guard, so the module ran as a script with no entry point. Additionally, __main__.py was absent, so python -m pwhl_client was also broken.

Fix: Added if __name__ == "__main__": main() to cli.py and created __main__.py to delegate to cli.main().


Today's games missing when end == today (v0.1.0)

Symptom: Calling get_schedule() or get_schedule(start=date.today()) returned no games even when games were scheduled or in progress for that day.

Root cause: The HockeyTech scorebar endpoint uses numberofdaysahead to control how far forward it looks. When end == today, numberofdaysahead was computed as 0, which caused the API to exclude games scheduled later the same day.

Fix: When end >= today, numberofdaysahead is incremented by 1 to ensure the full current day is included. Results are still filtered to the requested date range after fetching.

Playoff games silently dropped for late-evening starts (v0.1.1)

Symptom: Calling get_schedule(start=date(2026, 4, 30)) returned 0 games despite a completed playoff game on that date (Ottawa @ Boston, Tsongas Center).

Root cause: The date filter compared game_datetime.date() — the game's start time converted to UTC — against the requested date. A game starting at 8 PM EDT is midnight UTC, so its UTC date is the next calendar day. The filter for April 30 therefore silently excluded it. The same issue affects any game starting at or after 8 PM Eastern time when queried in the default UTC timezone.

Fix (v0.1.2): Added a game_date field to Game that stores the calendar date extracted from the API's GameDateISO8601 string before any timezone conversion (i.e., the date the game is actually played at the arena). The filter in get_schedule() now uses game_date instead of game_datetime.date(). The game_date field is also included in to_dict() output.


Data source

Game data is fetched from the HockeyTech/LeagueStat API, the undocumented backend that powers thepwhl.com. The API has been reverse-engineered and documented by the community — see the PWHL Data Reference repository for full details on available endpoints and parameters.


License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pwhl_client-0.1.2.tar.gz (14.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pwhl_client-0.1.2-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file pwhl_client-0.1.2.tar.gz.

File metadata

  • Download URL: pwhl_client-0.1.2.tar.gz
  • Upload date:
  • Size: 14.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pwhl_client-0.1.2.tar.gz
Algorithm Hash digest
SHA256 695f3df8cd9f880a7f6b555131135dacb4ac3afb97be10f715636767627eb749
MD5 3243092635d632386f96868e325109c6
BLAKE2b-256 46c475ca95809b6329fe4beb0b437cde3cb035bf1dfa98561c30b5dd433cb384

See more details on using hashes here.

Provenance

The following attestation bundles were made for pwhl_client-0.1.2.tar.gz:

Publisher: publish.yml on jgalloway42/pwhl-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pwhl_client-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: pwhl_client-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 10.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pwhl_client-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 64e42e44f5699f46ffc83534a09453a0177f5c457017e7b6dd65a0626c37bbc7
MD5 2b032d47be57e3577d9c006762e45159
BLAKE2b-256 69b4a9bcdaa6661471636868c187bff523341a71eb5ba5db41732f5c753f661a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pwhl_client-0.1.2-py3-none-any.whl:

Publisher: publish.yml on jgalloway42/pwhl-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page