{"description":"Searches Doctolib Germany for practitioners and practices by specialty and city, for public (GKV) or private (PKV) insurance: name, specialty, address, link, whether new patients are accepted, video consultation, and the ids (visit motive, agendas, practice) that doctolib.de/get-slots needs.","effect":"read","id":"doctolib.de/search-practitioners","keywords":["doctolib","arzt","arzttermin","termin buchen","hautarzt","hausarzt","zahnarzt","facharzt","praxis","doctor","doctor appointment","book appointment","medical"],"output":{"schema":{"properties":{"city":{"type":"string"},"insurance_sector":{"type":"string"},"page":{"type":"integer"},"practitioners":{"items":{"properties":{"accepts_new_patients":{"type":["boolean","null"]},"address":{"type":["string","null"]},"agenda_ids":{"items":{"type":"integer"},"type":"array"},"city":{"type":["string","null"]},"kind":{"enum":["practitioner","practice"]},"languages":{"type":"array"},"name":{"type":"string"},"practice_id":{"type":["integer","string","null"]},"profile_id":{"type":["integer","string","null"]},"specialty":{"type":["string","null"]},"url":{"format":"uri","type":"string"},"video":{"type":"boolean"},"visit_motive_id":{"description":"For get-slots; null when no online booking for this specialty","type":["integer","null"]},"visit_motive_name":{"type":["string","null"]},"zip":{"type":["string","null"]}},"type":"object"},"type":"array"},"specialty":{"description":"Doctolib specialty actually used","type":"string"},"total":{"type":"integer"}},"required":["total","practitioners"],"type":"object"},"value":"{specialty: steps.kw.name, city: params.city, insurance_sector: params.insurance_sector, total: steps.search[0].total, page: params.page, practitioners: steps.search[0].items}"},"params":{"additionalProperties":false,"properties":{"city":{"description":"City, e.g. 'Berlin', 'München', 'Frankfurt am Main'","maxLength":60,"minLength":2,"type":"string"},"insurance_sector":{"default":"public","description":"public = gesetzlich (GKV), private = privat (PKV)","enum":["public","private"],"type":"string"},"page":{"default":0,"description":"0-based, 20 per page","maximum":20,"minimum":0,"type":"integer"},"specialty":{"description":"Specialty in German, e.g. 'Hautarzt', 'Hausarzt', 'Zahnarzt', 'Kinderarzt'","maxLength":60,"minLength":2,"type":"string"}},"required":["specialty","city"],"type":"object"},"provenance":{"method":"browser-inspect","notes":"spikes/doctolib.md. Search API (Spring service) needs the complete window.place object from the SSR search page (~1.6 MB); a partial place gives nationwide results without error, so it is cut out of the inline script (ends with '};window.searchType') and sent as raw JSON in a text body. Unknown specialty slugs make /search redirect to / (the extension reports a redirect error). No CSRF, cookies or custom headers for reads; Cloudflare in front did not challenge. Status 206 is success.","recorded_at":"2026-11-07T12:12:00+01:00","recorded_by":"C4"},"requires_login":false,"schema":"https://wield.run/schema/recipe/v1.json","site":{"country":"DE","id":"doctolib.de","language":"de","login_url":"https://www.doctolib.de/auth/patient_de","name":"Doctolib","origin":"https://www.doctolib.de","origins":["https://www.doctolib.de"]},"steps":[{"description":"Free text to Doctolib's specialty slug.","expect":{"assert":"length(body.searchEntries[?kind=='SPECIALITY']) > `0`","content_type":"json","status":[200]},"extract":{"json":{"name":"searchEntries[?kind=='SPECIALITY'] | [0].name","slug":"searchEntries[?kind=='SPECIALITY'] | [0].slug"}},"id":"kw","request":{"body":{"type":"json","value":{"query":"{{params.specialty | lower}}"}},"headers":{"Accept":"application/json","Content-Type":"application/json"},"method":"POST","url":"/patient-health-search/api/v1/autocomplete"}},{"description":"The search page embeds the place object the search API needs (window.place = {...}; in an inline script). The single-item foreach only computes the city slug (umlauts transliterated).","expect":{"assert":"contains(body, 'window.place = {')","content_type":"html","status":[200]},"extract":{"html":{"scripts":{"all":true,"selector":"script:not([src])"}}},"foreach":{"as":"loc","in":"[{slug: lower(replace(replace(replace(replace(replace(replace(replace(replace(trim(params.city), 'ü', 'ue'), 'Ü', 'ue'), 'ö', 'oe'), 'Ö', 'oe'), 'ä', 'ae'), 'Ä', 'ae'), 'ß', 'ss'), ' ', '-'))}]","max":1},"id":"place","parse":"html","request":{"headers":{"Accept":"text/html"},"method":"GET","query":{"keyword":"{{steps.kw.slug}}","location":"{{loc.slug}}"},"url":"/search"}},{"description":"Practitioner search. Answers 206. The full place object is spliced in as raw JSON (a partial place silently returns nationwide results). Single-item foreach cuts the object out of the script text.","expect":{"assert":"body.total != null","content_type":"json","status":[200,206]},"extract":{"json":{"items":"healthcareProviders[].{name: join(' ', [title || '', firstName || '', name][?@ != '']), kind: type == 'ORGANIZATION' && 'practice' || 'practitioner', specialty: speciality.name, address: location.address, zip: location.zipcode, city: location.city, url: join('', ['https://www.doctolib.de', link]), profile_id: references.id, practice_id: references.practiceId, visit_motive_id: matchedVisitMotive.visitMotiveId, visit_motive_name: matchedVisitMotive.name, agenda_ids: matchedVisitMotive.agendaIds || onlineBooking.agendaIds || `[]`, accepts_new_patients: matchedVisitMotive.allowNewPatients, video: onlineBooking.telehealth == `true`, languages: languages || `[]`}","total":"total"}},"foreach":{"as":"p","in":"[{place: join('', [split(split(steps.place[0].scripts[?contains(@, 'window.place = {')] | [0], 'window.place = ')[1], '};window.')[0], '}'])}]","max":1},"id":"search","request":{"body":{"type":"text","value":"{\"keyword\":\"{{steps.kw.slug}}\",\"location\":{\"place\":{{p.place}}},\"filters\":{\"insuranceSector\":\"{{params.insurance_sector}}\"}}"},"headers":{"Accept":"application/json","Content-Type":"application/json"},"method":"POST","query":{"page":"{{params.page}}"},"url":"/patient-health-search/api/v1/hcp/search"}}],"task":"Search doctors on Doctolib by specialty and city","tos":{"notes":"Doctolib's terms prohibit automated access and scraping. One user-initiated search at a time from the user's own browser (3 requests). Health-related searches are sensitive: results stay on the user's device.","reviewed":false},"verify":{"checks":["output.total > `20`","length(output.practitioners) > `5`","length(output.practitioners[?city == 'Berlin']) > `10`","starts_with(output.practitioners[0].url, 'https://www.doctolib.de/')","length(output.practitioners[?visit_motive_id != `null`]) > `0`"],"example_params":{"city":"Berlin","specialty":"Hautarzt"},"max_ms":8000},"version":1}