# NPI Registry Scraper: US doctors and providers by specialty (`bepolabs/npi-registry`) Actor

Build prospect files or verify credentials: nurses, therapists, clinics, hospitals and pharmacies within US healthcare providers, with identifiers and contacts from the authoritative federal source. Costs 1 USD per 1,000 providers.

- **URL**: https://apify.com/bepolabs/npi-registry.md
- **Developed by:** [BEPO Labs](https://apify.com/bepolabs) (community)
- **Categories:** Lead generation, Other
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 providers

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

### 🩺 What is NPI Registry Lookup?

Find the right physician, clinic or pharmacy: this Actor queries the [NPI Registry](https://npiregistry.cms.hhs.gov) run by CMS and returns every matching entry across US healthcare providers in tidy tabular form. Combine focus area, individual or company label, state, city or ZIP; each line carries credential, practice and mailing location, fax, licence numbers and activity.

- **Healthcare lead lists**: every cardiologist in Texas or every pharmacy in a city, with practice address and phone
- **Provider verification**: check NPI numbers against the registry before onboarding, billing or credentialing
- **Data enrichment**: add specialty, address and organization to a list of NPIs from claims or CRM data
- **Market mapping**: count and locate providers of a specialty by state, city or ZIP code
- **Directories and apps**: build or refresh a provider directory from the official source

![NPI Registry Lookup: US doctors, nurses, clinics and pharmacies from the official CMS NPI Registry, by specialty, name, NPI or place.](https://api.apify.com/v2/key-value-stores/wdeAWGooHdIhvFgSY/records/npi-registry-hero.png)

#### ✨ Why use this Actor?

- ✅ **Official source**: straight from the CMS NPPES API, no third-party copy, no scraping
- ✅ **Search the way you think**: specialty, person name, organization or NPI, times every state you list
- ✅ **NPI check digit verified**: typos in NPI numbers are caught before any request
- ✅ **Main specialty filter**: keep only providers whose primary field matches, not secondary ones
- ✅ **Readable rows**: names in normal case, addresses as objects, primary taxonomy pulled up front
- ✅ **Fair price**: 1 USD per 1,000 providers, deduped across searches; you pay only for providers saved

### 📦 What data can you get with NPI Registry Lookup?

| | | |
|---|---|---|
| 🆔 NPI number | 👤 Name, first, middle, last | 🎓 Credential (MD, DO, NP...) |
| 🏥 Individual or organization | 🩺 Primary specialty and code | 📋 All taxonomies with license and state |
| 📍 Practice address | 📬 Mailing address | 📞 Phone and fax |
| 🏢 Other practice locations | 👔 Authorized official (organizations) | 🔢 Other identifiers |
| ✅ Status | 📅 Enumeration and last update date | 🔗 NPI Registry page URL |

> Fields the provider did not file with CMS are empty (null), never guessed.

### 🚀 How to use NPI Registry Lookup

NPI Registry Lookup works in a few clicks, no coding needed:

1. [Create a free Apify account](https://console.apify.com/sign-up) (the free plan includes 5 USD of monthly credit).
2. Open [NPI Registry Lookup](https://apify.com/bepolabs/npi-registry) and click **Try for free**.
3. Enter specialties, names, organizations or NPI numbers, add the states, city or ZIP code, and set how many providers per search.
4. Click **Start** and wait for the run to finish (most runs take seconds).
5. Download your data as JSON, CSV, Excel, XML or HTML, or send it straight to Google Sheets, Make, Zapier or your AI agent.

![How NPI Registry Lookup works](https://api.apify.com/v2/key-value-stores/wdeAWGooHdIhvFgSY/records/npi-registry-workflow.png)

### ⬇️ Input

Give at least one specialty, provider name, organization or NPI number. A state alone is not a search in the NPI Registry, so add one of those to it.

##### Specialty, name, organization or NPI

`taxonomies` takes specialty names as NPPES writes them (Cardiovascular Disease, Dentist, Nurse Practitioner; `Dent*` matches the start). `names` accepts "Jane Smith" or just a last name. `organizations` finds hospitals, clinics and pharmacies (`CVS*`). `npiNumbers` looks up 10-digit NPIs, up to 5,000 per run.

##### States, city and ZIP

Each search runs once per entry of `states`. `city` and `postalCode` (`787*` for a prefix) narrow all of them. The registry matches a state on any of a provider's addresses, so a few rows can have their principal site elsewhere; filter on `practiceAddress.state` for that one only.

##### More than 1,200 per search

The NPI Registry returns at most 1,200 records per query. When a search hits that limit, the run summary says so; split it by city or ZIP prefix to reach the rest.

| Field | Type | What it does | Default |
|---|---|---|---|
| **Specialties (taxonomy)** (`taxonomies`) | array | Specialty descriptions as NPPES names them, e.g. | `["Cardiovascular Disease"]` |
| **States** (`states`) | array | Two-letter US state codes, e.g. | `["TX"]` |
| **Provider names** (`names`) | array | Individual providers: 'Jane Smith', 'Smith, Jane' or a last name; a trailing \* after 2 letters matches the start (Smi\*). |  |
| **Organization names** (`organizations`) | array | Hospitals, clinics, pharmacies and other organizations, e.g. |  |
| **NPI numbers** (`npiNumbers`) | array | Look up these 10-digit NPIs directly (check digit verified), e.g. |  |
| **City** (`city`) | string | Narrow every search to this city of the practice or mailing address, e.g. |  |
| **ZIP code** (`postalCode`) | string | Narrow every search to this ZIP code; a trailing \* matches the start (787\*). |  |
| **Provider type for specialty searches** (`providerType`) | string | individual (doctors, nurses, therapists), organization (hospitals, clinics, pharmacies) or any. | `"any"` |
| **Main specialty only** (`primaryTaxonomyOnly`) | boolean | Keep only providers whose primary specialty matches the searched specialty (NPPES also matches secondary ones). | `false` |
| **Max providers per search** (`maxItemsPerQuery`) | integer | Per specialty, name or organization and state (1 to 1,200, the NPI Registry's own limit per query; add a city or ZIP to reach more). | `200` |
| **Max retries** (`maxRetries`) | integer | Retries per request on timeouts, rate limits and server errors. | `3` |

![NPI Registry Lookup input form](https://api.apify.com/v2/key-value-stores/wdeAWGooHdIhvFgSY/records/npi-registry-input.png)

#### Input example

```json
{
    "taxonomies": [
        "Cardiovascular Disease"
    ],
    "states": [
        "TX"
    ],
    "providerType": "individual",
    "primaryTaxonomyOnly": true,
    "maxItemsPerQuery": 200
}
```

### ⬆️ Output

Every provider becomes one row with the same fields; `source` tells you which search found it, and providers matched twice are kept once. The run summary in the key-value store (`OUTPUT`) lists every query with its rows and a tip when it reached the registry's limit.

![NPI Registry Lookup output table](https://api.apify.com/v2/key-value-stores/wdeAWGooHdIhvFgSY/records/npi-registry-output.png)

#### Output example

One row of the dataset (NPI lookup of 1003000126):

```json
{
    "npi": "1003000126",
    "type": "individual",
    "name": "Ardalan Enkeshafi",
    "firstName": "Ardalan",
    "lastName": "Enkeshafi",
    "middleName": null,
    "credential": "M.D.",
    "sex": "M",
    "organizationName": null,
    "organizationalSubpart": null,
    "soleProprietor": false,
    "authorizedOfficial": null,
    "status": "active",
    "primaryTaxonomy": "Hospitalist",
    "primaryTaxonomyCode": "208M00000X",
    "taxonomies": [
        {
            "code": "207R00000X",
            "description": "Internal Medicine",
            "primary": false,
            "license": "D0000290",
            "state": "MD"
        },
        {
            "code": "207R00000X",
            "description": "Internal Medicine",
            "primary": false,
            "license": "D0068455",
            "state": "MD"
        },
        {
            "code": "207R00000X",
            "description": "Internal Medicine",
            "primary": false,
            "license": "0101254037",
            "state": "VA"
        },
        {
            "code": "208M00000X",
            "description": "Hospitalist",
            "primary": true,
            "license": "MD600003480",
            "state": "DC"
        }
    ],
    "practiceAddress": {
        "line1": "6410 ROCKLEDGE DR STE 304",
        "line2": null,
        "city": "BETHESDA",
        "state": "MD",
        "postalCode": "208171841",
        "country": "US",
        "phone": "443-602-6207",
        "fax": null
    },
    "mailingAddress": {
        "line1": "6410 ROCKLEDGE DR STE 304",
        "line2": null,
        "city": "BETHESDA",
        "state": "MD",
        "postalCode": "208171841",
        "country": "US",
        "phone": "443-602-6207",
        "fax": "540-224-5684"
    },
    "phone": "443-602-6207",
    "otherPracticeLocations": [
        {
            "line1": "2900 LAMB CIR",
            "line2": null,
            "city": "CHRISTIANSBURG",
            "state": "VA",
            "postalCode": "240736344",
            "country": "US",
            "phone": "540-731-2000",
            "fax": "540-731-2659"
        },
        {
            "line1": "900 SETON DR",
            "line2": null,
            "city": "CUMBERLAND",
            "state": "MD",
            "postalCode": "215021854",
            "country": "US",
            "phone": "301-723-4000",
            "fax": null
        },
        {
            "line1": "1200 PECAN ST SE",
            "line2": null,
            "city": "WASHINGTON",
            "state": "DC",
            "postalCode": "200322652",
            "country": "US",
            "phone": "777-444-6200",
            "fax": null
        }
    ],
    "otherNames": [],
    "identifiers": [],
    "endpoints": [],
    "enumerationDate": "2007-08-31",
    "lastUpdated": "2025-05-28",
    "url": "https://npiregistry.cms.hhs.gov/provider-view/1003000126",
    "source": "NPI 1003000126"
}
```

#### Run summary (OUTPUT)

The key-value store record `OUTPUT` has the self-check and one line per search. An NPI with a valid check digit that is not in the registry returns no row:

```json
{
    "ok": true,
    "rows": 2,
    "problems": [],
    "tip": null,
    "tasks": [
        {
            "task": "NPI 1003000126",
            "ok": true,
            "rows": 1,
            "capped": false,
            "error": null
        },
        {
            "task": "NPI 1881018208",
            "ok": true,
            "rows": 1,
            "capped": false,
            "error": null
        },
        {
            "task": "NPI 1234567893",
            "ok": true,
            "rows": 0,
            "capped": false,
            "error": null
        }
    ]
}
```

View the results as a table or JSON in the Output tab and download them as JSON, CSV, Excel, XML, HTML or RSS, all fields or only those you pick.

### 💰 How much does NPI Registry Lookup cost?

NPI Registry Lookup is priced **per event**: **1 USD per 1,000 providers** (0.001 USD each), with no monthly rental. Each provider saved to the dataset is billed once, even if two searches found it; a search without hits is free.

| You get | You pay |
|---|---|
| 100 providers | 0.1 USD |
| 1,000 providers | 1 USD |
| 10,000 providers | 10 USD |
| 100,000 providers | 100 USD |

💡 Apify's free plan gives you 5 USD of credit every month, enough for about **5,000 providers** at no cost. Set a spending limit per run and the Actor stops there.

### ⚖️ NPI Registry Lookup vs. the alternatives

| | NPI Registry Lookup | NPI Registry website | Paid provider databases |
|---|---|---|---|
| **Source** | ✅ official CMS NPPES | ✅ official CMS NPPES | resold copies |
| **Bulk search by specialty and state** | ✅ many at once | one search at a time | ✅ |
| **Export to CSV, Excel, JSON** | ✅ | ❌ | ✅ |
| **NPI list lookup** | ✅ up to 5,000 per run | one by one | ✅ |
| **Price** | 1 USD per 1,000 providers | free, manual | subscription |
| **API, schedules and MCP for AI agents** | ✅ | ❌ | varies |

### 🔌 Integrations, API and MCP

#### Connect NPI Registry Lookup to your AI agent (MCP)

Give Claude, ChatGPT, Cursor or any MCP client direct access to NPI Registry Lookup through the [Apify MCP server](https://mcp.apify.com). Add this URL to its settings:

```text
https://mcp.apify.com/?actors=bepolabs/npi-registry
```

For Claude Desktop, add it under `mcpServers` in `claude_desktop_config.json`:

```json
{
    "mcpServers": {
        "npi-registry": {
            "command": "npx",
            "args": [
                "-y",
                "@apify/actors-mcp-server",
                "--actors",
                "bepolabs/npi-registry"
            ],
            "env": {
                "APIFY_TOKEN": "<your Apify API token>"
            }
        }
    }
}
```

Then ask: *"List 50 dermatologists with a practice in Austin, Texas, with their phone numbers."*

#### Run it from your code

Python (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("bepolabs/npi-registry").call(run_input={"taxonomies":["Cardiovascular Disease"],"states":["TX"],"providerType":"individual","primaryTaxonomyOnly":true,"maxItemsPerQuery":200})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

JavaScript (`npm install apify-client`):

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('bepolabs/npi-registry').call({"taxonomies":["Cardiovascular Disease"],"states":["TX"],"providerType":"individual","primaryTaxonomyOnly":true,"maxItemsPerQuery":200});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### No-code integrations

Send results to **Google Sheets, Slack, Airtable, HubSpot, Make, Zapier, n8n** and more from the Integrations tab, start runs on a **schedule**, or trigger your own endpoint with a **webhook** when a run finishes. The [Apify API](https://docs.apify.com/api/v2) gives you full control over runs and datasets.

### ❓ FAQ

##### Where does the data come from?

From the official NPPES NPI Registry API of CMS (npiregistry.cms.hhs.gov, version 2.1). Every run asks the registry live.

##### Which specialty names work?

The taxonomy descriptions NPPES uses, for example Cardiovascular Disease, Family Medicine, Dentist, Nurse Practitioner, Physical Therapist or Pharmacy. A trailing `*` matches the start of a name.

##### Why do some rows show a practice in another state?

The registry matches the state on all of a provider's locations, including mailing ones and other practice sites. Filter on `practiceAddress.state` for main practices only.

##### Are emails included?

No. The NPI Registry publishes street locations, phone and fax numbers, not mail accounts.

##### How many providers can I get?

Up to 1,200 per query (the registry's own limit) and up to 200 queries and 5,000 NPI numbers per run. Split large searches by city or ZIP prefix.

##### Is it legal to use NPI Registry Lookup?

Yes. NPPES NPI Registry data is information that CMS publishes for anyone to search and download, and the Actor uses the registry's official API. If you use the data for outreach, follow the laws that apply to you, such as the CAN-SPAM Act, the TCPA for calls and texts, and state rules.

##### What if something is missing or does not work?

Open an issue on the **Issues** tab; we read each one and reply. Feature requests are welcome too.

### 💬 Your feedback

Tell us what NPI Registry Lookup should add on the **Issues** tab or leave a review; your notes decide what we work on next.

### 🔗 Related Actors

| Actor | What it does |
|---|---|
| 🧪 [Clinical Trials Data](https://apify.com/bepolabs/clinical-trials) | ClinicalTrials.gov studies by condition, drug, sponsor or NCT id, with sites, eligibility and posted results. |
| 🏛️ [SAM.gov Contract Opportunities](https://apify.com/bepolabs/sam-gov) | US federal contract opportunities by keyword, NAICS, set-aside or agency, with deadlines, contacts and attachments. |
| 🏛️ [UK Tenders](https://apify.com/bepolabs/uk-tenders) | UK public contracts from Contracts Finder and Find a Tender by keyword, CPV, value, region and deadline, with daily alerts. |
| 💊 [openFDA Data](https://apify.com/bepolabs/openfda) | FDA adverse events, recalls, drug labels and 510(k) clearances for any drug or device, as clean rows. |
| 💼 [ATS Jobs](https://apify.com/bepolabs/ats-jobs) | Every open job from company career boards on Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee in one deduped feed. |
| 🌐 [Domain RDAP and DNS](https://apify.com/bepolabs/domain-rdap) | Domains to registrar, creation and expiry dates, age, status, nameservers, DNSSEC and DNS records from official RDAP, in bulk. |
| 📧 [Email Verifier](https://apify.com/bepolabs/email-dns-check) | Bulk email validation over DNS: valid, risky or invalid per address, with the reasons, a score, a typo fix, throwaway and shared-inbox flags. |
| 📍 [OpenStreetMap Places](https://apify.com/bepolabs/osm-pois) | Shops, restaurants and offices in any city or area, with address, phone, website, opening hours and coordinates. |

# Changelog

This Actor's version history is a separate document: https://apify.com/bepolabs/npi-registry/changelog.md

# Actor input Schema

## `taxonomies` (type: `array`):

Specialty descriptions as NPPES names them, e.g. Cardiovascular Disease, Dentist, Nurse Practitioner or Physical Therapist; a trailing \* matches the start (Dent\*). One search per specialty and state.

## `states` (type: `array`):

Two-letter US state codes, e.g. TX or CA; each search runs once per state. A state alone is not a search: add a specialty, name or organization.

## `names` (type: `array`):

Individual providers: 'Jane Smith', 'Smith, Jane' or a last name; a trailing \* after 2 letters matches the start (Smi\*).

## `organizations` (type: `array`):

Hospitals, clinics, pharmacies and other organizations, e.g. Mayo Clinic or CVS\*.

## `npiNumbers` (type: `array`):

Look up these 10-digit NPIs directly (check digit verified), e.g. 1003000126.

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

Narrow every search to this city of the practice or mailing address, e.g. Austin.

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

Narrow every search to this ZIP code; a trailing \* matches the start (787\*).

## `providerType` (type: `string`):

individual (doctors, nurses, therapists), organization (hospitals, clinics, pharmacies) or any.

## `primaryTaxonomyOnly` (type: `boolean`):

Keep only providers whose primary specialty matches the searched specialty (NPPES also matches secondary ones).

## `maxItemsPerQuery` (type: `integer`):

Per specialty, name or organization and state (1 to 1,200, the NPI Registry's own limit per query; add a city or ZIP to reach more).

## `maxRetries` (type: `integer`):

Retries per request on timeouts, rate limits and server errors.

## Actor input object example

```json
{
  "taxonomies": [
    "Cardiovascular Disease"
  ],
  "states": [
    "TX"
  ],
  "providerType": "any",
  "primaryTaxonomyOnly": false,
  "maxItemsPerQuery": 200,
  "maxRetries": 3
}
```

# Actor output Schema

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

Dataset items, one row per result, in the overview table view.

# 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 = {
    "taxonomies": [
        "Cardiovascular Disease"
    ],
    "states": [
        "TX"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bepolabs/npi-registry").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 = {
    "taxonomies": ["Cardiovascular Disease"],
    "states": ["TX"],
}

# Run the Actor and wait for it to finish
run = client.actor("bepolabs/npi-registry").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 '{
  "taxonomies": [
    "Cardiovascular Disease"
  ],
  "states": [
    "TX"
  ]
}' |
apify call bepolabs/npi-registry --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bepolabs/npi-registry"
        }
    }
}
```

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/GhwaytBNSFwqRcoa3/builds/ddDSLLPADxipK0nym/openapi.json
