← All work

Automation · Case study

DoctoAlerte

Never refresh Doctolib again

running in production doctoalerte.com ↗

The problem

This one started as my own problem. I needed a specialist appointment, and Doctolib's first availability was months away. Cancellations do free up earlier slots — but they're gone within minutes, and the only "strategy" is refreshing the page every day and still losing. So I built a robot to do the refreshing for me, then made it free for everyone with the same problem.

What I built

  • An alert is a city, a medical specialty, a date limit, and smart filters — Secteur 1 (no extra fees) and practitioners accepting new patients
  • Automatic checks every 15 minutes, around the clock
  • Exactly one email per alert, containing the direct booking link, the moment a matching slot appears — then the alert closes itself. No spam by design
  • Free, and deliberately minimal on data: an email address is all it needs

How it works

Rather than scraping HTML, DoctoAlerte talks to the same internal availability API that Doctolib's own frontend calls — mapped by reverse-engineering the network traffic. Structured JSON means precise matching on sectors, dates and availability, and far fewer breakages than parsing markup that can change any day.

  1. User creates an alert (city, specialty, filters, deadline)
  2. Hangfire recurring job ticks every 15 minutes
  3. Throttled batch queries Doctolib's availability API
  4. Results are matched against each alert's filters
  5. One email goes out with the direct booking link
  6. The alert closes itself

Being a polite guest is an architectural requirement here, enforced at two levels: per-user quotas cap how many alerts an account can run, and a global internal throttle spaces and batches every outgoing request, so the total traffic DoctoAlerte generates stays a small, steady fraction of ordinary browsing. Only active alerts are ever queried, and results are cached.

Scheduling is Hangfire recurring jobs on .NET; alerts and state live in SQL Server; sign-in is Google; notifications go out as transactional email. The UI is Blazor Server.

Hard problems

  • Working against an undocumented API: mapping it in the first place, then adapting quickly whenever it shifts underneath you.
  • Fitting every active alert inside a strict politeness budget in each 15-minute window — batching, spacing and prioritizing the checks.
  • Exactly-one-email semantics: deduplication so a slot that appears in several consecutive checks never alerts the same user twice.

Results & lessons

Users regularly find appointments in days that Doctolib listed as months away — at zero cost to them. And the constraint turned out to be the teacher: designing for restraint — scrape less, cache more, alert once — produced a better system than designing for scale would have.