# Healthgrades Scraper — Doctor & Dentist Leads, NPI + Phone (`scrapersdelight/healthgrades-scraper`) Actor

Scrape the Healthgrades provider directory by specialty and city — doctor/dentist name, credentials, specialty, NPI number, star rating, review count, every office address with phone and GPS, awards and profile URL. 184 specialties, all 50 states. Public data, no login. Export JSON/CSV/Excel.

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

## Pricing

$1.50 / 1,000 per provider returneds

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/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

## Healthgrades Scraper — doctor & dentist leads with NPI + phone

Turn the Healthgrades provider directory into a clean lead list. Pick a **specialty** and a
**city or state**, and get one row per provider: name, credentials, specialty, **NPI number**,
star rating, review count, **every office address with its own phone number and GPS coordinates**,
awards, "accepting new patients", bio and profile URL.

184 specialties (from Family Medicine and Dentistry to Vascular Surgery), all 50 states + DC + PR.
Public data, no login, no API key.

### What you get (one row per provider)

| Field | Example |
|---|---|
| `name` / `credentials` | `Dr. Maribel Carbia` / `DMD` |
| `npi` | `1174799001` — the 10-digit National Provider Identifier |
| `specialty` / `specialtyDetail` | `Dentistry` / `Dentistry` |
| `rating` / `reviewCount` | `4.8` / `26` |
| `phone` | `(305) 666-0006` |
| `practiceName` | `The Dental Studio` |
| `addressStreet` / `City` / `State` / `Zip` | `4100 Salzedo St Ste 20` / `Coral Gables` / `FL` / `33146` |
| `latitude` / `longitude` | `25.73398` / `-80.26041` |
| `offices[]` | every office: name, street, city, state, zip, **its own phone**, GPS, office profile URL |
| `officeCount` | `2` |
| `acceptingNewPatients` | `true` |
| `awards[]` | `["Healthgrades Honor Roll"]` |
| `highlights[]` / `attributes[]` | `["Listened/answered questions"]` / `["Virtual Visits"]` |
| `description` | the provider's published bio |
| `lastVerified` | `May 29, 2026` — when Healthgrades last verified the profile |
| `sponsored` | `true` for the paid cards Healthgrades injects at the top of each page |
| `profileUrl`, `imageUrl`, `providerId`, `providerType` | source + stable IDs |
| `searchSpecialty`, `searchLocation`, `resultPage`, `sourceUrl`, `scrapedAt` | provenance |

### Input

```json
{
  "specialties": ["Family Medicine", "Cardiology"],
  "locations": ["Los Angeles, CA", "Miami, FL"],
  "maxItems": 500,
  "maxPagesPerSearch": 10,
  "includeProviderDetails": true,
  "excludeSponsored": true,
  "minRating": 4,
  "requirePhone": true
}
```

- **specialties** — everyday name (`"Dentistry"`, `"Primary Care"`, `"OBGYN"`) or the exact
  Healthgrades slug (`"dermatology-directory"`). Full list:
  <https://www.healthgrades.com/specialty-directory>
- **locations** — `"City, ST"` for a city, or a bare state code (`"CA"`) to sweep a whole state.
  Healthgrades spells cities out, so `"St. Louis, MO"` is converted to `saint-louis` for you.
- Every specialty is crossed with every location. 2 specialties × 3 cities = 6 searches.
- **startUrls** — paste directory URLs directly if you prefer; pagination is followed for you.
- **includeProviderDetails** — ON opens each provider profile to add NPI, phone, all offices,
  GPS, awards and bio. OFF is ~5× faster but returns listing-level fields only (no phone, no NPI).

### Who buys this

Medical-practice marketing agencies, healthcare staffing and locum recruiters, medtech and
practice-management SaaS sales teams, insurance credentialing and provider-network builders,
and researchers who need an NPI-keyed provider list they can join to CMS/NPPES data.

### How it works (and its honest limits)

- Directory pages are server-rendered HTML; provider cards are read from stable
  `data-qa-target` attributes, and each provider profile is parsed from its schema.org JSON-LD
  block **plus** the DOM (phone lives in the DOM, GPS lives in the JSON-LD). Nothing is scraped
  with a whole-page regex.
- **Deduplicated** by the Healthgrades provider id and again by NPI, so the same doctor is never
  returned — or billed — twice in a run.
- **Radius, not city limits.** Healthgrades returns "providers within ~10 miles of the city",
  so a `Los Angeles, CA` search legitimately includes Culver City and Beverly Hills addresses.
  Filter on `addressCity` if you need strict city limits.
- **Sponsored cards.** Each result page carries up to 3 paid listings. They are flagged
  (`sponsored: true`) and can be excluded with `excludeSponsored`.
- **practiceName is not always published.** Where Healthgrades shows the placeholder "Practice",
  the actor falls back to the group's directory-URL name, and returns `null` when there is none
  (~35% of rows in a Miami dentistry sample).
- **Education, residency and board-certification detail are not in scope** — Healthgrades loads
  those client-side after the page renders, so they are not in the HTML this actor reads. Awards
  and the `highlights` list are returned.
- Rating/review counts are Healthgrades' own patient ratings; providers with no ratings have
  `rating: null`.

### Legal / responsible use

This actor collects information Healthgrades publishes openly for patients to browse: provider
names, professional credentials, NPIs (a public federal identifier) and office contact details.
That is professional/business information, not consumer personal data — but **you** are
responsible for using it lawfully: B2B outreach, credentialing, network building and market
research, in line with Healthgrades' terms of use and any privacy, anti-spam or marketing law
that applies to you (GDPR/CCPA, TCPA, CAN-SPAM). Do not use it to contact patients, and do not
represent scraped ratings as an endorsement.

### Pricing

Pay per event: **$0.0015 per provider returned**. You are charged only for rows actually
delivered to your dataset — duplicates and filtered-out providers are free.

# Actor input Schema

## `specialties` (type: `array`):

One or more Healthgrades specialties. Use the everyday name ("Family Medicine", "Dentistry", "Cardiology", "Psychiatry") or the exact directory slug ("dermatology-directory"). 184 specialties are supported — the full list is at https://www.healthgrades.com/specialty-directory. Every specialty is crossed with every location below.

## `locations` (type: `array`):

"City, ST" for a city (e.g. "Los Angeles, CA") or just a state code ("CA") to sweep the whole state. Tip: Healthgrades spells cities out — use "Saint Louis, MO", not "St. Louis" (the actor converts St./Ft./Mt. for you).

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

Paste Healthgrades directory URLs directly, e.g. https://www.healthgrades.com/family-practice-directory/ca-california/los-angeles. Used in addition to the specialty × location grid above. Pagination is followed automatically, so paste page 1.

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

Stop after this many provider rows in total (across all searches). Set 0 for no limit.

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

Healthgrades returns 20 organic providers per page (a big city can run to 400+ pages). This caps how deep each specialty × location goes.

## `includeProviderDetails` (type: `boolean`):

ON (recommended): opens every provider profile to add the NPI number, office phone numbers, all office addresses with GPS coordinates, awards, bio and "accepting new patients". OFF: listing-level fields only (name, specialty, rating, one address) — about 5× faster, but no phone and no NPI.

## `excludeSponsored` (type: `boolean`):

Healthgrades injects up to 3 paid "sponsored" cards at the top of each page. Turn this on to keep only organic results.

## `minRating` (type: `string`):

Drop providers rated below this. Unrated providers are dropped when a floor is set. "Any rating" keeps everyone.

## `minReviewCount` (type: `integer`):

Drop providers with fewer patient ratings than this. 0 = keep everyone.

## `requirePhone` (type: `boolean`):

Drops rows with no office phone. Needs profile enrichment ON (phone is not on the listing card).

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

Apify Proxy (datacenter) is enough for healthgrades.com and is the default — measured 8/8 clean pages. Switch to RESIDENTIAL only if you start seeing blocked pages.

## Actor input object example

```json
{
  "specialties": [
    "Family Medicine"
  ],
  "locations": [
    "Los Angeles, CA"
  ],
  "startUrls": [],
  "maxItems": 100,
  "maxPagesPerSearch": 5,
  "includeProviderDetails": true,
  "excludeSponsored": false,
  "minRating": "0",
  "minReviewCount": 0,
  "requirePhone": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `records` (type: `string`):

The dataset of scraped Healthgrades providers, one item per doctor / dentist / clinician.

# 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 = {
    "specialties": [
        "Family Medicine"
    ],
    "locations": [
        "Los Angeles, CA"
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/healthgrades-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 = {
    "specialties": ["Family Medicine"],
    "locations": ["Los Angeles, CA"],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/healthgrades-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 '{
  "specialties": [
    "Family Medicine"
  ],
  "locations": [
    "Los Angeles, CA"
  ],
  "maxItems": 100
}' |
apify call scrapersdelight/healthgrades-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapersdelight/healthgrades-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/TGCeWgqRJcvEPiQYX/builds/wImBdhEaDL18i5F3b/openapi.json
