NPPES NPI Registry Scraper (US Providers) avatar

NPPES NPI Registry Scraper (US Providers)

Pricing

$3.00 / 1,000 provider returneds

Go to Apify Store
NPPES NPI Registry Scraper (US Providers)

NPPES NPI Registry Scraper (US Providers)

US health care providers from the official CMS NPPES NPI Registry API: NPI, taxonomy, licence, practice address, phone, fax and authorized official.

Pricing

$3.00 / 1,000 provider returneds

Rating

0.0

(0)

Developer

Jason

Jason

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Pulls US health care providers from the NPPES NPI Registry, the national directory every doctor, dentist, pharmacy, clinic and hospital in the United States must be listed in to bill insurance, through the official CMS Read API v2.1. No API key, no account, no browser automation. You get one flat JSON record per provider with the 10-digit NPI, the provider or organization name, credentials, the Healthcare Provider Taxonomy code and description, the state licence number, the full practice address with phone and fax, the mailing address, the organization's authorized official with their title and direct phone, and the enumeration and last-updated dates - filtered by taxonomy, state, city, ZIP prefix, NPI type, name, or a list of NPIs to look up directly.

The one thing the API cannot do, and this Actor can. Any single NPI Registry query returns at most 1,200 records - 200 rows a request and a skip that stops at 1,000 - however many providers actually match. Ask it for dentists in California and you get 1,200 of the 52,265 there are, with no warning that the other 51,065 exist. This Actor detects a query that has filled that ceiling and automatically partitions it - first by NPI type, then down the ZIP-code prefix tree - re-running the narrower queries until every record is reachable, de-duplicating across them, and writing a complete flag to the run summary so you know whether the answer you have is the whole answer.

What you get

Every record contains:

FieldDescription
idThe NPI, e.g. 1760813802 - same as npi, present because every Actor in this series has an id
sourcenppes, constant
urlhttps://npiregistry.cms.hhs.gov/provider-view/{npi} - the public NPI Registry page
npiThe unique 10-digit National Provider Identifier
enumerationTypeNPI-1 (an individual provider) or NPI-2 (an organization)
providerNameThe organization's legal business name for NPI-2; prefix + first + middle + last + suffix for NPI-1
firstName / lastNameIndividual provider's names (null for organizations)
credentialFree text exactly as the provider typed it - DDS, D.D.S., dds, DDS, MS are all real values (see Limits and freshness)
genderM or F as NPPES publishes it in basic.sex; null for organizations
organizationNameLegal business name (null for individuals)
authorizedOfficialName / authorizedOfficialTitle / authorizedOfficialPhoneThe named person an organization registered as its authorized official, their job title and their direct line. null for individuals
primaryTaxonomyCode / primaryTaxonomyDescriptionThe Healthcare Provider Taxonomy the provider flagged primary, e.g. 1223G0001X / Dentist, General Practice
licenseNumber / licenseStateThe state licence attached to that primary taxonomy
allTaxonomiesEvery taxonomy on the record as {code, description, group, license, state, primary} - a provider may hold up to 15
practiceAddressThe practice location on one line: 7259 OWENSMOUTH AVE, CANOGA PARK, CA 91303-1530
practiceCity / practiceState / practiceZipThe same address split up; practiceZip is ZIP+4 when NPPES holds nine digits, and its first five characters are always the 5-digit ZIP
practicePhone / practiceFaxPhone and fax at the practice location
mailingAddressThe mailing address on one line - often, but not always, the same as the practice address
enumerationDateDate the NPI was issued, YYYY-MM-DD
lastUpdatedDate the provider last revised the record, YYYY-MM-DD
statusActive or Deactivated
fetchedAtISO timestamp of the run that produced the record

The dataset has three views: Overview (NPI, name, taxonomy, city, phone, link), Contacts (credential, authorized official, phone, fax, both addresses) and Taxonomy and licence (codes, licence number and state, dates, status).

Input

InputTypeDefaultDescription
taxonomiesstring[]["Dentist"]Taxonomy descriptions: a classification (Dentist, Pharmacy, Chiropractor, Optometrist), a full description (Dentist, General Practice), or a prefix with * and at least two leading characters (Nurse*). Each is queried separately and the results merged.
statesstring[]["CA"]Two-letter codes, including territories (PR, GU), military (AE) and the foreign-address codes XX/ZZ. Each is queried separately.
citiesstring[]noneCity names as NPPES stores them, usually upper case. SAN* is a prefix search.
postalCodesstring[]noneA 5-digit ZIP (90210, which also matches the stored ZIP+4), a full ZIP+4, or a prefix of at least two digits (902 / 902*).
enumerationTypestringbothboth, NPI-1 (individuals) or NPI-2 (organizations). Picking one also doubles how deep a single query reaches.
addressPurposestringLOCATIONWhich address the city/state/ZIP filters match: LOCATION (any practice location), ANY (the API's own default - mailing address too), MAILING, PRIMARY, SECONDARY.
organizationNamestringnoneType 2 legal business name; Kaiser* is a prefix search. NPPES also searches "doing business as" and former names.
lastName / firstNamestringnoneType 1 provider names; Smith* is a prefix search. First names also match common aliases (Robert for Bob).
npiNumbersstring[]noneTen-digit NPIs to look up directly, one request and one record each. Ignores the search filters above (the API rejects number combined with anything else); the date filters still apply.
enumeratedFrom / enumeratedTostringnoneKeep only NPIs issued in this YYYY-MM-DD window. Applied after fetching - the API has no date parameter (see Limits and freshness).
updatedWithinDaysintegernoneKeep only records revised in the last N days. Applied after fetching.
maxItemsinteger500Stop after this many providers. You are charged per provider, so this is also the cost cap.
maxRequestsinteger1000Budget on API calls, which also bounds the run time. One call returns up to 200 providers; each level of partitioning costs up to 100 probe calls.

The API insists on at least one of taxonomies, cities, postalCodes, organizationName, lastName, firstName or npiNumbers: a state, an NPI type or an address purpose on their own are refused. This Actor checks that, the state codes, the ZIP shapes, the two-character wildcard rule and the date formats before the first request, and stops the run with the reason as its status, so a typo costs nothing.

Example - every dental practice (organizations only) in the Los Angeles 902 ZIP area, with the authorized official's phone:

{
"taxonomies": ["Dentist"],
"postalCodes": ["902*"],
"enumerationType": "NPI-2",
"addressPurpose": "LOCATION",
"maxItems": 2000
}

Example - newly enumerated providers to reach before anyone else, run weekly:

{
"taxonomies": ["Nurse Practitioner"],
"states": ["TX"],
"enumeratedFrom": "2026-08-01",
"maxItems": 500
}

Example - a complete state download that partitions itself past the API ceiling:

{ "taxonomies": ["Dentist"], "states": ["CA"], "maxItems": 100000, "maxRequests": 3000 }

That input with maxRequests at 900 returned 52,265 providers in 8 minutes on 8 September 2026 - see Limits and freshness.

Example - re-check a list of NPIs you already hold, for licence and address changes:

{ "npiNumbers": ["1760813802", "1497431100"], "maxItems": 100 }

Output example

A real record from a live run on 8 September 2026 ({"taxonomies": ["Dentist"], "states": ["CA"], "enumerationType": "NPI-1", "maxItems": 3}), unedited:

{
"id": "1497431100",
"source": "nppes",
"url": "https://npiregistry.cms.hhs.gov/provider-view/1497431100",
"npi": "1497431100",
"enumerationType": "NPI-1",
"providerName": "Dr. SOHRAB AALAM",
"firstName": "SOHRAB",
"lastName": "AALAM",
"credential": "DMD",
"gender": "M",
"organizationName": null,
"authorizedOfficialName": null,
"authorizedOfficialTitle": null,
"authorizedOfficialPhone": null,
"primaryTaxonomyCode": "122300000X",
"primaryTaxonomyDescription": "Dentist",
"licenseNumber": "108817",
"licenseState": "CA",
"allTaxonomies": [
{ "code": "122300000X", "description": "Dentist", "group": null, "license": "108817", "state": "CA", "primary": true }
],
"practiceAddress": "17010 RED HILL AVE STE D, IRVINE, CA 92614-5626",
"practiceCity": "IRVINE",
"practiceState": "CA",
"practiceZip": "92614-5626",
"practicePhone": "949-975-0150",
"practiceFax": null,
"mailingAddress": "17010 RED HILL AVE STE D, IRVINE, CA 92614-5626",
"enumerationDate": "2023-06-26",
"lastUpdated": "2023-06-26",
"status": "Active",
"fetchedAt": "2026-09-08T05:15:04.509Z"
}

An organization (NPI-2) from the same registry looks the same but fills the other half of the record - NPI 1760813802, "providerName": "101 DENTAL GROUP", "organizationName": "101 DENTAL GROUP", "authorizedOfficialName": "AMIR H CHOROOMI", "authorizedOfficialTitle": "dentist", "authorizedOfficialPhone": "818-735-3800", "practicePhone": "818-999-9900", "practiceFax": "818-999-9978", and firstName, lastName, credential and gender all null.

Every run also writes a SUMMARY record to the key-value store with the filters used, how many query cells were read, how many hit the 1,200-record ceiling and were partitioned, how many duplicates the partitioning produced, how many records the date filters dropped, the request count, and the complete flag described below.

Pricing

Pay per result: US$0.003 per provider delivered (US$3 per 1,000 providers). You are charged only for records pushed to the dataset; a run that returns nothing, or that fails validation before its first request, costs nothing. Runs on the Apify free plan are limited by the platform's free-tier usage allowance.

Data source and licence

  • Source. GET https://npiregistry.cms.hhs.gov/api/?version=2.1, the NPPES Read API operated by the Centers for Medicare and Medicaid Services. It is public and needs no key, no account and no registration; CMS states plainly that "There is no charge to use the NPI Registry". Documentation: https://npiregistry.cms.hhs.gov/api-page (read 8 September 2026). Versions 1.0 and 2.0 are retired; this Actor uses 2.1.
  • Licence. NPPES provider data is produced by CMS, an agency of the US Department of Health and Human Services, as part of its official duties, which makes it a US Government work: not subject to domestic copyright under 17 U.S.C. § 105, and free to reuse commercially. CMS publishes it under the NPPES Data Dissemination Notice (CMS-6060-N, 72 FR 30011, 30 May 2007), which lists the data elements that are required to be disclosed under the Freedom of Information Act; the registry's own help pages state that "All information produced by the NPPES Read API is provided in accordance with the NPPES Data Dissemination Notice". CMS's own dissemination page confirms the position: "The information disclosed on the NPI Registry and in the downloadable files are FOIA-disclosable and are required to be disclosed under the FOIA" (https://www.cms.gov/medicare/regulations-guidance/administrative-simplification/data-dissemination, read 8 September 2026).
  • Attribution. No attribution wording is mandated. Cite it as "Source: CMS NPPES NPI Registry" and link to the provider page. Do not use the data in a way that implies endorsement by CMS, HHS or any federal official, and do not reuse federal agency logos or trademarks.
  • Not a licence check. CMS's own warning, shown on every NPI Registry page: issuance of an NPI does not ensure or validate that the provider is licensed or credentialed. licenseNumber is what the provider self-reported to NPPES; verify it with the state board before relying on it.
  • Personal data. This dataset is about identified people. providerName, firstName, lastName, credential, gender, practiceAddress, practicePhone, practiceFax and the authorizedOfficial* fields are the professional details of named individuals. They are lawfully public - CMS is required by FOIA to disclose them, and says explicitly that there is "no way to 'opt out' or 'suppress' the NPPES record data for health care providers with active NPIs" - but public is not the same as unrestricted. If you use these records to make contact, the applicable regime is yours to satisfy: TCPA and the FCC rules govern calls, texts and unsolicited faxes to those numbers (the fax provisions in particular, since practiceFax is a fax number and the TCPA's junk-fax rules carry statutory damages); CAN-SPAM governs commercial email if you enrich these records with addresses; state telemarketing and do-not-call registers apply on top; and the GDPR applies if you are processing from, or contacting into, the EU/UK. A sole proprietor's practice address is frequently their home address. Nothing here is legal advice.

Limits and freshness

  • The 1,200-record ceiling is the API's, not this Actor's. CMS documents it: "An API query will return a maximum of 200 results per request. The Skip field in the API will let you skip up to 1000 records ... you can get up to a maximum of 1,200 records over six requests." Verified 8 September 2026: limit=201 silently returns 200, and skip=1001 returns byte-for-byte the same page as skip=1000. There is no total-match count in the response, so a query that matches 50,000 providers looks exactly like one that matches 1,200.
  • How the partitioning works. When the deepest page a query allows (skip=1000) comes back full, the Actor knows the query is capped and splits it. First by enumeration_type, giving individuals and organizations a 1,200 ceiling each. Then by ZIP-code prefix: no ZIP filter becomes 00*99*, an N-digit prefix becomes its ten N+1-digit children, down to a single 5-digit ZIP. Records are de-duplicated by NPI across every cell. Measured 8 September 2026: {"taxonomies": ["Dentist"], "states": ["CA"], "addressPurpose": "LOCATION", "maxItems": 100000, "maxRequests": 900} delivered 52,265 unique dentists - 43.6 times what a single query can reach - in 8 min 7 s over 746 requests and 433 query cells (26 of which had filled the ceiling and were split, 194 of which were empty ZIP prefixes), dropping 33,167 records already seen in a wider cell and finishing with complete: true and not one repeated NPI in the dataset. The same input without partitioning is the 1,200 records the API hands everybody.
  • Where partitioning stops, and what happens then. A single 5-digit ZIP is the floor: postal_code=90210 also matches records stored as 902101234, so a six-digit prefix would silently drop every provider whose address carries only the five-digit ZIP. If one 5-digit ZIP plus one NPI type plus your other filters still holds more than 1,200 providers, the Actor cannot reach the rest - it logs a warning naming that cell, lists it in SUMMARY.cellsUnsplittable, and sets complete: false. It never reports a truncated result as complete. ZIP partitioning only works on numeric US ZIP codes, so a cell that had to be split can miss a provider whose matched address is foreign (postal_code "L1T5A4"); sweep those separately with states: ["XX"] or ["ZZ"], the codes NPPES puts on foreign addresses.
  • SUMMARY.complete is the completeness guarantee. It is true only when every queued cell was read to its end, no cell was left at the ceiling unsplit, the request budget held, and every record the run kept was actually delivered. maxItems, maxRequests and the Apify spend limit each set it to false, and the run log says which one and what to raise.
  • Volumes and speed, measured 8 September 2026 (addressPurpose: "LOCATION"): every dentist practising in Wyoming is 615 records, 4 requests, 5.1 s; Rhode Island 1,068 records, 6 requests, 6.9 s; California 52,265 records (38,074 individuals and 14,191 organizations), 746 requests, 8 min 7 s. The default 500-record run takes 3 requests and about 4 s. A full page of 200 arrives in about 0.65 s, so throughput is roughly 150 records a second while pages are full and 107 a second averaged over the whole Californian run - the difference is the empty ZIP prefixes a deep run has to rule out at one request each.
  • Rate limits. CMS documents none. Twenty consecutive requests with no pacing all returned HTTP 200 (measured 8 September 2026, about 1.4 requests a second end to end). The Actor still paces itself at no more than 5 requests a second, and fetchWithRetry retries 429 and 5xx with exponential back-off, honouring Retry-After.
  • The API has no date parameter of any kind. enumeratedFrom, enumeratedTo and updatedWithinDays are therefore applied by the Actor to records it has already fetched, and results are ordered by name, not by date - so a narrow date window over a broad query reads a great many records to keep a few. It lowers your bill (you pay only for kept records) but not the run time. SUMMARY.scanned versus SUMMARY.pushed shows the ratio; add a state, city or ZIP filter to keep it sane.
  • addressPurpose matters more than it looks. With the API's own default, city, state and ZIP match the mailing address as readily as the practice location, and the two can be in different states: of 50 records returned for state=CA with no address purpose, 2 had their practice location outside California and matched only on the mailing address. This Actor therefore defaults to LOCATION, and every practice* field in the output is that location. Set addressPurpose: "ANY" to get the API's behaviour back.
  • An unknown state code returns nothing rather than an error. state=QQ answers HTTP 200 with result_count: 0 (verified for QQ, JJ, BB, EE on 8 September 2026), so a typo would hand you an empty dataset and no explanation. The Actor validates the code against the 65 two-letter codes NPPES uses - the 50 states, DC, the territories and freely associated states, the three military codes and the XX/ZZ foreign placeholders - and refuses to start on anything else.
  • credential is free text and is published unchanged. Of the 52,265 Californian dentists, 34,044 supplied a credential and wrote it 686 different ways: DDS (15,875), D.D.S. (8,271), DMD (3,216), D.D.S (1,337), D.M.D. (1,217), dds (1,018), DDS, MS (356) and a long tail. Match it case-insensitively with the dots stripped; the Actor does not collapse them to a canonical form, because that would throw away the second qualification in DDS, MS.
  • NPPES filler is removed. The enumerator writes a literal -- into name_prefix, name_suffix and their authorized-official twins when nothing was supplied: 883 of those four fields across a 1,200-record sample held one. Every text field is trimmed, whitespace-collapsed, and published as null rather than as --, . or N/A, so providerName never comes out as RONALD AANERUD -- - not one -- survived into the 52,265 delivered Californian records. Nine-digit ZIPs become 91303-1530; ten-digit bare phone numbers become 818-735-3800; foreign postal codes and numbers are left exactly as published.
  • Addresses are picked by purpose, never by position. The CMS help page says addresses[0] is the practice location and addresses[1] the mailing address. Live responses put MAILING first on the records sampled, so this Actor selects on address_purpose. All 1,200 sampled records carried exactly one LOCATION and one MAILING entry; 78 also had secondary practice locations, which the API returns in a separate practiceLocations array.
  • LOCATION includes secondary practice locations; the output reports the primary one. The practice* fields are the provider's primary practice location, but addressPurpose: "LOCATION" matches any practice location they filed - so a dentist whose main surgery is in Las Vegas and who also practises in Burbank matches a California search and is published with a Nevada practice address. In the 52,265-record Californian run, 395 records (0.76%) had a primary practice location outside California for exactly that reason. Set addressPurpose: "PRIMARY" when the primary location itself has to be inside the filter.
  • Missing values are the provider's, not the Actor's. Across the 52,265-record Californian run: 52,261 had a practice phone (99.99%), 26,185 a fax (50.1%), 46,093 a licence number (88.2%), 34,044 a credential (65.1%), and 38,038 of the 38,074 individuals a gender. All 14,191 organizations carried an authorized official's name. What the provider never filed stays null rather than being invented, and taxonomy_group - empty on 966 of 1,419 sampled taxonomy entries - becomes null rather than an empty string.
  • Freshness. CMS states the API "retrieves data from NPPES daily". Measured 8 September 2026 across 3,600 records in six taxonomies: the newest lastUpdated was 2026-09-07 (the previous day) and the newest enumerationDate 2026-09-04. The 52,265-record Californian run agreed - newest lastUpdated and enumerationDate both 2026-09-07, oldest enumerationDate 2005-05-23, the month NPIs were first issued. Records are revised in place, so re-run with an overlapping window and use lastUpdated to spot changes. Search results in every sample were Active; CMS advises that only the NPI and deactivation date be shown for deactivated NPIs, so treat a Deactivated status as the end of the record's usefulness rather than as a lead.

Use cases

  • Territory lists for medical-device, dental and pharma sales: one run per taxonomy and state gives every practice in the patch with its address, phone, fax and - for organizations - the authorized official's name, title and direct line, ready for a CRM import.
  • Provider directories, credentialing and network build-out: NPI, taxonomy code, self-reported state licence and current practice address for every provider in a region, re-run weekly against lastUpdated to catch moves, closures and new enumerations before your directory goes stale.
  • Market and health-policy analysis: count providers by taxonomy, ZIP or state to map specialty density and care deserts, or track new enumerations over time with enumeratedFrom - the partitioning is what makes a whole-state or whole-specialty census possible at all.

Support

Open an issue on the Actor's Issues tab on Apify Store. Replies within 14 days. Bug reports that name the run id and the input used are fixed fastest.