# US Healthcare Provider Search: Normalized NPI Data (NPPES) (`overlookdata/npimcp-search`) Actor

Search all 9M+ US healthcare providers with no 1,200-result cap. Normalized NPPES data: parsed credentials, deduplicated addresses, OIG exclusion + Medicare enrollment flags, quality scores. Filter by state, specialty, credential. $3 per 1,000 results.

- **URL**: https://apify.com/overlookdata/npimcp-search.md
- **Developed by:** [Aaron Melton](https://apify.com/overlookdata) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 results

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

## US Healthcare Provider Search: Normalized NPI Data

Get every healthcare provider matching your criteria, from the complete US NPPES registry (9.4M+ providers), as clean rows you can use immediately.

### True statewide pulls. No 1,200-result cap.

Most NPI tools on Apify and elsewhere are thin wrappers around the live NPPES API, which returns at most 200 records per request and **1,200 results per query, hard cap**. "Every cardiologist in California" is roughly 5,000 providers. A wrapper cannot deliver that list. This actor is not a wrapper: it queries our own database, built from CMS's full bulk data files, so a 50,000-row statewide pull is just a bigger run.

Several competing listings say this themselves: their advice for a statewide pull is to split your search into ZIP-by-ZIP runs and merge the datasets yourself. That workaround is your time and your money. Here it is just a query.

### Raw NPPES is messy. You are paying us to have cleaned it.

The government registry has no input sanitization. Real examples of what that means, and what this actor returns instead:

| Raw NPPES | This actor |
|---|---|
| `credential = "MSN, APRN, FNP-C"` (free text, 57% of records blank) | `primary_credential = "FNP"` plus every credential parsed and ranked. Filter MDs without also getting the MPH holders. |
| `"123 MAIN ST STE 200"` and `"123 Main St, Suite 200"` as two different addresses | One canonical, deduplicated address with parsed components and a PO Box flag |
| Endpoints, secondary locations, and alternate names shipped as three separate files you must join yourself | One provider record with everything pre-joined |
| Taxonomy code `207RH0003X` | "Internal Medicine, Hematology & Oncology", plus our own 21-bucket buyer-oriented grouping |

CMS's own audit programs have found 45-49% of provider directory listings contain inaccuracies, and only about 8% of NPI records are updated by their providers in a given year. No vendor can fix what providers never report. What we do about it: refresh from CMS weekly, deduplicate and normalize every field, attach a 0-100 quality confidence score to every record so you can filter to high-confidence rows, and stamp every response with the exact NPPES publication date it came from. You always know how fresh your data is.

### Included on every record (no add-on fees)

- **OIG exclusion flag**: is this provider on the HHS exclusion list (LEIE)? Avoid mailing sanctioned providers.
- **Medicare enrollment (PECOS) flag**: set the `medicare_enrolled` input filter to pull "Medicare-accepting providers only."
- **Practice-group clustering**: pull the whole cardiology group at one address in one query.
- **Multi-state licensure**: providers licensed in 3+ states, a telehealth-ready signal.
- **Digital maturity flags**: has a FHIR endpoint, has Direct messaging.
- **Career stage** and newly-enumerated flag: find brand-new practices.
- **Quality confidence score** (0-100) with per-component breakdown.

Other services sell some of these flags separately. What you cannot get elsewhere at usage pricing is the bundle: the flags integrated into normalized, deduplicated records with parsed credentials, priced per result instead of per month.

### Filters

State, specialty (taxonomy classification), credential code, city, ZIP, entity type (individual/organization), and name prefix (first, last, or business name). Set `max_results` to control spend. Set `include_full_record` for the complete enriched record per provider (nested taxonomies, all credentials, locations); leave it off for a compact row.

### Use from AI agents (MCP)

This actor works as an MCP tool out of the box. Point your agent at `mcp.apify.com` with this actor enabled and it can run provider searches directly ("find every dermatology NP in Texas"). Results land in a dataset your agent can page through.

### Pricing

**$3 per 1,000 results** ($0.003 per row pushed to your dataset). No subscription, no minimum. You pay only for rows delivered: duplicates and errors are filtered before they reach your dataset. A 10,000-provider statewide specialty pull costs $30.

### Stability

CMS changes its file formats (a major version cutover happened in March 2026 and broke downstream loaders across the ecosystem). We absorb that churn behind a stable output schema: your integration does not change when CMS's files do.

### Data source and compliance

Data comes from CMS's public NPPES registry (FOIA-disclosed federal data on healthcare *providers*, published for exactly this kind of use) plus other public federal datasets (HHS OIG LEIE, CMS PECOS). This is provider enrollment data. It contains no patient data and no HIPAA-covered information. Records are served as published by CMS, normalized for usability; addresses and phones are as reported by providers to CMS, not independently verified.

# Actor input Schema

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

Filter to providers whose practice address is in this US state. Examples: CA, TX, NY. Territories: PR, GU, AS, MP, VI.

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

NUCC taxonomy classification, e.g., 'Internal Medicine', 'Family Medicine', 'Cardiovascular Disease'. Matching is case-insensitive and whitespace-trimmed, but must otherwise match a classification exactly (no partial/fuzzy match). This is a free-text field, not a dropdown — Apify's static input schemas can't populate a dropdown from a live API call. See the GET /specialties endpoint for the full, current list of valid values.

## `credential` (type: `string`):

Primary credential code, e.g., MD, DO, NP, PA, RN, FNP, PsyD. Matching is case-insensitive and whitespace-trimmed. This is a free-text field, not a dropdown — Apify's static input schemas can't populate a dropdown from a live API call. See the GET /credentials endpoint for the full, current list of valid codes.

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

Practice address city. Prefix match (e.g., 'Sea' matches 'Seattle').

## `postal_code` (type: `string`):

Practice address ZIP. Prefix match (e.g., '902' matches all 902xx ZIPs).

## `entity_type` (type: `string`):

Filter by individual practitioners or organizations.

## `last_name` (type: `string`):

Provider last name. Prefix match.

## `first_name` (type: `string`):

Provider first name. Prefix match.

## `business_name` (type: `string`):

For organizations only. Legal business name prefix.

## `radius_zip` (type: `string`):

5-digit ZIP code to center a radius search on. Requires 'Radius search: miles' to also be set. Precision is ZIP-centroid-level (Census ZCTA Gazetteer), not a per-address geocode — expect roughly +/-1 to 3 mile error, worse for large rural ZIPs. Some ZIPs (PO-Box-only, no residential/business footprint) have no centroid and will return an error; try a neighboring ZIP.

## `radius_miles` (type: `integer`):

Search radius in miles from 'Radius search: center ZIP'. Requires that field to also be set.

## `telehealth` (type: `boolean`):

Filter to providers with a telehealth indicator in the CMS Doctors & Clinicians data. Coverage caveat: this dataset covers Medicare-enrolled clinicians only (~1.3M of ~9.4M NPPES providers) — a provider absent from that dataset is excluded from this filter's TRUE match, not marked false; leaving this off returns providers regardless of telehealth status.

## `has_hospital_affiliation` (type: `boolean`):

Filter to providers with at least one facility affiliation (hospital, home health agency, hospice, nursing home, dialysis facility, inpatient rehab, or long-term care hospital) in the CMS Doctors & Clinicians Facility Affiliation data. Same Medicare-enrolled-clinician coverage caveat as 'Telehealth offered'.

## `graduation_year_min` (type: `integer`):

Filter to providers who graduated medical school in this year or later, per CMS Doctors & Clinicians data. Same Medicare-enrolled-clinician coverage caveat as 'Telehealth offered' — providers with no CMS DAC record are excluded from this filter.

## `graduation_year_max` (type: `integer`):

Filter to providers who graduated medical school in this year or earlier, per CMS Doctors & Clinicians data. Must be >= 'Medical school graduation year (minimum)' when both are set.

## `is_rural` (type: `boolean`):

Filter to providers whose practice ZIP has a USDA ERS primary RUCA code of 4 or higher (rural — Micropolitan/Small town/Rural, per USDA ERS's own Metropolitan/Micropolitan/Small town/Rural grouping). ZIP-level approximation, not a per-address determination. Coverage caveat: a ZIP the RUCA file doesn't cover is excluded from this filter's TRUE match, not marked false; leaving this off returns providers regardless of rural/urban status.

## `exclude_license_issues` (type: `boolean`):

Filter to providers whose Texas board license status is verifiably not-current (delinquent, inactive, retired, cancelled, suspended, revoked, surrendered, or deceased), sourced from the TX Medical Board (TMB) and TX Board of Nursing (BON) free bulk license rosters, joined on NPPES's self-reported license number and name-verified. TX-only coverage at this release. Coverage caveat: this is NOT a clean-license guarantee — a provider with no board match (unrecognized/unreported license number, or a name mismatch against the board record) is excluded from this filter's TRUE match, not marked as currently licensed; leaving this off returns providers regardless of license status.

## `medicare_enrolled` (type: `boolean`):

Filter to providers enrolled in Medicare, per CMS PECOS enrollment data. Leaving this off returns providers regardless of enrollment status; setting it on returns only enrolled providers (there is no 'non-enrolled only' mode).

## `max_results` (type: `integer`):

Stop after this many results. Each pushed result is billed.

## `include_full_record` (type: `boolean`):

When ON, fetch the full enriched record for each result (taxonomies, credentials, secondary locations, OIG exclusion, PECOS Medicare enrollment, practice group, digital maturity flags, quality score). When OFF, only the basic search fields are returned. Each provider record is one billable result either way; the toggle controls how rich each row is.

## Actor input object example

```json
{
  "state": "GA",
  "specialty": "Family Medicine",
  "max_results": 25,
  "include_full_record": false
}
```

# Actor output Schema

## `providers` (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 = {
    "state": "GA",
    "specialty": "Family Medicine",
    "max_results": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("overlookdata/npimcp-search").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 = {
    "state": "GA",
    "specialty": "Family Medicine",
    "max_results": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("overlookdata/npimcp-search").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 '{
  "state": "GA",
  "specialty": "Family Medicine",
  "max_results": 25
}' |
apify call overlookdata/npimcp-search --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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