NPPES API Pagination — skip, limit & Getting All Results
The NPPES API returns a maximum of 200 records per request. If your search matches
more providers than that — a common specialty or state search easily returns thousands
— you need to paginate using the skip and limit parameters.
This guide covers exactly how NPPES pagination works, the gotchas that break naive
implementations, and when the pagination model becomes impractical for your use case.
The two pagination parameters: limit and skip
| Parameter | Default | Maximum | Purpose |
|---|---|---|---|
limit |
10 | 200 | Number of records to return per request |
skip |
0 | No documented max | Number of records to skip before returning results — used to advance through pages |
Always set limit=200 for pagination — you want the maximum per page to
minimize the number of requests. The default of 10 will make a large result set
require 20× more requests than necessary.
Basic pagination pattern
Stop condition: returned_count < limit — you have reached the last page.
# Page 1
GET https://npiregistry.cms.hhs.gov/api/?taxonomy_description=Cardiology&limit=200&skip=0
# Page 2
GET https://npiregistry.cms.hhs.gov/api/?taxonomy_description=Cardiology&limit=200&skip=200
# Page 3
GET https://npiregistry.cms.hhs.gov/api/?taxonomy_description=Cardiology&limit=200&skip=400
# Stop when the response returns fewer than 200 records (or zero)
Complete pagination loop in Python
import time, requests
def nppes_paginate(params, limit=200, sleep_s=0.3):
"""Fetch all NPPES results for a query, handling pagination."""
results, skip = [], 0
base = "https://npiregistry.cms.hhs.gov/api/"
while True:
page_params = {**params, "limit": limit, "skip": skip, "version": "2.1"}
try:
r = requests.get(base, params=page_params, timeout=10)
if r.status_code in (429, 503):
time.sleep(5) # no Retry-After — back off and retry
continue
r.raise_for_status()
except requests.exceptions.RequestException:
break # abort on persistent failure
batch = r.json().get("results", [])
if not batch:
break # no more pages
results.extend(batch)
skip += len(batch)
if len(batch) < limit:
break # last page — fewer than limit returned
time.sleep(sleep_s) # pace requests to avoid throttle
return results
# Example: all cardiologists in Michigan
providers = nppes_paginate({
"taxonomy_description": "Cardiology",
"state": "MI"
})
Common mistakes that break NPPES pagination
- Not handling the last page. The loop must stop when the response
returns fewer records than
limit, not only when it returns zero. If a result set has exactly 400 records, page 2 returns 200 and page 3 returns 0. If your loop waits for zero, page 2's 200 records get processed but the empty page 3 is still a valid exit condition — handle both. - Incrementing skip by a fixed 200 instead of the actual batch size.
If an intermediate page returns fewer than 200 (possible with some queries), fixed
increment skips records. Use
skip += len(batch), notskip += 200. - No sleep between pages. Rapid sequential requests trigger the undocumented NPPES throttle. A 200–500ms pause significantly reduces 429/503 errors on large result sets.
- Assuming a total count exists. The NPPES API does not return the total number of matching records. You cannot compute the number of pages upfront — you must paginate until the response returns an empty or partial batch.
- Using the default limit=10. The default returns 10 records per
page. Always set
limit=200when paginating to minimize request count.
Node.js pagination example
const sleep = ms => new Promise(r => setTimeout(r, ms));
async function nppesPageAll(params, limit = 200) {
const results = [];
let skip = 0;
while (true) {
const url = new URL("https://npiregistry.cms.hhs.gov/api/");
Object.entries({ ...params, limit, skip, version: "2.1" })
.forEach(([k, v]) => url.searchParams.set(k, v));
const res = await fetch(url);
if (!res.ok) break;
const batch = (await res.json()).results ?? [];
if (!batch.length) break;
results.push(...batch);
skip += batch.length;
if (batch.length < limit) break; // last page
await sleep(300);
}
return results;
}
// Example: all family medicine providers in Texas
const providers = await nppesPageAll({ taxonomy_description: "Family Medicine", state: "TX" });
When NPPES pagination becomes impractical
Pagination works well for result sets up to a few thousand records. It breaks down when:
- The result set is very large. A query like "all individual providers in California" can return hundreds of thousands of records, requiring thousands of sequential requests. At 300ms per request, that is many hours of runtime — with no guarantee the API stays available throughout.
- You need to stay current. Each paginated run is a point-in-time snapshot. If records change mid-pagination (NPPES updates daily), your collected dataset is internally inconsistent.
- You need enriched data. The NPPES API returns only raw registry fields. Adding Medicare enrollment, PECOS IDs, or LEIE flags requires separate queries to other sources for each of the thousands of records you paginated.
For result sets beyond a few thousand records, consider the NPI Bulk Lookup API against a commercial NPI Registry API with defined quotas, or the CMS NPPES data dissemination file for a full static dataset.
Related guides
- NPPES API Rate Limits — the 200-record cap, undocumented throttling, and bulk export constraints
- NPI Bulk Lookup API — when NPPES pagination isn't sufficient: commercial API with defined quotas
- NPPES API Down? — handling 429, 503, and timeouts in your pagination loop
- NPPES API vs NPI Registry API — when to switch from the free API to a commercial alternative
- Healthcare Provider Data API — enrichment use case for paginated specialty or state provider queries
- Provider Directory API — using NPPES pagination to populate and sync a compliant provider directory
The NPI Registry API provides 12,500–125,000 requests per month on paid plans — enough to run large validation and enrichment jobs reliably, with enriched PECOS and LEIE data in every response.
Explore the API & start a free trial →Frequently asked questions
What is the maximum limit value for the NPPES API?
The limit parameter accepts a maximum of 200, as documented in the
official NPPES API documentation.
Always set limit=200 when paginating to minimize request count.
How does NPPES API pagination work?
Set limit=200 and increment skip by the number of records
returned each page. Stop when a response returns fewer than limit records.
There is no total count endpoint — you discover the end by fetching it.
Does the NPPES API return a total record count?
No. result_count in the response is the count for the current page, not
the total matching records. You cannot know the total without paginating to the end.
What happens if I paginate too fast?
Rapid requests trigger undocumented throttling — HTTP 429 or 503 with no
Retry-After header. Add a 200–500ms sleep between pages. See
NPPES API rate limits explained for the full
picture.