# Practo Scraper (`automation-lab/practo-doctor-directory-scraper`) Actor

Search public Practo doctor directories by city and specialty. Export names, qualifications, clinics, fees, recommendations, reviews, and profile URLs.

- **URL**: https://apify.com/automation-lab/practo-doctor-directory-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Lead generation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.69 / 1,000 item extracteds

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

## Practo Scraper

Export public Practo doctor directory data by specialty and location.
Practo Scraper turns public city-and-specialty listings into structured doctor,
qualification, clinic, consultation fee, recommendation, review, and profile records.
Use it for provider-market research, directory enrichment, competitive analysis,
and repeatable spreadsheet or data-pipeline exports.

### What does Practo Scraper do?

The Actor searches public Practo directories using either:

- city and specialty pairs, such as `Bangalore` and `Cardiologist`; or
- public directory URLs, such as `https://www.practo.com/delhi/dentist`.

It follows directory pagination, removes duplicate doctor profiles, and writes one
normalized doctor record to the default Apify dataset for every accepted listing.
The default proxy setup is enabled because Practo does not consistently serve its
structured directory pages to direct cloud requests.

This Actor extracts public directory information. It does not book appointments,
log in to Practo, access patient information, or scrape private consultations.

### Who is it for?

- **Healthcare market researchers** comparing provider supply by city or specialty.
- **Clinic strategy teams** studying displayed fees and local competitive density.
- **Directory operators** enriching an existing provider database with public links.
- **Analysts** building reproducible specialty and location snapshots.
- **Developers** sending normalized Practo data into a warehouse or internal tool.
- **Operations teams** scheduling the same query and comparing datasets over time.

Choose this Actor when the source must be Practo and the unit of output is a doctor
listing. For official US provider identifiers, taxonomies, and licenses, use the
related NPI Registry actor instead.

### Why use this Actor?

- Search with readable city and specialty inputs.
- Accept supported Practo directory URLs directly.
- Return typed records instead of raw HTML.
- Preserve canonical profile and source URLs for traceability.
- Stop at a predictable global item limit.
- Deduplicate profiles across overlapping searches.
- Rotate bounded proxy sessions after blocked or transient responses.
- Export through the Apify API as JSON, CSV, Excel, XML, or RSS.
- Run manually, through an API, from a schedule, or with Apify integrations.

### What Practo doctor fields are extracted?

| Field | Meaning |
| --- | --- |
| `doctorName` | Doctor name displayed by Practo |
| `profileUrl` | Canonical public Practo profile URL |
| `specialty` | Displayed specialty |
| `qualifications` | Array of displayed qualifications |
| `experienceYears` | Years of experience, when shown |
| `clinicName` | Clinic or practice name |
| `clinicAddress` | Combined public clinic address |
| `locality` | Neighborhood or locality |
| `city` | Directory or clinic city |
| `consultationFee` | Displayed consultation fee |
| `currency` | `INR` when a fee is present |
| `recommendationPercent` | Practo recommendation percentage |
| `reviewCount` | Displayed patient review count |
| `isVerified` | Practo Prime or verification signal |
| `onlineConsultationAvailable` | Whether an online consultation action is shown |
| `sourceUrl` | Directory page where the record was found |
| `scrapedAt` | ISO timestamp for extraction |

Fields that Practo does not display for a listing are returned as `null` or an
empty array. Do not interpret a missing fee, qualification, or review count as zero.

### How to scrape Practo doctor directories

1. Open the Actor in Apify Console.
2. Add one or more city and specialty searches.
3. Alternatively, paste supported public Practo directory URLs.
4. Set `maxItems` to the maximum unique doctor records you need.
5. Keep the default proxy configuration unless you have tested another proxy pool.
6. Click **Start**.
7. Open the **Dataset** tab to inspect and export the records.
8. Save the task or add a schedule when you need repeatable snapshots.

A small first run is recommended. Confirm that Practo uses the expected city and
specialty path before increasing the result limit.

### Input parameters

#### `searches`

An array of city and specialty objects.
Names are normalized to lowercase URL slugs.
For example:

```json
{
  "searches": [
    { "city": "Bangalore", "specialty": "Cardiologist" },
    { "city": "Mumbai", "specialty": "Dermatologist" }
  ],
  "maxItems": 20
}
```

#### `startUrls`

An optional list of public Practo directory URLs.
Only HTTPS URLs on `practo.com` or `www.practo.com` with a city/specialty path
are accepted.

```json
{
  "startUrls": [
    { "url": "https://www.practo.com/delhi/dentist" }
  ],
  "maxItems": 10
}
```

#### `maxItems`

Global maximum number of unique doctor records.
Allowed range: 1 to 10,000.
The default is 50.
The Actor stops scheduling pages after reaching this limit.

#### `maxPagesPerSearch`

Safety limit for each city and specialty combination.
Allowed range: 1 to 100.
The default is 20.
Practo typically exposes ten doctor cards per directory page.

#### `proxyConfiguration`

Apify Proxy is enabled by default.
Practo may block direct server traffic, so disabling proxy access can cause a
clear run failure rather than an empty dataset.
Custom proxy URLs and Apify Proxy settings can be supplied through the standard
proxy editor.

### Example output

The following shape reflects the Actor's current normalized output.
Values vary with the public directory page.

```json
{
  "doctorName": "Dr. Example Kumar",
  "profileUrl": "https://www.practo.com/bangalore/doctor/example-kumar-cardiologist",
  "specialty": "Cardiologist",
  "qualifications": ["MBBS", "MD - General Medicine"],
  "experienceYears": 14,
  "clinicName": "Example Heart Clinic",
  "clinicAddress": "12 Sample Road, Indiranagar, Bangalore",
  "locality": "Indiranagar",
  "city": "Bangalore",
  "consultationFee": 800,
  "currency": "INR",
  "recommendationPercent": 96,
  "reviewCount": 215,
  "isVerified": true,
  "onlineConsultationAvailable": true,
  "sourceUrl": "https://www.practo.com/bangalore/cardiologist",
  "scrapedAt": "2026-01-15T12:00:00.000Z"
}
```

### How much does it cost to extract Practo doctor records?

The Actor uses pay-per-event pricing:

- a one-time **Start** event for each run; and
- an **Item processed** event for each doctor record saved.

The current base pricing starts at **$0.001 per run** plus the applicable
subscription-tier item price. At the BRONZE tier, the current item price is
**$0.001152 per doctor record**.

Example BRONZE totals before any platform-plan allowances:

| Records | Estimated Actor charge |
| ---: | ---: |
| 10 | $0.01252 |
| 100 | $0.11620 |
| 1,000 | $1.15300 |

Proxy and compute usage are included in the Actor's platform execution context;
the event total shown by Apify is the clearest estimate for a configured run.
Always check the pricing panel for the tier that applies to your account.

### Build a recurring provider-market workflow

A useful recurring workflow is:

1. Create one task per specialty market or use several searches in one task.
2. Keep the search input and item limit stable.
3. Schedule the task weekly or monthly.
4. Export each run's dataset to cloud storage or a warehouse.
5. Compare records by `profileUrl`.
6. Track additions, removals, displayed fee changes, or clinic changes downstream.

The Actor creates current snapshots. It does not calculate historical changes
inside a run, send alerts, or maintain a private longitudinal database.

### Export and integration options

Default dataset results can be downloaded in:

- JSON
- CSV
- Excel
- XML
- RSS

Common integrations include Google Sheets, Slack, Make, Zapier, webhooks, and
custom API clients. Use `profileUrl` as a stable practical deduplication key and
retain `scrapedAt` when combining several run snapshots.

### Run through the Apify API with cURL

Replace `YOUR_TOKEN` with your Apify API token:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~practo-doctor-directory-scraper/runs?token=YOUR_TOKEN&waitForFinish=300" \
  -H "Content-Type: application/json" \
  -d '{
    "searches": [{"city":"Bangalore","specialty":"Cardiologist"}],
    "maxItems": 10
  }'
```

Fetch dataset items from the `defaultDatasetId` returned by the run API.

### Run through the Apify API with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/practo-doctor-directory-scraper').call({
  searches: [{ city: 'Bangalore', specialty: 'Cardiologist' }],
  maxItems: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Run through the Apify API with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/practo-doctor-directory-scraper').call(run_input={
    'searches': [{'city': 'Delhi', 'specialty': 'Dentist'}],
    'maxItems': 10,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use Practo Scraper with MCP

Add the Apify MCP server to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/practo-doctor-directory-scraper"
```

#### Claude Desktop, Cursor, and VS Code setup

Claude Desktop, Cursor, and VS Code can use this equivalent MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=automation-lab/practo-doctor-directory-scraper"
    }
  }
}
```

Example prompts:

- “Find ten cardiologists listed on Practo in Bangalore.”
- “Export the Delhi dentist directory and summarize displayed fees.”
- “Collect dermatologist records for Bangalore and Mumbai as JSON.”

### Data quality and interpretation tips

- Treat fields as public listing claims, not independently verified credentials.
- Keep `sourceUrl` and `profileUrl` for auditability.
- Compare like-for-like specialties because Practo path naming affects results.
- Use explicit city names rather than metro-area assumptions.
- Missing values mean that the listing did not expose the field at extraction time.
- A recommendation percentage is not the same metric as an average star rating.
- Fees can vary by clinic, visit type, and time; the Actor returns the listing value.
- Deduplication happens by canonical doctor profile URL within one run.

### Limits and expected failure behavior

Practo controls the public directory and can change its response structure,
pagination, or anti-bot controls without notice.
The Actor retries transient failures with bounded proxy-session rotation.
If all attempts return blocked or unsupported content, it fails clearly instead
of reporting a misleading successful empty result.

Other limits:

- only public city/specialty directory pages are supported;
- doctor profile detail pages are not accepted as start URLs;
- appointment booking and logged-in areas are outside scope;
- naturally empty searches can produce zero records;
- `maxPagesPerSearch` can stop before the complete directory;
- public fields vary by listing and location;
- the Actor does not infer medical credentials or quality.

### Troubleshooting

#### The run says a proxy is required

Enable Apify Proxy in `proxyConfiguration` or supply working custom proxy URLs.
Direct cloud requests are not a reliable Practo route.

#### The run returns no records

Check that the city and specialty correspond to a real public Practo directory.
Open the generated city/specialty URL in a normal browser and test a small limit.
A valid but naturally empty directory can produce no items.

#### The start URL is rejected

Use an HTTPS city/specialty directory URL with exactly two path segments, such as
`https://www.practo.com/delhi/dentist`.
Profile URLs, search-engine URLs, query-only routes, and non-Practo domains are
rejected intentionally.

#### A larger run stops early

Review `maxItems`, `maxPagesPerSearch`, and Actor logs.
The source may expose fewer records than the requested maximum, and overlapping
searches may contain profiles removed by deduplication.

### Legality and responsible use

Use this Actor only for lawful purposes and public data you are permitted to
process. Review Practo's terms, applicable database rights, privacy obligations,
and medical-sector rules for your use case.

Do not use directory data for harassment, discrimination, deceptive outreach,
medical decision-making, or attempts to identify private patient information.
Apply data minimization, retention limits, access controls, and a valid legal
basis where personal data law applies. Honor deletion and correction requests
in downstream systems.

This Actor is an independent extraction tool and is not affiliated with,
endorsed by, or operated by Practo.

### Related Automation Lab actors

- [NPPES NPI Registry Provider Search](https://apify.com/automation-lab/npi-registry-provider-search) — official US provider identity, taxonomy, address, and license data.
- [India Hospitals & Pharmacies by PIN](https://apify.com/automation-lab/india-healthcare-directory-by-pin) — facility discovery by Indian postal code.
- [Healthgrades Doctors & Profiles Scraper](https://apify.com/automation-lab/healthgrades-doctors-profiles-scraper) — public US doctor and profile research from Healthgrades.

These are complementary sources. They do not replace Practo-specific city and
specialty listing data.

### FAQ

#### Does the Actor need a Practo login?

No. It processes public doctor directory pages and does not accept account cookies.

#### Can it scrape several cities or specialties in one run?

Yes. Add several objects to `searches`. The global `maxItems` limit applies across
all searches, while `maxPagesPerSearch` applies to each unique pair.

#### Does it scrape complete doctor profile pages?

No. The product normalizes fields exposed by public directory listings and returns
the canonical profile URL for traceability.

#### Can I schedule it to monitor a market?

Yes. Save the input as an Apify Task, add a schedule, and compare run datasets in
your own spreadsheet, database, or workflow. The Actor itself emits snapshots.

#### Are consultation fees guaranteed to be current?

No. They are the values displayed by Practo at extraction time and can change.

#### Why are some fields null?

Practo does not expose every field on every listing. Null values preserve that
difference instead of inventing data.

#### How are duplicate doctors handled?

Within a run, records sharing the same canonical `profileUrl` are saved once.

#### Can I turn off the proxy?

The input supports standard proxy configuration, but a working proxy is required
because direct cloud requests are not a reliable Practo route.

# Actor input Schema

## `searches` (type: `array`):

Directory searches to run. Use ordinary city and specialty names, for example Bangalore and cardiologist.

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

Optional public Practo city/specialty directory URLs such as https://www.practo.com/delhi/dentist.

## `maxItems` (type: `integer`):

Stop after saving this many unique doctor profiles across all searches.

## `maxPagesPerSearch` (type: `integer`):

Safety limit for each city and specialty combination. Practo normally exposes 10 doctors per page.

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

Apify Proxy is required because Practo blocks direct server requests. The default automatic proxy pool is the cost-efficient option.

## Actor input object example

```json
{
  "searches": [
    {
      "city": "Bangalore",
      "specialty": "Cardiologist"
    }
  ],
  "maxItems": 20,
  "maxPagesPerSearch": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Default dataset containing extracted Practo doctor records.

# 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 = {
    "searches": [
        {
            "city": "Bangalore",
            "specialty": "Cardiologist"
        }
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/practo-doctor-directory-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 = {
    "searches": [{
            "city": "Bangalore",
            "specialty": "Cardiologist",
        }],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/practo-doctor-directory-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 '{
  "searches": [
    {
      "city": "Bangalore",
      "specialty": "Cardiologist"
    }
  ],
  "maxItems": 20
}' |
apify call automation-lab/practo-doctor-directory-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/practo-doctor-directory-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/zUn99jZ2FvcXrMzli/builds/OSyMTb9r1G5Be1cow/openapi.json
