Fetch every page of a paginated API with an async generator
Iterate cursor-paginated API results with for await, loading pages lazily and stopping early when needed.
- JavaScript
- GreenSnippets
- MIT
- Executed with Node.js 22
async function* paginate(fetchPage, { maxPages = 1000 } = {}) {
let cursor;
for (let page = 0; page < maxPages; page++) {
const { items, next_cursor: next } = await fetchPage(cursor);
yield* items;
if (!next) return;
cursor = next;
}
throw new Error(`Pagination exceeded ${maxPages} pages`);
}Example / expected output
for await (const user of paginate((cursor) => api.listUsers({ cursor }))) {
console.log(user.id);
}How it works
An async generator hides the pagination loop: callers just for await over items. Pages load lazily, so breaking out of the loop stops further requests. This version follows a next_cursor field; adapt the property names to your API (some use Link headers or page numbers).
Add a hard page cap so a buggy server that never ends pagination cannot loop forever.
Related snippets
- PHP Tested
Retry a callable with exponential backoff in PHP
Re-run flaky operations with growing delays and jitter, only for chosen exception types.
- TypeScript Tested
Typed fetch helper that checks the response
A fetch wrapper that throws on HTTP errors and validates the JSON body with a type guard.
- JavaScript Tested
Verify a webhook signature in Node.js
Validate an HMAC-SHA256 webhook against the raw request body with a constant-time comparison and replay window.
- PHP Tested
Decode JSON safely in PHP
Parse JSON with exceptions on error and a depth limit, instead of silently getting null.

