# NPI Registry Exporter – Complete Provider Lists (`classier_linear/npi-registry-exporter`) Actor

Export complete lists of US doctors, dentists and other providers by specialty, state, city or ZIP from the CMS NPI Registry. Splits past the 1,200-record cap automatically and includes a completeness report. Pay per provider.

- **URL**: https://apify.com/classier_linear/npi-registry-exporter.md
- **Developed by:** [Destiny Lazcano](https://apify.com/classier_linear) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 1,000 provider record exporteds

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?

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

## NPI Registry Exporter – Complete Provider Lists

Export a **complete, current list of US healthcare providers** by specialty, state, city or ZIP code from the CMS National Plan and Provider Enumeration System (NPPES) NPI Registry: name, NPI, taxonomy, practice address, phone, fax, license and enumeration date, ready for Excel, CSV or JSON.

Built for medical and dental sales teams, device and supply distributors, healthcare recruiters, credentialing teams and market researchers who need every provider of one kind in one place, not the first 1,200 the registry happens to return.

### Why "complete by design"

The public NPI Registry API answers at most **1,200 records per search** (200 per page, six pages). Ask it for every dentist in Texas and you get 1,200 of roughly 20,000, with no warning. This Actor:

1. probes every search to detect when it is full,
2. splits a full search automatically by provider type and then by ZIP prefix (`78*`, `786*`, `7864*`, `78640`),
3. de-duplicates by NPI across every slice,
4. writes a **completeness report** to the run's key-value store (`COMPLETENESS_REPORT`) listing every slice, how many pages it took, and whether it was `complete`, `split`, `truncated` or `error`.

A `truncated` slice is one unsplittable ZIP with more than 1,200 providers of one type and specialty. It is rare with a specialty filter, more likely when you export every provider type in a dense ZIP; the run's status message and the report both say so and name the ZIP.

### What you get

One row per unique provider (NPI). Key columns:

| Column | Example |
|---|---|
| `npi`, `enumerationType`, `providerType` | `1234567893`, `NPI-1`, `Individual` |
| `displayName`, `firstName`, `lastName`, `credential` | `SAMPLE, JANE Q, DDS` |
| `organizationName`, `authorizedOfficialName`, `authorizedOfficialTitle`, `authorizedOfficialPhone` | organizations (NPI-2) only |
| `taxonomyCode`, `taxonomyDescription`, `taxonomyIsPrimary` | the taxonomy that matched your search |
| `primaryTaxonomyCode`, `primaryTaxonomyDescription`, `allTaxonomyCodes` | |
| `licenseNumber`, `licenseState`, `taxonomyGroup` | |
| `practiceAddress1`, `practiceAddress2`, `practiceCity`, `practiceState`, `practicePostalCode`, `practiceZip5`, `practiceCountry` | the practice location |
| `practicePhone`, `practiceFax` | |
| `mailingAddress1` … `mailingPhone` | optional, with **Include mailing address columns** |
| `enumerationDate`, `lastUpdated`, `certificationDate`, `status` | |
| `registryUrl`, `searchSlice`, `source`, `fetchedAt` | audit trail |

No emails: NPPES publishes none, and this Actor does not enrich records from other websites. Deactivated NPIs are reduced to the NPI, status and deactivation date, which is all CMS discloses for them, and those rows are saved free of charge.

The practice address shown is the one that matched your city or ZIP filter: if a provider's main location is elsewhere and only a secondary practice location matches, that location is shown and `practiceLocationIsSecondary` is `true`.

### How to use it

1. Enter a **Specialty** as written in the NUCC taxonomy (`Dentist`, `Family Medicine`, `Nurse Practitioner`, `Physical Therapist`, `Chiropractor`, `Pharmacy`). The registry matches the text inside any of a provider's taxonomy descriptions, so `Dentist` also returns `Dentist, General Practice` and `Dentist, Pediatric Dentistry`; use a full description to narrow.
2. Pick the **State** of the practice location.
3. Optionally add **Cities** or **ZIP codes / prefixes** (`786*`). Leave both empty for the whole state.
4. Optionally limit to individuals (`NPI-1`) or organizations (`NPI-2`), add mailing columns, and set **Maximum providers to export**.
5. Run. Download the dataset as CSV, Excel or JSON from the Storage tab, and read `COMPLETENESS_REPORT` in the key-value store if you want proof the list is exhaustive.

#### Example inputs

All dentists in Kyle, Texas (about 65 rows, under a minute):

```json
{ "taxonomyDescription": "Dentist", "state": "TX", "cities": ["Kyle"] }
```

Every orthodontist in Texas:

```json
{ "taxonomyDescription": "Dentist, Orthodontics and Dentofacial Orthopedics", "state": "TX", "maxResults": 100000 }
```

Every provider of any kind in the 786 ZIP area:

```json
{ "state": "TX", "postalCodes": ["786*"], "maxResults": 100000 }
```

The registry needs a specialty, a city or a ZIP code together with the state; a state on its own is rejected before any request is made.

### Pricing

**$2.50 per 1,000 providers** on the Free plan (Bronze $2.20, Silver $1.90, Gold $1.60). A tiny start fee of $0.00005 per run (one two-hundredth of a cent). Otherwise you pay only for unique providers saved to your dataset; duplicates, deactivated NPIs and empty searches cost nothing. Use **Maximum cost per run** to cap any run: at $2.50 per 1,000, a $1.00 cap allows 399 providers and the Actor stops cleanly with a status message when the cap is reached.

Worked examples: 65 Kyle dentists ≈ $0.16. 20,000 Texas dentists ≈ $50 and about 15 minutes.

### Limits and good citizenship

- One request per second to the registry, one fixed identity, no proxies. If the registry answers an error twice in a row the run stops politely, keeps everything already exported, and tells you to re-run later.
- One state per run (run once per state for multi-state lists). Up to 100,000 providers per run.
- City, state and ZIP filters apply to **practice locations** (`address_purpose=LOCATION`, main or secondary), so a provider whose only Kyle address is a mailing address is not included.
- A state-wide specialty export makes several hundred to about a thousand requests and takes 10 to 20 minutes.

### Data source and attribution

Source: CMS National Plan and Provider Enumeration System (NPPES) NPI Registry API v2.1, https://npiregistry.cms.hhs.gov. NPPES data is public under the Freedom of Information Act; CMS states there is no charge to download it and no way for providers to opt out. Taxonomy codes are the NUCC Health Care Provider Taxonomy code set. Every row carries `source` and `fetchedAt` so you can cite it.

### FAQ

**Why do I get fewer rows than another tool?** Filters apply to the practice location, duplicates are removed, and deactivated NPIs are reduced to NPI and date. The completeness report shows exactly what was searched.

**Why no emails?** The registry does not publish them, and this Actor never looks anywhere else.

**How fresh is the data?** The registry is updated daily; `lastUpdated` on each row is the provider's own last update.

**Can I get mailing addresses?** Yes, switch on **Include mailing address columns**.

**What happens when my cost cap is hit?** The run stops with a clear status message, the rows already saved stay in your dataset, and the report records `stopReason: "budget"`.

**Something looks wrong.** Open an issue on the Issues tab with your input JSON; issues are answered within two business days.

# Actor input Schema

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

Provider specialty as written in the NUCC taxonomy, for example Dentist, Family Medicine, Nurse Practitioner, Physical Therapist, Chiropractor, Pharmacy. The registry matches this text inside ANY of a provider's taxonomy descriptions (primary or secondary), so 'Dentist' also returns 'Dentist, General Practice', 'Dentist, Pediatric Dentistry' and so on. Use the full description to narrow (for example 'Dentist, Orthodontics and Dentofacial Orthopedics'). Leave empty to export every provider type in the given cities or ZIP codes.

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

Two-letter code of the state or territory of the provider's PRACTICE LOCATION address. One state per run; run the Actor once per state for multi-state lists.

## `cities` (type: `array`):

Practice-location cities, for example Kyle, Austin, San Antonio. Leave empty for the whole state. Matching is case-insensitive and uses the registry's own spelling (no punctuation).

## `postalCodes` (type: `array`):

Practice-location ZIP codes (5 digits, for example 78640) or prefixes with a trailing \* and at least two digits (for example 786\*). Leave empty for the whole state. If both cities and ZIP codes are given, providers matching ANY of them are exported (merged, de-duplicated by NPI).

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

NPI-1 = individual providers (doctors, dentists, nurses, therapists). NPI-2 = organizations (group practices, clinics, hospitals, pharmacies, suppliers).

## `includeMailingAddress` (type: `boolean`):

Adds mailingAddress1, mailingAddress2, mailingCity, mailingState, mailingPostalCode and mailingPhone (often a billing office or PO box). The practice location address is always included.

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

Stop after this many unique providers. Your run's 'Maximum cost per run' also caps the export: at $2.50 per 1,000 providers a $1.00 cap allows 400 providers. Large state-wide specialties (for example all Texas dentists) need 20,000 or more.

## Actor input object example

```json
{
  "taxonomyDescription": "Dentist",
  "state": "TX",
  "cities": [
    "Kyle"
  ],
  "enumerationType": "ALL",
  "includeMailingAddress": false,
  "maxResults": 1000
}
```

# Actor output Schema

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

No description

# 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",
    "cities": [
        "Kyle"
    ],
    "maxResults": 1000
};

// Run the Actor and wait for it to finish
const run = await client.actor("classier_linear/npi-registry-exporter").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",
    "cities": ["Kyle"],
    "maxResults": 1000,
}

# Run the Actor and wait for it to finish
run = client.actor("classier_linear/npi-registry-exporter").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 '{
  "taxonomyDescription": "Dentist",
  "state": "TX",
  "cities": [
    "Kyle"
  ],
  "maxResults": 1000
}' |
apify call classier_linear/npi-registry-exporter --silent --output-dataset

```

## MCP server setup

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

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/2EHCcQIg2KDasv5LL/builds/4g5JZjCi9DHI9HQan/openapi.json
