When building applications that interact with the Claude Code API, handling large datasets efficiently becomes crucial. Pagination isn’t just about splitting data into chunks—it’s about creating a smooth, performant experience for your users while respecting API rate limits and response times.
This guide covers practical pagination strategies you can implement today, with code examples that work with real-world scenarios.
Understanding Cursor-Based Pagination
The Claude Code API uses cursor-based pagination rather than offset-based approaches. This means each response includes a cursor token that points to the next set of results. Unlike traditional offset pagination (skip 10, take 10), cursor-based pagination is more stable when data changes between requests.
Here’s how to implement basic cursor pagination:
import anthropic
client = anthropic.Anthropic(api_key="your-api-key")
def fetch_all_messages(thread_id, max_results=100):
"""Fetch all messages from a thread with pagination."""
messages = []
cursor = None
while len(messages) < max_results:
response = client.messages.list(
thread_id=thread_id,
cursor=cursor,
limit=50
)
messages.extend(response.data)
if not response.has_more:
break
cursor = response.cursor
return messages[:max_results]
The key insight is that you always check has_more before attempting to fetch the next page. This prevents unnecessary API calls and helps you handle edge cases where the dataset is smaller than expected.
Setting Appropriate Page Sizes
The limit parameter controls how many items return per request. The Claude Code API typically allows limits between 1 and 100, but choosing the right value depends on your use case.
For interactive applications where users scroll through results, a limit of 20-30 provides a good balance:
async function fetchConversations(limit = 25) {
const response = await fetch('/api/conversations', {
method: 'POST',
body: JSON.stringify({ limit })
});
const data = await response.json();
return {
conversations: data.conversations,
nextCursor: data.cursor
};
}
For background jobs or data exports where throughput matters, you might push toward the maximum limit. However, larger page sizes increase memory usage and response latency, so profile your application to find the sweet spot.
Handling Rate Limits Gracefully
When paginating through large datasets, you’ll inevitably encounter rate limits. The Claude Code API returns a 429 status code when you’ve exceeded your quota. Implement exponential backoff to handle this gracefully:
import time
import requests
def fetch_with_retry(url, max_retries=3):
"""Fetch with exponential backoff on rate limits."""
for attempt in range(max_retries):
response = requests.get(url)
if response.status_code == 200:
return response.json()
if response.status_code == 429:
wait_time = 2 ** attempt
print(f"Rate limited. Waiting {wait_time}s...")
time.sleep(wait_time)
response.raise_for_status()
raise Exception("Max retries exceeded")
This pattern works especially well when combining pagination with other API operations. If you’re building a tool that uses the pdf skill to process documents while also fetching conversation history, rate limit handling ensures your entire workflow doesn’t fail on a temporary throttling event.
Parallel Page Fetching for Independent Data
Sometimes you need to fetch multiple paginated resources simultaneously. Rather than sequentially waiting for each page, you can use concurrent requests:
async function fetchMultipleThreads(threadIds: string[]) {
const fetchThread = async (id: string) => {
const response = await fetch(`/api/threads/${id}/messages`);
return response.json();
};
// Fetch all threads in parallel
const results = await Promise.all(
threadIds.map(fetchThread)
);
return results;
}
This approach works well when you know the thread IDs upfront. However, be mindful of total concurrent connections—too many simultaneous requests can trigger rate limits regardless of individual request patterns.
Combining Claude Skills with Pagination
The real power of pagination emerges when you combine it with Claude’s specialized skills. For instance, when using the frontend-design skill to generate UI components, you might paginate through a library of design tokens:
def process_design_tokens(token_library_id, token_handler):
"""Process design tokens across multiple pages."""
cursor = None
while True:
page = client.design_tokens.list(
library_id=token_library_id,
cursor=cursor,
limit=50
)
for token in page.data:
token_handler(token)
if not page.has_more:
break
cursor = page.cursor
Similarly, when using the tdd skill to generate tests across multiple files, pagination helps you manage large codebases without overwhelming memory:
async function generateTestsForFiles(fileIds, testGenerator) {
let cursor = null;
do {
const page = await fetchFilePage(fileIds, cursor);
for (const file of page.files) {
await testGenerator(file.path, file.content);
}
cursor = page.has_more ? page.cursor : null;
} while (cursor);
}
The supermemory skill can also benefit from pagination when retrieving historical context—fetching memories in chunks prevents single-request timeouts while still building a complete context window.
Tracking Pagination State
For long-running operations or user-resumable flows, persist pagination state:
import json
def save_progress(cursor, page_number, filename="pagination_state.json"):
"""Save pagination progress for resumability."""
state = {
"cursor": cursor,
"page": page_number,
"timestamp": time.time()
}
with open(filename, "w") as f:
json.dump(state, f)
def load_progress(filename="pagination_state.json"):
"""Load saved pagination state."""
try:
with open(filename, "r") as f:
return json.load(f)
except FileNotFoundError:
return None
This becomes valuable when building tools that run as background jobs or need to survive application restarts. Your users will appreciate not losing progress when processing thousands of items.
Key Takeaways
Cursor-based pagination with the Claude Code API requires a different mindset than traditional offset pagination, but it offers significant advantages for data consistency and performance. Set appropriate page sizes based on your use case, implement proper rate limit handling, and consider parallel fetching when you need to gather data from multiple independent sources.
The skills like pdf, tdd, frontend-design, and supermemory all work better when you build pagination into your workflows from the start rather than treating it as an afterthought.
Related Reading
- Claude Code REST API Design Best Practices
- Claude Code GraphQL Schema Design Guide
- Claude Code OpenAPI Spec Generation Guide
- Claude Skills Integrations Hub
Built by theluckystrike — More at zovo.one