NPPES NPI Registry Scraper (US Providers)
Pricing
$3.00 / 1,000 provider returneds
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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
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:
| Field | Description |
|---|---|
id | The NPI, e.g. 1760813802 - same as npi, present because every Actor in this series has an id |
source | nppes, constant |
url | https://npiregistry.cms.hhs.gov/provider-view/{npi} - the public NPI Registry page |
npi | The unique 10-digit National Provider Identifier |
enumerationType | NPI-1 (an individual provider) or NPI-2 (an organization) |
providerName | The organization's legal business name for NPI-2; prefix + first + middle + last + suffix for NPI-1 |
firstName / lastName | Individual provider's names (null for organizations) |
credential | Free text exactly as the provider typed it - DDS, D.D.S., dds, DDS, MS are all real values (see Limits and freshness) |
gender | M or F as NPPES publishes it in basic.sex; null for organizations |
organizationName | Legal business name (null for individuals) |
authorizedOfficialName / authorizedOfficialTitle / authorizedOfficialPhone | The named person an organization registered as its authorized official, their job title and their direct line. null for individuals |
primaryTaxonomyCode / primaryTaxonomyDescription | The Healthcare Provider Taxonomy the provider flagged primary, e.g. 1223G0001X / Dentist, General Practice |
licenseNumber / licenseState | The state licence attached to that primary taxonomy |
allTaxonomies | Every taxonomy on the record as {code, description, group, license, state, primary} - a provider may hold up to 15 |
practiceAddress | The practice location on one line: 7259 OWENSMOUTH AVE, CANOGA PARK, CA 91303-1530 |
practiceCity / practiceState / practiceZip | The 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 / practiceFax | Phone and fax at the practice location |
mailingAddress | The mailing address on one line - often, but not always, the same as the practice address |
enumerationDate | Date the NPI was issued, YYYY-MM-DD |
lastUpdated | Date the provider last revised the record, YYYY-MM-DD |
status | Active or Deactivated |
fetchedAt | ISO 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
| Input | Type | Default | Description |
|---|---|---|---|
taxonomies | string[] | ["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. |
states | string[] | ["CA"] | Two-letter codes, including territories (PR, GU), military (AE) and the foreign-address codes XX/ZZ. Each is queried separately. |
cities | string[] | none | City names as NPPES stores them, usually upper case. SAN* is a prefix search. |
postalCodes | string[] | none | A 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*). |
enumerationType | string | both | both, NPI-1 (individuals) or NPI-2 (organizations). Picking one also doubles how deep a single query reaches. |
addressPurpose | string | LOCATION | Which address the city/state/ZIP filters match: LOCATION (any practice location), ANY (the API's own default - mailing address too), MAILING, PRIMARY, SECONDARY. |
organizationName | string | none | Type 2 legal business name; Kaiser* is a prefix search. NPPES also searches "doing business as" and former names. |
lastName / firstName | string | none | Type 1 provider names; Smith* is a prefix search. First names also match common aliases (Robert for Bob). |
npiNumbers | string[] | none | Ten-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 / enumeratedTo | string | none | Keep only NPIs issued in this YYYY-MM-DD window. Applied after fetching - the API has no date parameter (see Limits and freshness). |
updatedWithinDays | integer | none | Keep only records revised in the last N days. Applied after fetching. |
maxItems | integer | 500 | Stop after this many providers. You are charged per provider, so this is also the cost cap. |
maxRequests | integer | 1000 | Budget 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.
licenseNumberis 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,practiceFaxand theauthorizedOfficial*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, sincepracticeFaxis 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=201silently returns 200, andskip=1001returns byte-for-byte the same page asskip=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 byenumeration_type, giving individuals and organizations a 1,200 ceiling each. Then by ZIP-code prefix: no ZIP filter becomes00*…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 withcomplete: trueand 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=90210also matches records stored as902101234, 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 inSUMMARY.cellsUnsplittable, and setscomplete: 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 withstates: ["XX"]or["ZZ"], the codes NPPES puts on foreign addresses. SUMMARY.completeis the completeness guarantee. It istrueonly 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,maxRequestsand the Apify spend limit each set it tofalse, 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
fetchWithRetryretries 429 and 5xx with exponential back-off, honouringRetry-After. - The API has no date parameter of any kind.
enumeratedFrom,enumeratedToandupdatedWithinDaysare 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.scannedversusSUMMARY.pushedshows the ratio; add a state, city or ZIP filter to keep it sane. addressPurposematters 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 forstate=CAwith no address purpose, 2 had their practice location outside California and matched only on the mailing address. This Actor therefore defaults toLOCATION, and everypractice*field in the output is that location. SetaddressPurpose: "ANY"to get the API's behaviour back.- An unknown state code returns nothing rather than an error.
state=QQanswers HTTP 200 withresult_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 theXX/ZZforeign placeholders - and refuses to start on anything else. credentialis 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 inDDS, MS.- NPPES filler is removed. The enumerator writes a literal
--intoname_prefix,name_suffixand 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 asnullrather than as--,.orN/A, soproviderNamenever comes out asRONALD AANERUD --- not one--survived into the 52,265 delivered Californian records. Nine-digit ZIPs become91303-1530; ten-digit bare phone numbers become818-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 andaddresses[1]the mailing address. Live responses putMAILINGfirst on the records sampled, so this Actor selects onaddress_purpose. All 1,200 sampled records carried exactly oneLOCATIONand oneMAILINGentry; 78 also had secondary practice locations, which the API returns in a separatepracticeLocationsarray. LOCATIONincludes secondary practice locations; the output reports the primary one. Thepractice*fields are the provider's primary practice location, butaddressPurpose: "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. SetaddressPurpose: "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 staysnullrather than being invented, andtaxonomy_group- empty on 966 of 1,419 sampled taxonomy entries - becomesnullrather 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
lastUpdatedwas 2026-09-07 (the previous day) and the newestenumerationDate2026-09-04. The 52,265-record Californian run agreed - newestlastUpdatedandenumerationDateboth 2026-09-07, oldestenumerationDate2005-05-23, the month NPIs were first issued. Records are revised in place, so re-run with an overlapping window and uselastUpdatedto spot changes. Search results in every sample wereActive; CMS advises that only the NPI and deactivation date be shown for deactivated NPIs, so treat aDeactivatedstatus 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
lastUpdatedto 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.