Do AI Agents Dream of Pickleball Rallies

The App

The Problem

I play pickleball a few times a week. My local indoor facility uses an online booking platform for court reservations, and the prime time slots — 6:30 to 8:00 PM — get snatched up fast. My membership only lets me see availability 7 days in advance, which means every week I'm racing to book exactly when the window opens. Miss it by a few minutes and the best courts are gone.

It's the kind of task that shouldn't require human attention. Open the app. Check Court #11. If it's taken, check #12. Then #13. Keep going down my list until I find one that's open for at least 90 minutes. Book it. Done.

But a human doing this takes several minutes of tapping through the app, and the window closes fast. Other members are doing the same thing at the same time. It's competitive and tedious.

I wanted a machine to do it for me.

Why This Was Harder Than It Sounds

The booking platform doesn't have a public API. There's no developer portal, no API keys, no documentation. If you're a member, you use their app or website. That's it.

A human booking a court goes through roughly these steps:

  1. Open the app
  2. Navigate to the scheduler
  3. Select the date (7 days out)
  4. Check each court one by one
  5. Find an open slot that's at least 90 minutes
  6. Fill out the booking form
  7. Submit and hope nobody beat you to it

Simple enough for a person. But for a script? You'd need to know how the login works, how availability is checked, how the booking form is submitted, and what all the hidden tokens and IDs mean. None of that is documented anywhere.

This is where most people would give up. I had an AI agent on my home server and some time on my hands.

The First Attempt: Browser Automation

The obvious approach — just automate the browser. Open a headless Chrome, navigate to the booking site, log in, click around, book the court.

It failed immediately.

The platform's main web app sits behind Cloudflare bot protection. Every time our headless browser tried to load the login page, it got stopped at the Cloudflare challenge. We upgraded browsers, tweaked fingerprints, tried everything. None of it mattered.

Here's the thing about Cloudflare: it checks your IP reputation first, before it even looks at your browser. Our home server runs on a datacenter IP, and Cloudflare flags those automatically. No amount of browser stealth fixes that.

Lesson one: When Cloudflare says no, it's the IP talking, not the browser.

The Second Attempt: Intercepting the Traffic

If I couldn't use a browser, I'd go around it. I wanted to understand what the booking app was actually doing under the hood — what calls was it making when I browsed the scheduler and booked a court?

I set up a traffic interception proxy on my server and configured my phone's Wi-Fi to route through it. Now every request my phone made flowed through the proxy, and I could see everything.

There was one catch: Android apps ignore user-installed CA certificates. So the booking app's traffic was invisible to me. But Chrome on Android trusts user certificates, and the mobile website uses the same backend. Good enough.

I spent an afternoon browsing through the booking website on my phone while the proxy captured everything. After a few sessions and many gigabytes of captured traffic, I had a clear picture of how the platform worked.

Lesson two: When the front door is locked, check the windows.

The Breakthrough

While analyzing the captured traffic, I found something unexpected. The platform doesn't have just one server — it has several, and they don't all have the same security.

The main web app and mobile app sit behind Cloudflare. But there's another server that handles login, availability checking, and portal access — and it has no bot protection at all.

This was the key. We could log in, check availability, and get the tokens we needed — all through a server that wasn't blocking us. No browser needed. No proxy subscription. Just regular HTTP requests.

Lesson three: Large platforms are rarely consistent about security. Find the weak link.

The Hard Truth About "Availability"

With the login working and tokens in hand, I thought the hard part was over. It wasn't.

The platform has endpoints that look like they check availability. You send a request with a court ID and time, and it returns the available durations — 30 minutes, 60 minutes, 90 minutes. Perfect, right?

Except those endpoints lie.

They return the same durations whether a court is fully booked or completely empty. I tested it at 5 AM, when the facility is closed. I tested it on courts I knew were taken. Same answer every time. Those endpoints only return reservation type rules — like "this membership allows 30, 60, or 90 minute bookings" — not whether the court is actually free.

We also tried the scheduler endpoint that returns events. It only shows group activities — not individual member reservations. So Court #11 could show as wide open when every slot was already booked.

The only reliable way to check if a court is available? Try to load the booking form for that specific court and time. If the form loads, the slot is open. If the page returns an error — "this court has already been reserved" or "restricted to 1 reservation per day" — the slot is taken.

That's not an API. That's a web page. But it's the only thing that tells the truth.

Lesson four: When the API lies, the form page tells the truth.

The Booking: It's a Form, Not an API Call

Here's something that surprised me: the actual booking isn't a modern JSON API call. It's an old-school web form submission — the kind with a CSRF token, hidden fields, and an encrypted token pulled from the portal page.

There's also a step-based JSON flow that looks like it handles the booking — Steps 1 through 6. But that's analytics and tracking. It doesn't create the reservation. The form does.

Lesson five: Not every endpoint does what it looks like it does. Sometimes the old way is the real way.

With all the pieces figured out, I built a web app with a dashboard. It runs on my home server and does the following every morning:

  1. Logs in and grabs the necessary tokens
  2. Goes through each court in my priority order (Court #11 first, then #12, #13, and so on)
  3. For each court, attempts to load the booking form for the target time
  4. If the form loads, the slot is available — it extracts the security token and submits the booking
  5. If the form returns an error, moves to the next court
  6. Sends me a Discord notification with the result

There's a short delay between each court check. The platform recently released bot detection features that specifically flag "high volumes of reservation attempts" and "actions in fractions of a second." I don't want to look like a bot — I just want my court.

The app has a dashboard where I can see booking history, view logs, test notifications, and adjust my schedule. It runs as a systemd service that starts on boot.

My membership only allows one reservation per day, so once the app books a court, it stops. No need to keep checking.

What Would a Human Do?

If I didn't have this automation, here's what my morning would look like:

  1. Set a reminder for when the 7-day window opens
  2. Open the booking app
  3. Navigate to the date I want
  4. Tap on Court #11, check the time slot
  5. If it's taken, back out, tap Court #12
  6. Repeat for each court
  7. Hope I'm fast enough
  8. If I get one, fill out the form and book
  9. If I don't, try again tomorrow

This takes 3-5 minutes if everything goes smoothly. But if the app is slow, or I'm busy at that exact moment, or I forget — the prime slots are gone. And I do this every week.

The automation does it in seconds, at the exact right time, without forgetting, and sends me a confirmation on Discord. I don't even have to think about it.

What I Learned

AI as a coding partner

I didn't write this alone. Tom — my AI coding agent running on my home server through OpenClaw — did the heavy lifting on the code side. I'd describe what I wanted and where to look, and Tom would explore the platform, test endpoints, write the code, and debug the failures. When the availability endpoint turned out to be unreliable, Tom was the one who tested every option until we found the form-page approach that actually works. I directed the project, made the strategic calls, and decided which rabbit holes were worth going down. Tom executed.

This is the real value of AI agents for automation projects. Not that they replace the thinking — but they accelerate the exploration. A human reverse-engineering a platform would need to manually test each endpoint, document the findings, and iterate. An AI agent can do that in hours instead of weeks, while you focus on the strategy.

Consistency is more important than cleverness

The most reliable part of this whole system isn't some clever hack. It's the boring approach of loading a web form and checking if it returns an error. Sometimes the simplest path is the one that actually works.

Every platform has gaps

Cloudflare protects the front door, but the side entrance is wide open. The availability endpoint exists but doesn't tell the truth. The booking is a form submission, not a JSON call. These aren't bugs — they're the natural inconsistency of a large, evolving platform. If you're patient enough to explore, you'll find the path of least resistance.

The Result

Every morning at 7 AM, the automation checks the courts for the following week's prime time slot. It runs through my priority list, finds the best available court, books it, and lets me know.

I still play pickleball. I just don't fight for courts anymore.


This project was built with Tom, an OpenClaw AI agent. If you're interested in automating the mundane parts of your life with AI, check out OpenClaw.