[Tuto] Scruter le prochain rdv Doctolib disponible

Bonjour,
Je vous propose ci-dessous de détailler comment obtenir via le plugin script la date et l’heure du prochain rendez-vous disponible sur l’agenda Doctolib chez un praticien.
On commence très logiquement par la fin :slight_smile: en vous montrant le résultat :

Ensuite au choix :
Méthode 1, la plus rapide pour ceux qui maîtrisent la console de développement.
On commence donc par naviguer habituellement sur Doctolib jusqu’à la page qui affiche les créneaux (ou le message qui indique qu’il n’y en a pas justement). Un retour arrière pour revenir à la page précédente, on ouvre la console de développement et on scrute ce qui apparaît dans l’onglet « network » ou « réseau » quand on clique à nouveau sur le choix de type de rdv. La console doit alors afficher un item de type Json.


C’est justement cette url json qui nous intéresse puisque si vous le recopiez dans la barre d’adresse vous obtiendrez la liste des créneaux dispos (ou pas) en forme brute:

On y retrouve le nombre de créneau dispo sur les 2 prochains jours, les horaires des creneaux en question si il y en a, et la date et heure du prochain créneau dispo si il n’y en a pas dans les 2 jours.
Il reste alors à récupérer dans cette url les 3 éléments qui vont nous servir dans le script :

  • visit_motive_ids qui correspond au type de consultation que vous souhaitez
  • agenda_ids : le numéro de l’agenda du praticien (il peut aussi y en avoir plusieurs en les groupant avec des tirets
  • practice_ids : item lié à l’agenda ci-dessus.

Vous pouvez alors passer à la Dernière Étape ci-dessous

Méthode 2: à tâtons via les json.
Première étape: identifier le « slug-name » du praticien c’est à dire l’alias qui apparaît dans l’URL Doctolib de son profil. Par exemple pour ce praticien choisi au hasard en naviguant sur le site « https://www.doctolib.fr/gastro-enterologue/bordeaux/alain-castinel?pid=practice-194708 » son slug-name sera « alain-castinel ».
Il faut ensuite ouvrir l’URL « https://www.doctolib.fr/online_booking/api/slot_selection_funnel/v1/info.json?profile_slug=XXXXX » en remplaçant évidemment les XXX par le slug-name identifié précédemment. On tombe alors sur une page au format json que je vous conseille de traiter via un décodeur json pour pouvoir récupérer trois items numériques :

  • visit_motive_ids qui correspond au type de consultation que vous souhaitez
  • agenda_ids : le numéro de l’agenda du praticien (il peut aussi y en avoir plusieurs en les groupant avec des tirets
  • practice_ids : item lié à l’agenda ci-dessus.

On peut alors tester ces IDs en les utilisant dans l’URL suivant : https://www.doctolib.fr/availabilities.json?visit_motive_ids=xxxxx&agenda_ids=yyyyyy&practice_ids=zzzzzz&telehealth=false&limit=2&start_date=2025-05-27 qui doit alors afficher un json de ce type :


On y retrouve le nombre de créneau dispo sur les 2 prochains jours, les horaires des creneaux en question si il y en a, et la date et heure du prochain créneau dispo si il n’y en a pas dans les 2 jours.

Dernière étape : utiliser un script pour utiliser ces 3 ids
J’ai créé un code python pour extraire le premier créneau dispo (j’ai essayé plusieurs manières dont un script json mais ça ne fonctionne pas, voir ce post).

Voici donc le script en question, il appelle en argument les trois ids récupérés précédemment, et retourne le prochain créneau dispo au format dd/mm/yy HH:mm.

#!/usr/bin/python3

import requests
import json
from datetime import datetime
import sys

def format_slot(slot):
    """Formate un créneau horaire en chaîne lisible."""
    if slot:
        try:
            slot_datetime = datetime.strptime(slot, "%Y-%m-%dT%H:%M:%S.%f%z")
            return slot_datetime.strftime("%d/%m/%Y %H:%M")
        except ValueError:
            print("Format de date/time invalide !")
            return None
    else:
        print("Aucun créneau disponible.")
        return None

def get_next_slot(visit_motive_ids, agenda_ids, practice_ids):
    base_url = "https://www.doctolib.fr/availabilities.json"
    start_date = datetime.now().strftime('%Y-%m-%d')
    url = (f"{base_url}?visit_motive_ids={visit_motive_ids}"
           f"&agenda_ids={agenda_ids}&practice_ids={practice_ids}"
           f"&telehealth=false&limit=2&start_date={start_date}")
    
    headers = {
        'User-Agent': 'Mozilla/5.0'
    }
    
    response = requests.get(url, headers=headers)
    
    if response.status_code == 200:
        data = response.json()

        # Si total est nul → aucun créneau du tout
        if data.get('total', 0) == 0:
            next_slot= data.get('next_slot')
            return format_slot(next_slot)

        # Cherche le premier créneau non vide dans availabilities
        for day in data.get('availabilities', []):
            slots = day.get('slots', [])
            if slots:
                # retourne le premier créneau formaté
                return format_slot(slots[0])

        # Aucun slot trouvé malgré total > 0
        return "aucun creneau"
    else:
        print(f"Erreur lors de la requête : {response.status_code}")
        return None

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: python script.py <visit_motive_ids> <agenda_ids> <practice_ids>")
        sys.exit(1)

    visit_motive_ids = sys.argv[1]
    agenda_ids = sys.argv[2]
    practice_ids = sys.argv[3]

    slot_result = get_next_slot(visit_motive_ids, agenda_ids, practice_ids)
    if slot_result:
        print(slot_result)

Il reste donc à appeler ce script dans le plugin avec les trois id en argument, comme sur le premier screenshot de ce post, avec un rafraichissement auto de votre choix.
Évidemment, ce script seul n’est pas forcément suffisant, mais on peut ensuite imaginer des scénarios qui compare ce prochain créneau avec une date de votre choix pour vous alerter si un créneau plus proche se débloque !

PS: merci à @vicnet pour l’idée et avoir fourni l’URL utile via ce post.

11 « J'aime »

Edit du jour : en fait si il y a un slot disponible dans les 15 jours prochains, l’item « next_slot » n’apparait pas dans le json donc mon code ne marche plus :clown_face:. Je dois l’améliorer pour récupérer soit le slot dispo dans la liste, soit le next_slot !

Edit su jour : script modifié pour récupérer soit le le next_slot soit le premier créneau listé.
J’ai aussi modifié l’URL pour n’afficher que 2 jours au lieu de 15, ça ne me servait pas.

Edit du jour : ajout de la méthode 1 qui devient la plus simple en utilisant la console de dev pour récupérer directement le Json et identifier les IDs nécessaires !