Skip to main content
List methods in the Cloudflare API return paginated results. The SDK provides convenient auto-pagination and manual pagination methods.

Auto-pagination with async iterators

Use for await...of syntax to automatically fetch all pages:
import Cloudflare from 'cloudflare';

const client = new Cloudflare();

async function fetchAllAccounts() {
  const allAccounts = [];
  
  // Automatically fetches more pages as needed
  for await (const account of client.accounts.list()) {
    allAccounts.push(account);
  }
  
  return allAccounts;
}
The SDK handles pagination transparently, fetching additional pages as you iterate.

Manual pagination

For more control, fetch pages manually:
let page = await client.accounts.list();

// Process first page
for (const account of page.result) {
  console.log(account);
}

// Fetch subsequent pages
while (page.hasNextPage()) {
  page = await page.getNextPage();
  
  for (const account of page.result) {
    console.log(account);
  }
}

Pagination types

The SDK supports multiple pagination styles used across Cloudflare’s API:
Page-based pagination with items wrapped in a result object:
interface V4PagePaginationResponse<Item> {
  result: {
    items?: Array<Item>;
  };
  result_info: {
    page?: number;
    per_page?: number;
  };
}
Query parameters:
interface V4PagePaginationParams {
  page?: number;
  per_page?: number;
}

Working with paginated results

Check for more pages

const page = await client.accounts.list();

if (page.hasNextPage()) {
  console.log('More results available');
}

Access result metadata

const page = await client.accounts.list();

// Page information
console.log('Current page:', page.result_info.page);
console.log('Items per page:', page.result_info.per_page);
console.log('Item count:', page.result_info.count);

// Cursor (for cursor-based pagination)
console.log('Next cursor:', page.result_info.cursor);

Iterate through pages

for await (const page of client.accounts.list().iterPages()) {
  console.log(`Processing page with ${page.result.length} items`);
  
  for (const account of page.result) {
    console.log(account.name);
  }
}

Pagination parameters

Control pagination behavior with query parameters:
// Page-based pagination
const page = await client.accounts.list({
  page: 2,
  per_page: 50,
});

// Cursor-based pagination
const cursorPage = await client.zones.list({
  cursor: 'previous-cursor-value',
  per_page: 100,
});
page
number
Page number to fetch (1-indexed, page-based pagination only)
per_page
number
Number of items per page
limit
number
Number of items to return (cursor-limit pagination only)
cursor
string
Cursor token for fetching the next page (cursor-based pagination only)

Advanced patterns

Process items in batches

const BATCH_SIZE = 100;
const batches = [];
let batch = [];

for await (const account of client.accounts.list({ per_page: 50 })) {
  batch.push(account);
  
  if (batch.length >= BATCH_SIZE) {
    batches.push(batch);
    batch = [];
  }
}

if (batch.length > 0) {
  batches.push(batch);
}

console.log(`Processed ${batches.length} batches`);

Limit total results

const MAX_ITEMS = 500;
const accounts = [];

for await (const account of client.accounts.list()) {
  accounts.push(account);
  
  if (accounts.length >= MAX_ITEMS) {
    break;
  }
}

Filter while paginating

const activeZones = [];

for await (const zone of client.zones.list()) {
  if (zone.status === 'active') {
    activeZones.push(zone);
  }
}

console.log(`Found ${activeZones.length} active zones`);

Parallel processing

const pages = [];

// Collect all pages
for await (const page of client.accounts.list().iterPages()) {
  pages.push(page.result);
}

// Process pages in parallel
await Promise.all(
  pages.map(async (pageResults) => {
    // Process each page
    for (const account of pageResults) {
      await processAccount(account);
    }
  })
);

Single page responses

Some endpoints return non-paginated results using SinglePage:
interface SinglePageResponse<Item> {
  result: Array<Item>;
}
These responses work with the same iterator pattern but never have additional pages:
for await (const item of client.someEndpoint.list()) {
  console.log(item);
}
// Only iterates once, no additional pages

Performance considerations

1

Choose appropriate page sizes

Balance between request count and memory usage:
// Fewer requests, more memory
client.zones.list({ per_page: 1000 });

// More requests, less memory
client.zones.list({ per_page: 50 });
2

Use cursor pagination for large datasets

Cursor-based pagination provides stable results even as data changes:
for await (const log of client.logpush.jobs.list()) {
  // Cursor pagination handles concurrent modifications
}
3

Process items as they arrive

Avoid loading all results into memory:
// Good: Stream processing
for await (const zone of client.zones.list()) {
  await processZone(zone);
}

// Bad: Load everything first
const allZones = [];
for await (const zone of client.zones.list()) {
  allZones.push(zone);
}
await processZones(allZones);
4

Implement pagination limits

Protect against runaway pagination:
const MAX_PAGES = 100;
let pageCount = 0;

for await (const page of client.zones.list().iterPages()) {
  if (++pageCount > MAX_PAGES) {
    throw new Error('Pagination limit exceeded');
  }
  // Process page
}

Build docs developers (and LLMs) love