# WebMD Doctor Scraper (`solidcode/webmd-scraper`) Actor

\[💰 $2.5 / 1K] Extract US doctors and physicians from WebMD — names, specialties, NPI, education, practice locations, phones, insurance accepted, ratings, and patient reviews. Search by specialty and location, or paste WebMD profile or search URLs.

- **URL**: https://apify.com/solidcode/webmd-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 doctor profiles

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/platform/actors/running/actors-in-store#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

## WebMD Doctor Scraper

Pull structured US doctor and physician data from WebMD's "Find a Doctor" directory at scale — full profiles, NPI numbers, specialties, practice locations with geocoordinates, accepted insurances, star ratings, and patient reviews. Search by specialty and location, or paste WebMD URLs, and get clean, ready-to-use rows instead of hand-copied profiles. Built for healthcare recruiters, medical directory and referral platforms, and market researchers who need reliable physician data without working through WebMD one profile at a time.

### Why This Scraper?

- **Search by specialty and location, no URLs required** — type "Cardiology" near "New York, NY" or a ZIP code and get matching doctors; the URL-only alternatives make you hand-build every search link.
- **National Provider Identifier (NPI) on every doctor** — the standard registry ID that keys straight into Medicare, claims, and credentialing systems.
- **Patient reviews as separate, linkable rows** — each review ships as its own record joined to its doctor by `doctorProviderId`, ready to drop into a spreadsheet — not buried in a nested array you have to unpack.
- **Category-level patient-experience scores** — per-question "did well" versus "needs improvement" counts with a computed positive-percent, alongside the overall star rating and total review count.
- **Full accepted-insurance lists** — every named plan a doctor takes, with a total count, plus new-patient, Medicare, and Medicaid acceptance flags.
- **Every practice location with geocoordinates** — name, street address, city, state, ZIP, formatted phone, and lat/lng for each of a doctor's offices, not just the primary one.
- **Complete education and credential trail** — medical school, degrees (MD, DO), each training institution with its graduation year, and total years in practice.
- **Hospital affiliations, languages, and direct contacts** — affiliated hospitals, languages spoken, practice website, and published contact emails where WebMD lists them.
- **Nationwide US coverage** — the entire WebMD "Find a Doctor" directory, from dense metros to rural ZIP codes.

### Use Cases

**Healthcare Recruiting & Staffing**

- Build targeted candidate lists of physicians by specialty and metro
- Screen by years in practice, medical school, and hospital affiliations
- Reach practices directly with published phone numbers and office emails
- Spot growth-ready practices by their new-patient availability

**Referral & Directory Building**

- Populate provider directories with NPI, specialties, and locations
- Keep referral networks current with ratings and accepted insurances
- Match patients to nearby in-network doctors using geocoordinates
- Enrich existing physician records with full WebMD profile details

**Market & Competitive Research**

- Map physician supply by specialty across cities and ZIP codes
- Analyze accepted-insurance coverage across a local market
- Compare average ratings and review volume between practices
- Study patient-experience scores by specialty or region

**Reputation & Review Monitoring**

- Track patient reviews and star ratings for a set of doctors
- Analyze category-level "did well" scores across a practice
- Surface highlighted reviews and recurring patient themes
- Benchmark a practice's ratings against local peers

**Lead Generation & Outreach**

- Build medical-practice contact lists with phone, website, and email
- Target doctors accepting new patients or a specific insurance plan
- Segment leads by specialty, location, and rating

### Getting Started

#### Search by Specialty and Location

The simplest way to start — one specialty and one place:

```json
{
    "specialty": "Cardiology",
    "location": "New York, NY"
}
```

#### Focused Run with Capped Reviews

Tighten the geography with a ZIP and limit reviews per doctor:

```json
{
    "specialty": "Dermatology",
    "location": "10016",
    "maxResults": 50,
    "includeReviews": true,
    "maxReviewsPerDoctor": 10
}
```

#### Doctors Only (Faster, Cheaper)

Skip reviews entirely when you only need doctor and practice details:

```json
{
    "specialty": "Family Medicine",
    "location": "Austin, TX",
    "maxResults": 200,
    "includeReviews": false
}
```

#### From WebMD URLs

Paste doctor profile URLs, search URLs, or a mix of both:

```json
{
    "startUrls": [
        "https://doctor.webmd.com/doctor/jane-smith-a1b2c3d4-e5f6-7890-abcd-ef1234567890-overview",
        "https://doctor.webmd.com/results?so=Cardiology&sc=New+York%2C+NY"
    ],
    "maxResults": 100
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `startUrls` | array | `[]` | WebMD URLs — individual doctor profile pages or directory search-result pages. The page type is detected automatically. The most precise way to get exactly the doctors you want. When set, specialty and location are ignored. |
| `specialty` | string | `"Cardiology"` | Medical specialty to search for, e.g. "Cardiology", "Dermatology", or "Family Medicine". Combined with the location below. Leave empty to browse all doctors near the location. |
| `location` | string | `"New York, NY"` | City and state (e.g. "New York, NY") or a ZIP code (e.g. "10016") to search near. Combined with the specialty above. |

#### Results

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Maximum number of doctors to collect across all URLs and searches. Set to 0 for no limit (a safety maximum of 1,000 still applies). Reviews are not counted against this limit. |
| `includeReviews` | boolean | `true` | Collect each doctor's patient reviews (rating, comment, date, category scores). Turn off for faster, cheaper runs when you only need doctor and practice details. |
| `maxReviewsPerDoctor` | integer | `20` | Maximum reviews to collect for each doctor. Set to 0 to collect all available (up to a safety maximum of 1,000). Only applies when Include Patient Reviews is on. |

### Output

The output has two record types — doctors and patient reviews — and every row is clearly labelled as one or the other. The Overview tab holds every record; the Doctors and Patient reviews tabs are clean, type-filtered subsets of the same run.

#### Doctor Record

```json
{
    "recordType": "doctor",
    "providerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "npi": "1234567890",
    "fullName": "Dr. Jane A. Smith, MD",
    "firstName": "Jane",
    "middleName": "A",
    "lastName": "Smith",
    "suffix": "MD",
    "gender": "F",
    "specialties": ["Cardiology", "Interventional Cardiology"],
    "degrees": ["MD"],
    "graduationYear": 2004,
    "yearsOfExperience": 21,
    "bio": "Dr. Jane Smith is a cardiologist in New York, NY with over 20 years of experience.",
    "profilePhoto": "https://img.wbmdstatic.com/doctor/jane-smith.jpg",
    "languages": ["English", "Spanish"],
    "medicalSchool": "Columbia University College of Physicians and Surgeons",
    "education": [
        { "type": "Medical School", "institution": "Columbia University College of Physicians and Surgeons", "graduationYear": 2004 },
        { "type": "Residency", "institution": "NewYork-Presbyterian Hospital", "graduationYear": 2007 }
    ],
    "hospitalAffiliations": ["NewYork-Presbyterian Hospital", "Mount Sinai Hospital"],
    "rating": 4.42,
    "reviewCount": 87,
    "textReviewCount": 41,
    "categoryRatings": {
        "question_1": { "didWell": 78, "needsImprovement": 9, "positivePercent": 89.7 }
    },
    "patientHighlights": ["Listens & answers questions", "Spends enough time with patients"],
    "careExperienceSummary": "Patients highlight clear explanations and short wait times.",
    "insurances": ["Aetna", "Cigna", "UnitedHealthcare", "Blue Cross Blue Shield"],
    "insuranceCount": 42,
    "acceptsNewPatients": true,
    "acceptsMedicare": true,
    "acceptsMedicaid": false,
    "practiceName": "Manhattan Cardiology Associates",
    "address": "115 E 61st St",
    "city": "New York",
    "state": "NY",
    "zipCode": "10065",
    "coordinates": { "lat": 40.7638, "lng": -73.9662 },
    "phone": "(212) 555-0134",
    "websiteUrl": "https://manhattancardiology.example.com",
    "locations": [
        {
            "practiceName": "Manhattan Cardiology Associates",
            "address": "115 E 61st St",
            "city": "New York",
            "state": "NY",
            "zipCode": "10065",
            "phone": "(212) 555-0134",
            "coordinates": { "lat": 40.7638, "lng": -73.9662 },
            "acceptsNewPatients": true,
            "acceptsMedicare": true,
            "acceptsMedicaid": false,
            "websiteUrl": "https://manhattancardiology.example.com"
        }
    ],
    "emails": ["office@manhattancardiology.example.com"],
    "profileUrl": "https://doctor.webmd.com/doctor/jane-smith-a1b2c3d4-e5f6-7890-abcd-ef1234567890-overview",
    "sourceUrl": "https://doctor.webmd.com/results?so=Cardiology&sc=New+York%2C+NY"
}
```

##### Identity & Specialty

| Field | Type | Description |
|-------|------|-------------|
| `recordType` | string | Always `"doctor"` for this record type |
| `providerId` | string | WebMD provider ID — the join key for linked reviews |
| `npi` | string | National Provider Identifier |
| `fullName` | string | Full display name |
| `firstName` | string | First name |
| `middleName` | string | Middle name or initial |
| `lastName` | string | Last name |
| `suffix` | string | Credential suffix (e.g. MD, DO) |
| `gender` | string | Doctor gender code — `"M"` or `"F"` |
| `specialties` | string\[] | All listed specialties |
| `degrees` | string\[] | Degrees held (e.g. MD, DO) |

##### Education & Credentials

| Field | Type | Description |
|-------|------|-------------|
| `medicalSchool` | string | Primary medical school |
| `education` | object\[] | Training history: `type`, `institution`, `graduationYear` |
| `graduationYear` | number | Year of primary graduation |
| `yearsOfExperience` | number | Total years in practice |
| `hospitalAffiliations` | string\[] | Affiliated hospitals |
| `languages` | string\[] | Languages spoken |
| `bio` | string | Profile biography |
| `profilePhoto` | string | Profile photo URL |

##### Ratings & Reviews Summary

| Field | Type | Description |
|-------|------|-------------|
| `rating` | number | Average patient rating on a 0–5 scale |
| `reviewCount` | number | Total number of patient ratings |
| `textReviewCount` | number | Number of reviews that include written text |
| `categoryRatings` | object | Per-question patient-experience scores with `didWell`, `needsImprovement`, and `positivePercent` |
| `patientHighlights` | string\[] | Highlighted "did well" themes from patients |
| `careExperienceSummary` | string | Short summary of the care experience |

##### Practice Locations

| Field | Type | Description |
|-------|------|-------------|
| `practiceName` | string | Primary practice or clinic name |
| `address` | string | Primary street address |
| `city` | string | Primary city |
| `state` | string | Primary state |
| `zipCode` | string | Primary ZIP code |
| `coordinates` | object | Primary `{ lat, lng }` |
| `phone` | string | Primary practice phone (formatted) |
| `websiteUrl` | string | Primary practice website |
| `acceptsNewPatients` | boolean | Whether the doctor accepts new patients |
| `acceptsMedicare` | boolean | Whether Medicare is accepted |
| `acceptsMedicaid` | boolean | Whether Medicaid is accepted |
| `locations` | object\[] | Every practice location with its own address, phone, coordinates, and acceptance flags |

##### Insurance & Contact

| Field | Type | Description |
|-------|------|-------------|
| `insurances` | string\[] | Named insurance plans accepted |
| `insuranceCount` | number | Total number of accepted plans |
| `emails` | string\[] | Published contact emails, when available |
| `profileUrl` | string | WebMD profile URL |
| `sourceUrl` | string | The search or profile URL this doctor came from |

#### Patient Review Record

Present only when Include Patient Reviews is on. Each review links back to its doctor via `doctorProviderId`, `doctorName`, and `doctorProfileUrl`.

```json
{
    "recordType": "review",
    "reviewId": "r-58213904",
    "doctorProviderId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "doctorName": "Dr. Jane A. Smith, MD",
    "doctorProfileUrl": "https://doctor.webmd.com/doctor/jane-smith-a1b2c3d4-e5f6-7890-abcd-ef1234567890-overview",
    "reviewerName": null,
    "rating": 5,
    "categoryRatings": { "criteria_2": 5, "criteria_3": 4 },
    "title": "Excellent",
    "text": "Dr. Smith took the time to explain every option and never rushed the visit.",
    "date": "2026-04-14T18:40:46Z",
    "isHighlighted": true,
    "helpfulCount": 6,
    "reply": null,
    "hasText": true
}
```

| Field | Type | Description |
|-------|------|-------------|
| `recordType` | string | Always `"review"` for this record type |
| `reviewId` | string | Unique review ID |
| `doctorProviderId` | string | Parent doctor's provider ID (join key) |
| `doctorName` | string | Parent doctor's name, for standalone context |
| `doctorProfileUrl` | string | Parent doctor's WebMD profile URL |
| `reviewerName` | string | Reviewer name (WebMD reviews are anonymous, so this is null) |
| `rating` | number | Overall review rating on a 0–5 scale |
| `categoryRatings` | object | Per-category scores for this review |
| `title` | string | Short review headline (e.g. "Excellent") |
| `text` | string | Full review body |
| `date` | string | Publish date, ISO 8601 UTC |
| `isHighlighted` | boolean | Whether WebMD highlighted the review |
| `helpfulCount` | number | Count of readers who marked it helpful |
| `reply` | string | Practice reply to the review, when present |
| `hasText` | boolean | Whether the review includes written text |

### Tips for Best Results

- **Use a ZIP code for tight geo-targeting** — "10016" pins results to one neighborhood, while "New York, NY" spans the entire metro. ZIP searches give cleaner, more local lists.
- **Use a recognized medical specialty** — "Cardiology", "Dermatology", or "Family Medicine" resolve cleanly; obscure or misspelled terms fall back to browsing all doctors near the location.
- **Cap reviews per doctor in high-volume metros** — popular doctors can have hundreds of reviews. A `maxReviewsPerDoctor` of 10–20 keeps runs fast, predictable, and lower cost.
- **Turn off Include Patient Reviews for a doctors-only run** — it skips review collection entirely when you only need profiles, locations, and insurance.
- **Start small, then scale** — set `maxResults` to 10–50 on your first run to confirm the data fits your needs, then increase.
- **Paste WebMD URLs for precise control** — profile URLs pull one exact doctor; search URLs re-run any filtered WebMD search. When you supply URLs, specialty and location are ignored.
- **Join reviews to doctors on `doctorProviderId`** — every review row carries its parent doctor's ID, name, and profile URL, so the two record types line up cleanly in a spreadsheet or database.

### Pricing

**Pay per result — from $2.50 per 1,000 doctors plus $0.50 per 1,000 reviews (Gold tier).** Reviews are priced about 5× lower than doctors because they are bulk child records. There are no compute or time-based charges — you pay per doctor and per review collected, plus a small fixed per-run start fee. Bronze, Silver, and Gold loyalty discounts apply automatically in the Console, with Gold the lowest.

#### Doctors

| Doctors | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.30 | $0.28 | $0.26 | $0.25 |
| 1,000 | $3.00 | $2.80 | $2.60 | $2.50 |
| 10,000 | $30.00 | $28.00 | $26.00 | $25.00 |
| 100,000 | $300.00 | $280.00 | $260.00 | $250.00 |

#### Patient Reviews

| Reviews | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.06 | $0.055 | $0.052 | $0.05 |
| 1,000 | $0.60 | $0.55 | $0.52 | $0.50 |
| 10,000 | $6.00 | $5.50 | $5.20 | $5.00 |
| 100,000 | $60.00 | $55.00 | $52.00 | $50.00 |

#### Estimate Your Run (Gold tier)

| Run | Doctors | Reviews | Doctor cost | Review cost | Total |
|-----|---------|---------|-------------|-------------|-------|
| Quick test | 100 | 1,000 | $0.25 | $0.50 | $0.75 |
| Specialty sweep | 1,000 | 15,000 | $2.50 | $7.50 | $10.00 |
| Metro-wide | 10,000 | 150,000 | $25.00 | $75.00 | $100.00 |

Set `includeReviews` to false, or lower `maxReviewsPerDoctor`, to cut the review portion of the cost. Platform fees (storage and data transfer) depend on your Apify plan and are additional.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor collects publicly available doctor and practice information for legitimate research, recruiting, directory, and market-analysis purposes. Users are responsible for complying with applicable laws and WebMD's Terms of Service. Do not use the data for spam, harassment, or any unlawful purpose, and do not treat patient reviews or profile details as protected health information. Always handle collected data responsibly and in line with relevant privacy regulations.

# Actor input Schema

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

Paste one or more WebMD URLs — individual doctor profile pages or directory search-result pages. This is the most precise way to get exactly the doctors you want. The page type is detected automatically. Leave empty to use the Specialty and Location search below instead.

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

Medical specialty to search for, for example 'Cardiology', 'Dermatology', or 'Family Medicine'. Combine with a Location below. Ignored when you paste URLs. Leave empty to browse all doctors in the location.

## `location` (type: `string`):

City and state, or a ZIP code, to search near — for example 'New York, NY' or '10016'. Combine with a Specialty above. Ignored when you paste URLs.

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

Maximum number of doctors to collect across all URLs and searches. Set to 0 for no limit (a safety maximum of 1,000 still applies). Tip: start with 10-50 to test, then increase. Reviews are not counted against this limit.

## `includeReviews` (type: `boolean`):

Collect each doctor's patient reviews (rating, comment, date, and category scores). Turn this off for faster, cheaper runs when you only need doctor and practice details.

## `maxReviewsPerDoctor` (type: `integer`):

Maximum number of patient reviews to collect for each doctor. Set to 0 to collect all available reviews, up to a safety maximum of 1,000 per doctor. Popular doctors can have hundreds of reviews — a limit keeps runs fast and predictable. Only applies when 'Include Patient Reviews' is on.

## Actor input object example

```json
{
  "startUrls": [],
  "specialty": "Cardiology",
  "location": "New York, NY",
  "maxResults": 100,
  "includeReviews": true,
  "maxReviewsPerDoctor": 20
}
```

# Actor output Schema

## `overview` (type: `string`):

Every record from the run in one place — doctors and patient reviews — distinguished by `recordType`.

## `doctors` (type: `string`):

Doctors only, with name, specialties, rating, review count, practice city/state, new-patient flag, phone, and profile URL.

## `reviews` (type: `string`):

Individual patient reviews only, each linked to its doctor — rating, headline, comment, date, and highlighted flag. Present only when 'Include Patient Reviews' is enabled.

# 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 = {
    "startUrls": [],
    "specialty": "Cardiology",
    "location": "New York, NY",
    "maxResults": 100,
    "includeReviews": true,
    "maxReviewsPerDoctor": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/webmd-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 = {
    "startUrls": [],
    "specialty": "Cardiology",
    "location": "New York, NY",
    "maxResults": 100,
    "includeReviews": True,
    "maxReviewsPerDoctor": 20,
}

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

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

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

```

## CLI example

```bash
echo '{
  "startUrls": [],
  "specialty": "Cardiology",
  "location": "New York, NY",
  "maxResults": 100,
  "includeReviews": true,
  "maxReviewsPerDoctor": 20
}' |
apify call solidcode/webmd-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=solidcode/webmd-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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