How to Automate Gym Reservations with Selenium: A Google Engineer’s Design Doc

This article explains how a Google engineer designed and implemented an automated system using Python and Selenium to book gym slots two days in advance, detailing problem definition, requirements, architecture, code snippets, and operational workflow for reliable, headless execution on macOS.

Programmer DD
Programmer DD
Programmer DD
How to Automate Gym Reservations with Selenium: A Google Engineer’s Design Doc

Problem Description

During the COVID‑19 pandemic gyms required limiting on‑site members, and users had to reserve a spot online at least two days in advance, starting at midnight. The author needed a way to make a reservation for an early‑morning swimming pool slot without staying up until midnight.

Requirements

Automatically make a reservation two days ahead at midnight.

Run without human interaction, be fault‑tolerant, and retry intelligently.

Operate on a Mac computer.

Allow users to specify username, password, sport, date, and time.

Out of scope:

Reservations only one day ahead or same‑day.

Tolerating OS or network failures.

Continuing after the reservation server stops.

Working after the website’s HTML structure changes.

Overview Design

Browser Automation vs. Simulated Requests

Browser automation controls a real browser via GUI, while simulated requests interact with the server via HTTP. The author chose browser automation because it provides visibility for debugging, handles JavaScript‑driven controls, and despite its dependence on HTML structure, the benefits outweigh the drawbacks.

System Overview

Selenium provides the browser automation library; the program is written in Python and uses Selenium’s Python API to drive Firefox via the Gecko driver. Caffeinate prevents the macOS from sleeping during midnight execution.

Detailed Design

User Input

Username, password, date, and other parameters are supplied via command‑line arguments.

Retry Logic

The program catches all exceptions (e.g., page not loaded) and retries up to 100 times until the reservation succeeds, detecting success by confirming a specific DOM element.

Browser Choice

After testing Chrome, Firefox, and Safari, Firefox was selected because it required the least additional setup with Selenium.

Logging

The script logs each action and the expected result, making debugging straightforward. The log cycle includes:

Finding an element.

Interacting with the element (input, select, click).

Waiting for the expected outcome and returning success.

Each log entry records what was performed and what was awaited.

Preventing Sleep

subprocess.Popen(['caffeinate', '-d', '-w', '%d' % os.getpid()])

Element Location

Selenium’s find_element_by_xpath is used to locate buttons and inputs, preferring internal text over class names for stability.

Waiting for Page Load

After each HTTP request, the script waits 2–5 seconds for the page to load using WebDriverWait. Example:

book_btn = WebDriverWait(driver, 120).until(
    EC.element_to_be_clickable((By.XPATH, "//button[@ng-reflect-router-link='/Appointments']"))
)

If the button does not appear within 120 seconds, an exception is raised.

Additional Implementation Details

Choosing the correct date cell requires handling cases where the target day belongs to the next month and ensuring the cell has the cal-in-month class. The script also adjusts the month view when the reservation date crosses a month boundary.

Operational Flow

To reserve the pool for April 14, run the following command on April 11:

python book.py --username xxxxxx --password xxxxxx --day 14 --time '5:00 PM' --sport small_pool

The program wakes every second to check the time, with Caffeinate keeping the system awake. At midnight on April 12, it launches Firefox, performs the reservation, then exits, allowing the OS to sleep normally. The user can review the logs the next morning to verify success.

Interesting Fact

Reservations fill up within the first minute, with only six slots per time slot, making early‑morning bookings extremely competitive.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonAutomationSchedulingWeb ScrapingSelenium
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.