# Doctoralia & Jameda Scraper - Doctors, Clinics & Reviews (`s-r/doctoralia-scraper`) Actor

Export doctors and clinics from Doctoralia, jameda, MioDottore, ZnanyLekarz and DoktorTakvimi: specialties, addresses, coordinates, ratings, consultation prices and optional patient reviews. For healthcare lead lists, directories and market research.

- **URL**: https://apify.com/s-r/doctoralia-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 doctor or clinics

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Doctoralia Scraper

Doctoralia Scraper exports public doctor and clinic listings, consultation prices and
patient reviews from Doctoralia, jameda, MioDottore, ZnanyLekarz, DoktorTakvimi and
ZnamyLekar: eleven DocPlanner country sites in one actor. Use it to build healthcare
lead lists and directories, compare specialties across cities, analyse public
reputation or size a local healthcare market from information the source publishes.

The results include names, specialties, addresses, coordinates, ratings and review
counts. You can also request profile details and patient reviews. Doctors and clinics
are returned as place rows; each patient review is a separate review row connected to
its doctor or clinic. This makes the dataset usable in spreadsheets and databases
without unpacking a nested review collection.

### Use cases for a Doctoralia scraper

- **Healthcare lead generation.** Build a list of dermatologists in Madrid, dentists in
  Munich or cardiologists in Rome with practice address, published phone number,
  consultation price and online booking status, ready for a CRM import.
- **Healthcare marketing and agencies.** Find practices with many reviews but no online
  booking, or with a low rating, and tailor an offer to them.
- **Market analysis.** Count doctors per specialty and city, compare consultation prices
  between cities and countries, and see how many professionals are verified or bookable.
- **Reputation monitoring.** Collect patient reviews and professional replies for a set
  of profiles and compare ratings over time using stable ids.
- **Directories and data products.** Feed a doctor directory or a medical-tourism
  comparison site with geocoded practices across several countries.

### Doctoralia Scraper country coverage

Choose Spain, Mexico, Brazil, Italy, Poland, Germany, Türkiye, Chile, Colombia, Peru or
Czechia. The supported brands are Doctoralia, MioDottore, ZnanyLekarz, jameda,
DoktorTakvimi and ZnamyLekar. A country code selects the site for a specialty and city
search. When you provide a search or profile URL, its country takes precedence for
that URL. A single run can therefore contain URLs from several supported countries.

Enter the specialty and city in the local language. For example, use `Dermatólogo`
and `Madrid` for Spain, `Zahnarzt` and `München` for Germany, or `Kardiyoloji` and
`Ankara` for Türkiye. The search box accepts specialties, conditions and services.
Searching a person's name as a specialty may return no results, even if that doctor
has a public profile. Use their profile URL when you already know it.

### Input

Provide `country`, `specialty` and `city`, or supply `search_urls`, `profile_urls`,
or both. The default search is Dermatólogo in Madrid. Search URLs can point to a
specialty listing or the site's search page. Profile URLs must point to public doctor
or clinic profiles on one of the supported sites.

```json
{
  "country": "es",
  "specialty": "Dermatólogo",
  "city": "Madrid",
  "max_items": 100,
  "include_sponsored": true,
  "include_facilities": true,
  "include_details": false,
  "include_reviews": false
}
```

`max_items` limits the number of unique doctors and clinics across the whole run,
from one to ten thousand. It does not count review rows. Promoted cards and clinics
are included by default. Disable `include_sponsored` to remove promoted cards, or
disable `include_facilities` to collect doctors only. Repeated cards are deduplicated
using the country, entity type and original source id.

Set `include_details` to read the available profile information for each listing.
Set `include_reviews` to collect patient reviews, then choose
`max_reviews_per_place`, between one and one thousand. Profile URL input reads the
profile directly and includes the details it publishes. Large runs continue
automatically across pages; you do not need to handle continuation tokens in Apify.

### Output

Each dataset row carries `row_type` and `_type`, both either `place` or `review`.
Every row also includes a collection timestamp and the source country and entity id.
The stable `place_id` joins a place to its reviews, including when multiple countries
are collected in the same run.

Place rows include the published professional or clinic name, profile URL, the main
specialty in `category`, all listed specialties in `categories`,
rating, total review count, booking availability and consultation price. The
`addresses` collection preserves multiple locations, their coordinates and their
published service prices. The first physical address also populates the main
address and location fields. Online-only doctors may have no physical address.

Prices are numeric amounts with an ISO currency code. The original wording remains
in `price_text`; `price_is_from` distinguishes a starting price from a fixed price.
A service explicitly described as free has a price of zero. An unavailable price
stays empty. German and Turkish listing cards commonly omit consultation prices,
so the actor does not infer an amount for those cards.

Available profile details include a public phone number, postal code, registration
number, services, payment methods, languages and biography. Fields depend on what
the professional has published. `details_fetched` indicates that the profile was
successfully read, even if a particular optional field was absent. The actor does
not search external sources for personal email addresses or missing contact data.

Review rows include the source review id, place name and URL, rating, review text,
public author name, date wording, verification badge and a professional reply when
present. Anonymous author names remain empty. Dates are returned as calendar dates
with day precision. If a local date cannot be interpreted, the original wording is
preserved and the run reports a warning. Review text retains published line breaks.

#### Example output

A place row from a real `profile_urls` request for a Madrid doctor with reviews
enabled, shortened to the most used fields:

```json
{
  "row_type": "place",
  "name": "Dr. Ricardo Moreno Alonso De Celada",
  "place_id": "es:doctor:88918",
  "url": "https://www.doctoralia.es/ricardo-moreno-alonso-de-celada/dermatologo-dermatologo-infantil/madrid",
  "country": "es",
  "brand": "Doctoralia",
  "categories": ["Dermatólogo", "Dermatólogo infantil"],
  "address": "Calle de Fray Bernardino Sahagún 9, Madrid, 28036",
  "city": "Madrid",
  "lat": 40.4607315,
  "lng": -3.6810911,
  "rating": 5,
  "reviews_count": 436,
  "price": 140,
  "currency": "EUR",
  "price_text": "140 €",
  "has_online_booking": true,
  "details_fetched": true,
  "postal_code": "28036"
}
```

A review row from the same run, linked to the place by `place_id`:

```json
{
  "row_type": "review",
  "review_id": "2127635",
  "place_id": "es:doctor:88918",
  "place_name": "Dr. Ricardo Moreno Alonso De Celada",
  "rating": 5,
  "text": "Buena atención, el tratamiento y las recomendaciones le han ido excelentes a mi bebe.",
  "author_name": "E.C",
  "published_at": "2026-10-01",
  "date_text": "1 de octubre de 2026",
  "is_verified": true,
  "verification_text": "Cita verificada",
  "reply_text": null
}
```

A clinic row from a real `profile_urls` request for a Madrid clinic. Clinic profiles
return every specialty the clinic lists; `category` holds the main specialty:

```json
{
  "row_type": "place",
  "name": "Clínica Thuban",
  "place_id": "es:facility:45500",
  "url": "https://www.doctoralia.es/clinicas/clinica-thuban",
  "entity_type": "facility",
  "country": "es",
  "brand": "Doctoralia",
  "category": "Medicina familiar y comunitaria",
  "categories": [
    "Medicina familiar y comunitaria",
    "Medicina general",
    "Dermatología",
    "Medicina del deporte",
    "Medicina estética",
    "Medicinas y terapias complementarias",
    "Fisioterapia",
    "Osteopatía",
    "Acupuntura",
    "Homeopatía",
    "Nutrición y dietética"
  ],
  "address": "Avenida de Brasilia 3-5, Madrid 28028",
  "rating": 5,
  "reviews_count": 850,
  "has_online_booking": true,
  "details_fetched": true
}
```

### Pricing

The current Apify pricing panel is the authoritative source for event prices.
The actor distinguishes a run start, a delivered place, a delivered review and a
place whose profile details were successfully fetched. Profile details and reviews
are optional for search results, so you can control the work requested before
starting a run. Direct profile input includes a successfully read profile.

Empty search results produce no place, review or profile-detail charges. An
explicit run-start fee may still apply according to the pricing panel. A free
user receives at most ten dataset rows in total; reviews count toward that row cap.
Detail counts are based on places actually delivered, including after the free
delivery cap. Repeated cards across pages do not create duplicate result charges.

### How this Doctoralia scraper compares

Most doctor scrapers in the Store cover one site or one country: Doctoralia Brazil,
Doctoralia Spain or jameda alone. This actor covers all eleven DocPlanner country sites
with one input format and one output format, so a German jameda export and a Mexican
Doctoralia export can be merged without remapping columns.

| | This actor | Typical single-site scraper |
|---|---|---|
| Sites | Doctoralia (6 countries), jameda, MioDottore, ZnanyLekarz, DoktorTakvimi, ZnamyLekar | One site |
| Input | Specialty + city, search URL or profile URL, mixed countries per run | Usually URLs only |
| Prices | Numeric amount, ISO currency and original text, per address | Often text only |
| Reviews | Separate rows with stable ids and professional replies | Nested or not available |
| Empty searches | No result charges | Varies |

### Reliability and result limits

Doctor and clinic counts depend on the selected specialty, city and source site.
Some cities have few matches. Listing order, sponsored placements and public
ratings can change between collections. Consultation prices describe the service
shown by the site and should be treated as published information rather than a
guaranteed quote for every appointment.

The run summary reports delivered rows, partial status and warnings. An unavailable
profile or review page does not silently turn into complete data: the warning
explains the missing phase. Existing place results can still be delivered. A search
with no matching doctors returns an empty dataset. Use smaller review limits for
quick directory exports and larger limits when reputation analysis is the goal.

### FAQ

#### Can I collect doctors from several countries in one run?

Yes. Supply search or profile URLs from the supported country sites. Each row keeps
its own country and source site, and the country-qualified place id prevents
different countries' source ids from colliding.

#### Does max_items include patient reviews?

No. It limits unique places. Reviews are additional rows controlled by
`include_reviews` and `max_reviews_per_place`. The free delivery allowance counts
all dataset rows, including reviews.

#### Why are a phone number, price or address sometimes empty?

The professional may not publish that information. Search cards do not contain
every profile field, so enable details when you need the additional published
information. An online-only doctor may have no physical address. A missing price
is never replaced with an estimated amount.

#### Does it work for jameda, MioDottore and ZnanyLekarz?

Yes. Choose the country (`de`, `it`, `pl`, `tr`, `cz` and others) or paste a search or
profile URL from that site. All brands return the same row format.

#### Does the actor return email addresses?

No. It returns what the doctor or clinic publishes on their profile, such as a phone
number, address and services. It does not guess or look up personal email addresses.

#### Can I use the same ids for repeated exports?

Yes. Place ids combine country, entity type and source id. Review ids are the
source's review identifiers. Together with collection timestamps, these fields
support joins and comparisons between exports; the actor does not claim to track
every historical edit or removed review automatically.

# Actor input Schema

## `country` (type: `string`):

Country used for specialty and city searches; explicit URLs determine their own country.

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

Specialty, condition or service in the local language of the selected site. Names of doctors are not specialty searches.

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

City in the local language of the selected site.

## `search_urls` (type: `array`):

Listing or search URLs on supported DocPlanner sites. A page parameter sets the starting page.

## `profile_urls` (type: `array`):

Public doctor or clinic profile URLs. The profile request also returns available details.

## `max_items` (type: `integer`):

Maximum unique doctors and clinics across all input URLs. Review rows are additional.

## `include_sponsored` (type: `boolean`):

Include promoted cards once per doctor or clinic.

## `include_facilities` (type: `boolean`):

Include clinics and practices alongside doctors.

## `include_details` (type: `boolean`):

Fetch profile details such as phone, registration number, postal code, services and languages.

## `include_reviews` (type: `boolean`):

Return patient reviews as separate rows linked to their place.

## `max_reviews_per_place` (type: `integer`):

Maximum reviews for each delivered doctor or clinic, used when include_reviews is enabled.

## `cursor` (type: `string`):

Continuation token returned by a previous request. Keep all other input fields identical.

## Actor input object example

```json
{
  "country": "es",
  "specialty": "Dermatólogo",
  "city": "Madrid",
  "search_urls": [],
  "profile_urls": [],
  "max_items": 100,
  "include_sponsored": true,
  "include_facilities": true,
  "include_details": false,
  "include_reviews": false,
  "max_reviews_per_place": 10
}
```

# Actor output Schema

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

Doctor, clinic and optional review rows.

## `summary` (type: `string`):

Delivery counts, partial status and warnings.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/doctoralia-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("s-r/doctoralia-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 '{}' |
apify call s-r/doctoralia-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/doctoralia-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/0ahsXes98d8eVhQUM/builds/clWFAxkQTq4POHTcL/openapi.json
