cz.basketball Schedule Watcher
Pricing
Pay per usage
cz.basketball Schedule Watcher
Watches a cz.basketball team's fixtures for schedule changes (new/moved/cancelled games, time & venue changes) and optionally syncs them to Google Calendar. Sends email and webhook notifications on every change.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Zdeněk Kunčar
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
CBF.cz Schedule Watcher
Watches a team's fixtures on cz.basketball and tells you when the schedule changes: a game gets moved, the venue changes, a game is postponed/cancelled, or a brand-new fixture appears. Optionally mirrors the fixtures into a Google Calendar so your team's games just show up — and stay correct — without anyone re-typing anything.
Built for BASKET OPAVA 2010 by default, but works for any team in any Czech basketball league:
just change the teamId input.
How it works
cz.basketball doesn't have a stable per-season schedule URL — the competition ID (/soutez/5376)
changes every year when the league restarts. What is stable is the team ID (/tym/13093),
with the season selected via a ?y= query parameter (?y=2026 = the 2026/27 season).
Each run, the Actor:
- Fetches
https://cz.basketball/tym/{teamId}?y={year}to get the list of this season's fixtures. - Fetches each fixture's detail page (
/zapas/{id}) for the authoritative date, time, and venue. - Diffs the result against the snapshot saved from the previous run.
- Reports anything that changed — new games, reschedules, venue changes, postponements/cancellations, and games dropped from the schedule.
- Optionally emails you (via Gmail), POSTs a webhook, and/or creates/updates/deletes the matching Google Calendar events.
- Saves the new snapshot for next time.
If year is left empty, the Actor auto-detects the current season (it rolls over every August), so
it keeps working next year and the year after without any changes to the input.
Finding your team's ID
- Go to cz.basketball and open your team's page (via your league's standings/competition page, or search).
- The team ID is the number in the URL:
https://cz.basketball/tym/13093→teamId = "13093".
Input
| Field | Required | Default | Description |
|---|---|---|---|
teamId | yes | 13093 (BASKET OPAVA 2010) | The cz.basketball team ID. |
teamName | yes | BASKET OPAVA 2010 | Display name used in calendar events and notifications. |
year | no | auto-detected | Season start year (the ?y= value). Leave empty so the Actor tracks the current season automatically, forever. |
skipPastGames | no | true | Ignore fixtures already in the past. |
notifyEmail | no | — | Get an email summary when something changes, sent via Gmail from your connected Google account (see setup below). Can be any address. |
webhookUrl | no | — | POST a JSON payload of the changes to your own endpoint, Zapier, Make, a Slack incoming webhook, etc. |
notifyOnFirstRun | no | false | On the very first run every fixture looks "new" (no prior snapshot exists). Leave off to seed silently. |
dryRun | no | false | Detect and report changes but never write to Google Calendar. |
Google account (optional)
Connecting a Google account is entirely opt-in. If you leave the fields below empty, the Actor works purely as a change detector: it still diffs the schedule and still sends webhook notifications. The same Google account powers two independent, separately-toggled features:
- Calendar sync — mirrors fixtures into Google Calendar. Requires
enableCalendarto be turned on. - Email notifications — sends the change summary via Gmail. Requires
notifyEmailto be set.
You only need to do the OAuth setup once even if you use both — a single refresh token authorizes both.
| Field | Description |
|---|---|
enableCalendar | Turn on to mirror fixtures into Google Calendar. |
googleCalendarId | primary for your main calendar, or a specific calendar's ID. Only used when Calendar sync is on. |
googleClientId / googleClientSecret | OAuth 2.0 credentials from Google Cloud Console. |
googleRefreshToken | A long-lived refresh token (see setup below). |
eventDurationMinutes | How long each game event should last (default 120). Calendar sync only. |
If enableCalendar is on but any of the three Google credential fields is missing, the Actor logs a
warning and skips calendar sync for that run. Likewise, if notifyEmail is set without the Google
fields, it logs a warning and skips the email. Neither will crash the run.
One-time Google OAuth setup
-
In Google Cloud Console, create (or pick) a project and enable the Google Calendar API and the Gmail API.
-
Under APIs & Services → Credentials, create an OAuth client ID of type Desktop app.
-
Under OAuth consent screen, add your own Google account as a Test user (unless the app is published/verified).
-
Clone this repo locally, install dependencies (
npm install), then run:$GOOGLE_CLIENT_ID=<your client id> GOOGLE_CLIENT_SECRET=<your client secret> npm run get-tokenThis opens a consent URL in your terminal — open it in a browser, approve access, and the script prints your
googleClientId,googleClientSecret, andgoogleRefreshToken. The token is authorized for both Calendar and Gmail send access. -
Paste those three values into the Actor's input (mark the secret and refresh token fields as secret in Apify Console), then turn on
enableCalendarand/or setnotifyEmailas needed.
The refresh token doesn't expire under normal use, so this is a one-time setup. If you'd previously
generated a refresh token before email notifications used Gmail, re-run npm run get-token to get a
new one that also covers the Gmail scope — the old one won't have permission to send email.
Output
Every run that detects changes pushes one dataset row per change, with the change type
(added, removed, rescheduled, venue_changed, opponent_changed, status_changed), a
human-readable summary, the affected match's details, and (for updates) the previous values.
Scheduling
Run this Actor on a schedule (Apify Console → Schedules) — a few times a day is plenty for a weekly amateur league; tighten it up if your league tends to announce changes close to game time.
Local development
npm installapify run # reads storage/key_value_stores/default/INPUT.jsonnpm test # unit tests against saved real HTML fixtures — no network required
Notes on the source site
- cz.basketball is server-rendered HTML with no public API, so this Actor scrapes it directly with Cheerio (no browser needed — fast and light).
- The site displays
00:00as a placeholder when a game's kickoff time hasn't been announced yet; the Actor treats that as "time TBD" rather than a literal midnight game, and will correctly report it as a schedule update once a real time is announced. - All crawled HTML is treated as untrusted input and parsed defensively — nothing scraped is ever executed or interpolated into commands.