A Node.js CLI scrapper that tracks available doctor appointments on Doctolib and sends notifications via Telegram (optional). Works for any city, specialty, or search filter 🌍✨
- 🏙️ Track multiple cities at once
- 👨⚕️ Works for any specialty or search filter (
availabilitiesBefore,insuranceSector,regulationSector, etc.) - 📅 Notifies about new appointment slots per city
- 🔁 Avoids duplicate alerts using persistent state storage
- 🚫 Blacklist specific agenda IDs you don't want to be notified about
- 💬 Optional Telegram notifications
- 🖥️ Fully automated in the CLI
- 🤖 Handles rate limiting and page errors gracefully with automatic retries
- Node.js v20+
- npm
- Telegram account (optional)
- Clone the repo:
git clone https://github.com/besquiros/doctolib-scrapper.git
cd doctolib-scrapper- Install dependencies:
npm install- Create a
.envfile (ignored by git):
TELEGRAM_TOKEN=your_bot_token_here
CHAT_ID=your_chat_id_here
# Optional: comma-separated agenda IDs to silence
BLACKLISTED_AGENDA_IDS=123456,789012If you skip .env, the scraper will just log updates in the terminal.
Edit SEARCH_URLS in index.js to track any search:
const SEARCH_URLS = [
"https://www.doctolib.fr/search?keyword=dermatologue&location=toulouse&availabilitiesBefore=14",
"https://www.doctolib.fr/search?keyword=dermatologue&location=bordeaux&availabilitiesBefore=14",
];Works for any city, specialty, or Doctolib filter — just copy a search URL directly from the Doctolib website.
The scraper groups notifications by city & specialty.
npm start
# or
node index.jsIt will:
- Launch a headless browser for each search URL
- Scrape JSON endpoints for available appointment slots
- Compare with
doctolib_state.jsonto avoid duplicates - Send one Telegram message per city/specialty with all new slots
- Repeat every 8–12 minutes (randomized to avoid rate limits)
To silence a specific doctor/agenda, add their agenda ID to your .env:
BLACKLISTED_AGENDA_IDS=123456,789012The agenda ID appears in every console/Telegram notification: (agenda 123456).
Blacklisted slots are still logged to the console but never sent to Telegram.
The blacklist is re-read every cycle — no restart needed after editing .env.
- Create a Telegram bot with @BotFather
- Copy the bot token →
.env TELEGRAM_TOKEN - Send a message to your bot once, then check your chat ID:
https://api.telegram.org/bot<token>/getUpdates - Paste chat ID in
.env CHAT_ID
Docker avoids Node version issues and runs the scraper in an isolated environment.
# Build
docker build -t doctolib-scrapper .
# Run
docker run -d --env-file .env --restart unless-stopped doctolib-scrapper
⚠️ Running on a VPS may not work — VPS IPs are often blocked by Cloudflare.
doctolib-scrapper/
├── index.js # Main scraper script
├── doctolib_state.json # Auto-generated, tracks notified slots
├── package.json
├── Dockerfile
├── .env # Telegram token & chat ID (gitignored)
└── README.md
Console:
🩺 TOULOUSE | DERMATOLOGUE
🔗 https://www.doctolib.fr/search?keyword=dermatologue&location=toulouse&availabilitiesBefore=14
🚨 New slots:
- jeudi 5 mars 2026 à 09:45 (agenda 1653547)
- jeudi 5 mars 2026 à 11:45 (agenda 1653547)
⏱ Next check in 10 minutes
Blacklisted agenda:
🚫 [TOULOUSE | DERMATOLOGUE] 3 slot(s) blacklisté(s) ignorés (agendas: 129685)
- You can use any valid Doctolib search URL, including filters like
insuranceSector,regulationSector, etc. - To keep it running continuously outside Docker: use
pm2,screen, ortmux - Never share your
.envordoctolib_state.jsonpublicly — they are user-specific
This project is provided for educational and personal use only 🧑💻📚.
- Do not use this scraper for commercial purposes or to overload Doctolib's servers.
- The author is not responsible for any misuse of this tool.
- Always respect the Terms of Service of Doctolib.
Use responsibly and at your own risk
MIT — free to use, modify, and share