NPI Registry Scraper & API - US Doctors, Dentists & Clinics avatar

NPI Registry Scraper & API - US Doctors, Dentists & Clinics

Pricing

from $5.84 / 1,000 provider returneds

Go to Apify Store
NPI Registry Scraper & API - US Doctors, Dentists & Clinics

NPI Registry Scraper & API - US Doctors, Dentists & Clinics

For medical device and pharma sales, credentialing and provider directories: search the official NPPES registry for US doctors, dentists and clinics by specialty, city, ZIP, surname or organisation. 1,200 unique providers per run with zero duplicate rows. No API key, no login.

Pricing

from $5.84 / 1,000 provider returneds

Rating

0.0

(0)

Developer

NeverEmpty

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

5 hours ago

Last modified

Share

NPI Registry Scraper & API

For healthcare sales and lead lists, provider-directory and credentialing work, claims and payer analytics, and medical market research: US healthcare providers — doctors, dentists, therapists, pharmacies, clinics and hospitals — from the official NPPES NPI registry run by the Centers for Medicare & Medicaid Services, as flat rows.

The registry's paging silently hands you the same records over and over, and this Actor refuses to. Measured against the live API on 2026-09-10: limit is capped at 200 (ask for 1,200 and you get 200, no error), and the paging offset stops being honoured past roughly 1,000 recordsskip=1000 and skip=20000 overlap 200 of 200. A reader that trusts the offset keeps collecting the same page forever. Asking this Actor for 2,000 dentists in California returns 1,200 unique providers and zero duplicates, not 2,000 rows of which 800 are repeats — and it tells you the ceiling was hit and suggests how to narrow the search.

The registry also returns its errors with HTTP 200. A rejected search comes back as a normal-looking success with an error body, so a typo looks exactly like "no such providers". Here you get the registry's exact wording back instead. Measured on 2026-09-10 for New York, Cardiovascular Disease returned 200 providers and Kaiser Permanente returned 200, while a rejected term was reported as rejected.

Organisations and individuals are separated by providerType, so a table of 500 providers splits cleanly. You are charged only for unique rows you receive. No API key, no scraping, no proxy. Export as JSON, CSV or Excel.

{
"specialty": "dentist",
"state": "CA",
"maxProviders": 500
}

What this fixes about the raw API

Everything below was measured against the live API on 2026-09-10, not read from documentation.

1. The registry returns its errors with HTTP 200

A rejected search does not come back as an error status. It comes back as HTTP 200 with this body:

{"Errors":[{"description":"Field state requires additional search criteria","field":"state","number":"07"}]}

There is no result_count at all. Read the status and count the results and you conclude the search worked and found nobody - so state=CA on its own silently becomes "there are no providers in California".

Three rejections measured:

What was askedWhat the registry says
Nothing at allNo valid search criteria provided
state=CA aloneField state requires additional search criteria
An unknown specialtyNo taxonomy codes found with entered description

Each comes back here as a row that says the search was rejected, with the registry's own wording. A search that genuinely matched nobody gets a different row that says so. Neither is charged, and neither is ever reported as the other.

2. limit is capped at 200, and paging stops working past about 1,000

Ask for 201 and you get 200. Ask for 1,200 and you get 200. No error, no warning.

Worse, the paging offset stops being honoured past roughly 1,000 records. Measured on taxonomy_description=dentist&state=CA&limit=200:

skipfirst NPI returnedlast NPI returned
80019327721911295652956
1,00012354609161710697255
1,20012354609161710697255
2,00012354609161710697255
20,00012354609161710697255

skip=1000 and skip=20000 overlap 200 of 200. A reader that trusts the offset keeps collecting the same page forever. This Actor remembers every NPI it has delivered, drops repeats before they reach you, and stops when a page brings nothing new - then returns an uncharged row saying how far the search could actually reach and suggesting how to narrow it. Asking for 2,000 dentists in California returns 1,200 unique providers and zero duplicates, not 2,000 rows of which 800 are repeats.

The registry needs a city, a postal code, a specialty, a surname or an organisation name alongside it. That is checked before the run starts, with a message saying what to add, rather than burning a request to be told no.

4. Individuals and organisations are different records

An individual (NPI-1) has a surname, a credential and a licence. An organisation (NPI-2) has a legal name and an authorised official. Fields belonging to the other kind are left empty rather than filled with a blank string, so a table of 500 providers can be split cleanly by providerType.

5. Personal sex is not returned

The registry publishes a sex field on individual records. It is not in the output here: it is a personal attribute with no business use in a provider directory, and leaving it out costs the dataset nothing.

6. The registry's specialty vocabulary is not everyday English

taxonomy_description matches the registry's own official taxonomy names, not the words people use. Measured on 2026-09-10 for New York:

What you typeWhat you get
cardiologistRejected - No taxonomy codes found with entered description
cardiology7 providers
Cardiovascular Disease200 providers

The same applies to organisation names, which match the registered legal name: Kaiser returned 15 records while Kaiser Permanente returned 200. When a term is rejected, you get the registry's exact wording back rather than an empty table, so you can see that the word was the problem.

What you get

npi, npiUrl, providerType, organizationName, lastName, firstName, middleName, credential, soleProprietor, authorizedOfficialName, authorizedOfficialTitle, primaryTaxonomy, primaryTaxonomyCode, primaryTaxonomyLicense, primaryTaxonomyState, allTaxonomies, practiceAddress1, practiceCity, practiceState, practicePostalCode, practicePhone, practiceFax, mailingAddress1, mailingCity, mailingState, mailingPostalCode, otherNames, enumerationDate, lastUpdated, deactivationDate, providerStatus.

The practice address and the mailing address are separate columns, because for a large share of providers they are different places and collapsing them loses the one you wanted.

Input

FieldWhat it does
specialtyA specialty as the registry writes it: dentist, cardiology, pharmacy.
stateTwo-letter code. Refused on its own - combine it with another field.
city / postalCodeEither works as a search on its own.
lastName / firstNameIndividual practitioners.
organizationNamePractices, clinics, hospitals, suppliers.
npiA specific 10-digit NPI.
providerTypeNPI-1 individual or NPI-2 organisation. Refused on its own.
countryCodeTwo-letter code. Refused on its own.
maxProvidersHow many to return. Collected 200 at a time, and capped in practice by the registry's ~1,000-record paging ceiling for any one search. You are charged only for unique rows you receive.
maxRetriesAttempts per request.

No search field carries a default, so nothing is ever added to your search that you did not ask for. If you run it with everything blank it falls back to dentists in California and says so in the log.

Source and licence

NPPES NPI Registry API (npiregistry.cms.hhs.gov). The registry is published by the US Centers for Medicare & Medicaid Services as public data; works of the US federal government are in the public domain. The records are provider business information that CMS publishes for exactly this purpose. This Actor makes plain HTTPS requests to the documented JSON endpoint; it does not scrape any web page and needs no API key or proxy.