tj-pak — golf-booking-bot % cd ..

% open golf-booking-bot

Golf Booking Bot

Auto-books my weekly tee time the instant the slot opens.

automation live

PROBLEM

Tee times at my club open 7 days out at 06:22, and the good 9am slots vanish in minutes. Booking meant being awake refreshing a members' portal at dawn every week — for me and three regulars.

WHAT I BUILT

A bot that books the foursome automatically: logs in, waits for the sheet to open, grabs the slot closest to 9am, fills in all four players, and pays through to a finalised booking. Then it drops the round on my Google Calendar.

HOW IT WORKS

Pure Python + httpx — no browser, no CAPTCHA. It reads the real open time off the page countdown instead of trusting a fixed clock, so it self-corrects for weekends and daylight saving. When the sheet opens it polls hard until it lands a slot, then runs the club's confirm and finalise steps. Every run writes telemetry so a miss is debuggable.

WHERE IT'S AT

Live and recurring — books every Mon and Tue, 7 days out. Runs from an always-on VM in Sydney (jitter-free) with GitHub Actions as a free backup. Verified end-to-end on a real booking.

WHAT I LEARNED

The code was never the hard part — scheduler jitter was. A free cron fired 1h44 late once and blew the morning, even though the booking logic was perfect. Reliability of a small automation lives in the boring infrastructure around it, not the clever bit in the middle.

STACK

Python · httpx · GCP e2-micro VM (Sydney) · GitHub Actions · Google Calendar API

Live read of the club tee sheet — the bot logs in and picks the 9:06 slot. (Read-only inspect run; booking step omitted here.)
$ python booker.py inspect
[13:08:38] mode=inspect  target_date=2026-06-26  want=closest to 9:06
[13:08:39] Logged in.
[13:08:40] grid len=153686  tee-times=63  open=26
[13:08:40]     8:50  full
[13:08:40]     8:58  full
[13:08:40]     9:06  OPEN   ctl00$MainContent$book_47799528_3   <== would grab
[13:08:40]     9:14  OPEN   ctl00$MainContent$book_47799529_4
[13:08:40]     9:22  full
[13:08:40]     … 24 more open slots …
[13:08:40] Wrote run_summary.json (result=inspect)
Private repo — verified on a live booking.

% cd ..