# NPI Registry Scraper (NPPES Healthcare Providers) (`cblu/npi-healthcare-providers-scraper`) Actor

Extract US healthcare provider records from the official NPPES NPI Registry — NPI number, specialty, license, practice address, phone, fax, authorized officials. Search by specialty, state, city, ZIP, or name. Pay per provider record.

- **URL**: https://apify.com/cblu/npi-healthcare-providers-scraper.md
- **Developed by:** [Steven Carleton](https://apify.com/cblu) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 provider records

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## NPI Registry Scraper — NPPES Healthcare Provider Search, Lookup & Lead Export

Search and extract **US healthcare provider records from the official NPPES NPI Registry** — the CMS registry of all 8+ million providers and healthcare organizations. Get the **NPI number, specialty (taxonomy), state license number, practice address, phone, fax**, and for organizations the **authorized official's name, title, and phone**. Filter by **specialty, state, city, ZIP code (wildcards), provider name, or organization name**, and download clean JSON, CSV, or Excel.

This Actor reads the **official CMS NPPES API** — no login, no API key — and **breaks the API's 1,200-record search cap**: when a search exceeds the cap, it automatically fans out into ZIP-prefix sub-searches and de-duplicates by NPI, returning the complete result set in one run. (Most NPI scrapers silently stop at 1,200 — or worse, return the same page over and over, because NPPES repeats results past the cap instead of erroring.)

### What data do you get?

One result per provider:

| Field | Example |
|---|---|
| `npi` / `npiUrl` | `1265837074` + direct registry link |
| `enumerationType` | `individual` (NPI-1) or `organization` (NPI-2) |
| `name` / `credential` | `JOHN A SMITH DDS` / `DDS` |
| `specialty` | `Dentist`, `Family Medicine`, `Physical Therapist`... |
| `licenseNumber` / `licenseState` | State license of the primary specialty |
| `taxonomies` | Every specialty with license details |
| `practiceAddress` | Street, city, state, ZIP, **phone, fax** |
| `mailingAddress` / `additionalPracticeLocations` | Full location footprint |
| `authorizedOfficial` | **Decision maker name, title, and phone** (organizations) |
| `identifiers` | Medicaid and insurer IDs on the record |
| `enumerationDate` / `lastUpdated` / `status` | Registry dates and active status |

### Use cases

- **Healthcare sales & marketing lists** — every provider of a given specialty in your territory, with practice phone numbers: dental-supply reps pull dentists by metro ZIP prefix, device reps pull orthopedic surgeons by state.
- **Provider directory & data enrichment** — join your customer or claims data to the authoritative registry by NPI; verify specialty, license, and active status in bulk.
- **New-provider detection** — filter output on `enumerationDate` for providers who just received their NPI: new practices are prime prospects for EHR, billing, and equipment vendors.
- **Recruiting** — build lists of licensed clinicians by specialty and city for outreach.
- **Credentialing & compliance** — bulk-verify NPIs, licenses, and practice addresses against the official source instead of typing them into the NPPES website one at a time.
- **AI agents / MCP** — a clean, filterable interface to the national provider registry for agent-driven verification and enrichment.

### How to use it

Every dentist in greater Miami (ZIP prefix wildcard):

```json
{
    "taxonomyDescription": "Dentist",
    "state": "FL",
    "postalCode": "331*",
    "maxResults": 2000
}
```

Physical therapists (individuals only) in Houston:

```json
{
    "taxonomyDescription": "Physical Therapist",
    "state": "TX",
    "city": "Houston",
    "enumerationType": "individual",
    "maxResults": 1000
}
```

Pharmacies statewide:

```json
{
    "taxonomyDescription": "Pharmacy",
    "state": "CO",
    "enumerationType": "organization",
    "maxResults": 5000
}
```

The NPPES API requires at least one criterion besides state — a specialty, city, postal code, or name. Names and organization names support trailing wildcards (`mayo*`). Set `includeRawData` to `true` to attach the complete raw NPPES record. **You are only charged for records actually returned.**

### Pricing

Pay per result: one charge per provider record extracted.

> Suggested store pricing (set in the Apify Console → Publication → Monetization):
>
> - `provider-record` event: **$0.002 per record** ($2.00 per 1,000 providers)
>
> Rationale: NPI comparables charge $0.001–$0.002 per base record — the 80-user category leader charges $0.01 actor start + $0.001/record + $0.012–0.02 per email enrichment, and the 43-user #2 charges $0.002 flat. At $2/1K with no start fee, a 2,000-dentist metro list costs $4 — versus $200–500 for the same list from a healthcare-list broker (Definitive Healthcare, IQVIA resellers).

### Data source & freshness

Records come from the **NPPES NPI Registry API operated by CMS** (npiregistry.cms.hhs.gov) — the authoritative, legally mandated registry of every US healthcare provider with a National Provider Identifier. CMS updates it **daily** as providers register and update their records. Because the Actor uses the official public API instead of scraping directory sites, it cannot be blocked and the data is never second-hand.

### FAQ

**Do I need an API key or CMS account?** No. The NPPES API is public and keyless.

**Individual vs organization?** NPI-1 is a person (physician, dentist, nurse practitioner...); NPI-2 is an entity (clinic, hospital, pharmacy, group practice). Filter with `enumerationType`, or leave it empty for both.

**Does it include email addresses?** NPPES does not publish provider emails — no NPI dataset legitimately includes them. You get practice phone, fax, address, and (for organizations) the authorized official's direct phone. Actors that sell "NPI emails" are enriching from other sources at 10x the price.

**How complete are the results?** Complete. The NPPES API hard-caps every search at 1,200 records (and silently repeats the last page beyond it) — this Actor detects the cap and automatically subdivides the search by ZIP prefix until the whole result set is fetched, de-duplicated by NPI. Verified: a Miami-area dentist search returned 1,925 unique providers in one run. Very broad searches (a whole state with no other filter) are rejected by the API itself — add a specialty, city, or ZIP prefix.

**Can I search by taxonomy code?** Yes — `taxonomyDescription` accepts either the description (`Dentist`) or an exact taxonomy code (`122300000X`).

**Why do some results show a different ZIP than I searched?** NPPES matches `postalCode` against **any** of the provider's addresses (practice, mailing, or secondary locations). A provider practicing in Miami with a mailing address elsewhere still matches — check `practiceAddress`, `mailingAddress`, and `additionalPracticeLocations` in the output.

# Actor input Schema

## `taxonomyDescription` (type: `string`):

Provider specialty / taxonomy description, e.g. <code>Dentist</code>, <code>Family Medicine</code>, <code>Chiropractor</code>, <code>Physical Therapist</code>, <code>Pharmacy</code>. Exact taxonomy codes also work. One word searches broadly across sub-specialties.

## `state` (type: `string`):

Optional. Two-letter US state code of the practice location, e.g. <code>TX</code>.

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

Optional. Practice-location city, e.g. <code>Austin</code>.

## `postalCode` (type: `string`):

Optional. Practice-location ZIP. Supports prefix wildcards: <code>331\*</code> matches every ZIP starting with 331 (greater Miami).

## `enumerationType` (type: `string`):

Optional. <code>individual</code> (NPI-1: physicians, dentists, nurses...) or <code>organization</code> (NPI-2: clinics, hospitals, pharmacies...). Leave empty for both.

## `firstName` (type: `string`):

Optional. Provider first name (individual lookups). Supports trailing wildcard, e.g. <code>jo\*</code>.

## `lastName` (type: `string`):

Optional. Provider last name (individual lookups). Supports trailing wildcard.

## `organizationName` (type: `string`):

Optional. Organization name (NPI-2 lookups). Supports trailing wildcard, e.g. <code>mayo\*</code>.

## `includeRawData` (type: `boolean`):

Attach the complete raw NPPES API result to every record under <code>raw</code>.

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

Maximum number of provider records to return. You are only charged for records actually returned.

## Actor input object example

```json
{
  "taxonomyDescription": "Dentist",
  "state": "TX",
  "includeRawData": false,
  "maxResults": 500
}
```

# 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 = {
    "taxonomyDescription": "Dentist",
    "state": "TX",
    "maxResults": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("cblu/npi-healthcare-providers-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 = {
    "taxonomyDescription": "Dentist",
    "state": "TX",
    "maxResults": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("cblu/npi-healthcare-providers-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 '{
  "taxonomyDescription": "Dentist",
  "state": "TX",
  "maxResults": 500
}' |
apify call cblu/npi-healthcare-providers-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/vBRZnRZEMCWS1quF2/builds/RQTenGOeQTKCpRoVy/openapi.json
