# 🩺 Jameda Scraper - German Doctor Leads & Contacts (`benthepythondev/jameda-scraper`) Actor

Scrape German doctor profiles from jameda.de — Germany's #1 medical directory with 1.6M+ professionals. Extract name, specialty, address, phone, ratings. Perfect for healthtech, B2B medical lead-gen, market research.

- **URL**: https://apify.com/benthepythondev/jameda-scraper.md
- **Developed by:** [Ben](https://apify.com/benthepythondev) (community)
- **Categories:** Lead generation, Other, Business
- **Stats:** 3 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $24.00 / 1,000 doctors

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## 🩺 Jameda Scraper — German Doctor Leads, Practice Contacts & Market Data

Extract **structured doctor profiles from jameda.de** — Germany's #1 medical directory
with 1.6M+ medical professionals. Search by specialty, city and district, and get back
clean records with name, title prefix, specialty and sub-specialties, full practice
address, phone numbers in international format, insurance types, languages and review
counts. It's built for healthtech, B2B medical lead generation and market research, and
it bypasses jameda's anti-bot with TLS impersonation plus a German residential proxy —
no headless browser needed. Export to JSON/CSV/Excel, run on a schedule, call via API, or connect to Make, Zapier or n8n.

### 🩺 What is the Jameda Scraper?

It turns any jameda.de search into a structured contact dataset. Give it a medical
specialty (Fachgebiet) and a German city — optionally a district — or paste exact jameda
listing URLs, and the actor paginates the results, parses each doctor card, and (by
default) visits every profile to pull the full practice details. Under the hood it uses
`curl-cffi` Chrome TLS impersonation, a homepage warm-up, automatic re-warmup on blocks
and a German residential proxy, because jameda blocks datacenter and non-German IPs at the
network level. The result: a ready-to-use list of medical practices with contact and
credential data for outreach, provider databases or analysis.

#### What data does it extract?

For every doctor card on the listing pages:

- **Name and title prefix** (`name`, `title_prefix` — e.g. Dr. med., Prof.)
- **Specialty and sub-specialties** (`specialty`, `sub_specialties`)
- **Sponsored flag** (`is_sponsored`) and **review count** (`review_count`)
- **Profile slug & URL** (`slug`, `url`) plus your search context (`search_specialty`, `search_city`) and `scraped_at`

With **`fetchDetails: true`** (the default, strongly recommended) each profile is visited
and the record is enriched with: **practice name** (`practice_name`), **full address**
(`address`) parsed into **street**, **plz**, **city** and **district**, **all phone
numbers** (`phones`) plus a normalized **primary phone** in `+49…` format
(`primary_phone`), **insurance types** (`insurance_types`), **languages** (`languages`),
optional **website** and **opening hours text**.

> The listing page alone is sparse (name + specialty + review count), so keep
> `fetchDetails: true` for usable B2B data. Patient reviews and the star rating value
> (rendered client-side) are intentionally not scraped; the review count is captured.

### ⬇️ Input

Run it two ways — search a specialty + city, or pass exact jameda URLs:

| Field | Description |
|-------|-------------|
| `specialty` | Medical specialty slug (Fachgebiet), e.g. `zahnarzt`, `hautarzt`, `orthopaede`, `frauenarzt`, `kinderarzt`, `kardiologe` |
| `city` | German city slug, lowercase, e.g. `berlin`, `muenchen`, `hamburg`, `koeln`, `frankfurt` |
| `district` | Optional district within the city, e.g. `mitte`, `kreuzberg` |
| `startUrls` | Direct jameda.de listing URLs (overrides `specialty` + `city` + `district`) |
| `fetchDetails` | Visit each profile for address, phones, insurance, languages (default `true`, recommended) |
| `maxResults` | Max doctors to scrape (0 = unlimited, default 50, max 5000) |
| `delaySeconds` | Polite delay between requests (1–10, default 2.0 — jameda is rate-limit strict) |
| `proxyConfiguration` | **Required**: German residential proxy (default) |

#### Example input

```json
{
  "specialty": "zahnarzt",
  "city": "berlin",
  "district": "mitte",
  "fetchDetails": true,
  "maxResults": 50,
  "delaySeconds": 2.0
}
```

### ⬆️ Output

Every doctor is one clean row (view as a **table**, or export **JSON / CSV / Excel**):

```json
{
  "slug": "kurdin-alsolivany",
  "url": "https://www.jameda.de/kurdin-alsolivany/zahnarzt/berlin",
  "name": "Kurdin Alsolivany",
  "title_prefix": "Dr. med. dent.",
  "specialty": "Zahnärztin",
  "sub_specialties": ["Parodontologie", "Ästhetische Zahnmedizin", "Implantologie"],
  "is_sponsored": false,
  "review_count": 173,
  "search_specialty": "zahnarzt",
  "search_city": "berlin",
  "scraped_at": "2026-06-26T16:00:00+00:00",
  "practice_name": "Zahnarztpraxis Dr. Kurdin Alsolivany",
  "address": "Schönhauser Str. 17, 1.OG, Steglitz, 12157 Berlin",
  "street": "Schönhauser Str. 17",
  "plz": "12157",
  "city": "Berlin",
  "district": "Steglitz",
  "phones": ["030 7957784", "030 79782088"],
  "primary_phone": "+49307957784",
  "insurance_types": ["Gesetzliche Krankenkassen", "Selbstzahler"],
  "languages": ["Deutsch", "Englisch"]
}
```

> `practice_name`, `address`, `street`, `plz`, `city`, `district`, `phones`, `primary_phone`, `insurance_types` and `languages` are only present when `fetchDetails: true`.

### 💡 Use cases

- **🎯 Medical B2B lead generation:** build targeted lists of practices by specialty and city for medical equipment, software, consulting or services outreach.
- **🏥 HealthTech provider databases:** populate booking platforms, EMR integrations or "find a doctor" tools with structured practice data per region.
- **📊 Market & density research:** analyze specialty distribution, practice density and review counts across German cities and districts.
- **🗂️ CRM & data enrichment:** enrich healthcare contacts with verified practice names, addresses, phones and insurance acceptance.

### ❓ FAQ

**How do I scrape doctors from jameda.de?** Enter a `specialty` slug (e.g. `zahnarzt`)
and a `city` slug (e.g. `berlin`), optionally a `district`, then Run. With the default
`fetchDetails: true` you get full practice profiles with address, phones and insurance.

**Why is a German residential proxy required?** jameda.de blocks datacenter and non-German
IPs at the network level, returning instant 403s. The German residential proxy is
preconfigured by default so requests come from an accepted IP.

**Why should I keep `fetchDetails` on?** The listing page only contains name, specialty
and review count. `fetchDetails: true` (the default) visits each profile to add address,
phone numbers, insurance types and languages — the data that makes the dataset useful.

**Can I get phone numbers?** Yes — with `fetchDetails` on, each record includes all listed
`phones` plus a normalized `primary_phone` in international `+49…` format.

**Can I get doctor email addresses?** No — jameda hides email behind a contact form and
does not publish addresses publicly. Phone and practice address are the available contact
channels.

**Are patient reviews or star ratings included?** Only the review count is captured. Full
review text is not scraped, and the star-rating value is rendered client-side in React, so
it is not part of the output.

**Do I need an API key?** No API key for jameda is required. You just need an Apify
account; the German residential proxy is built into the default input.

**How many doctors can it return, and how do I avoid blocks?** Up to your `maxResults`
cap (0 = unlimited, max 5000). Keep `delaySeconds` at 2.0 or higher — jameda is rate-limit
strict — and the actor auto-retries with session re-warmup on blocks.

**Can I run it on a schedule or via API?** Yes — schedule recurring runs in Apify, call
it via the API/SDK, or connect it to Make, Zapier or n8n for automated pipelines.

**Is scraping jameda legal?** It extracts publicly listed practice profile data only.
Treat contact data as business data, handle it in a GDPR-compliant way for any outreach,
and follow applicable laws and jameda's terms. Patient reviews are not scraped.

### 🔗 You might also like

- **[Anwalt.de Scraper](https://apify.com/benthepythondev/anwalt-de-scraper)** — German lawyers directory (same premium B2B tier)
- **[Business Contact Scraper](https://apify.com/benthepythondev/business-contact-scraper)** — company contacts & B2B leads
- **[Gelbe Seiten Scraper](https://apify.com/benthepythondev/gelbe-seiten-scraper)** — German Yellow Pages business listings
- **[Smart Email Finder & Verifier](https://apify.com/benthepythondev/smart-email-finder-verifier)** — find and validate business emails

***

**Keywords:** jameda scraper, German doctor directory, medical practice data, doctor contact scraper, healthtech leads, medical B2B lead generation, German doctors data, practice address phone, specialty doctor scraper, healthcare market research, provider database Germany, find a doctor data, medical directory scraper, German B2B leads, doctor practice contacts.

# Actor input Schema

## `specialty` (type: `string`):

Specialty slug as used on jameda.de (e.g., 'zahnarzt', 'hautarzt', 'orthopaede', 'frauenarzt', 'kinderarzt', 'augenarzt', 'hno-arzt', 'kardiologe', 'urologe', 'neurologe', 'psychotherapeut', 'allgemeinarzt', 'internist'). Required unless startUrls provided.

## `city` (type: `string`):

German city slug, lowercase (e.g., 'berlin', 'muenchen', 'hamburg', 'koeln', 'frankfurt'). Required unless startUrls provided.

## `district` (type: `string`):

Optional district within the city (e.g., 'mitte', 'kreuzberg', 'schoeneberg' for Berlin).

## `startUrls` (type: `array`):

Direct jameda.de listing URLs (overrides specialty + city + district).

## `fetchDetails` (type: `boolean`):

Visit each doctor profile for full address, phone numbers, opening hours, full description. STRONGLY recommended for usable B2B data — listing page only contains name+specialty+review-count.

## `maxResults` (type: `integer`):

Maximum doctors to scrape (0 = unlimited, default 50).

## `delaySeconds` (type: `number`):

Polite delay between HTTP requests (default 2s, jameda has stricter rate-limits than most).

## `proxyConfiguration` (type: `object`):

REQUIRED: Apify DE residential proxy. jameda.de blocks all datacenter and non-DE IPs.

## Actor input object example

```json
{
  "specialty": "zahnarzt",
  "city": "berlin",
  "startUrls": [
    "https://www.jameda.de/zahnarzt/berlin"
  ],
  "fetchDetails": true,
  "maxResults": 50,
  "delaySeconds": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "DE"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "specialty": "zahnarzt",
    "city": "berlin"
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/jameda-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "specialty": "zahnarzt",
    "city": "berlin",
}

# Run the Actor and wait for it to finish
run = client.actor("benthepythondev/jameda-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "specialty": "zahnarzt",
  "city": "berlin"
}' |
apify call benthepythondev/jameda-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,benthepythondev/jameda-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/eRXV88PrE1Vq87RT2/builds/V5xp3GGZeltFGlUce/openapi.json
