The SDK exports eight pagination classes (sync/async pairs for cursor-based, offset-based, token-based, and bidirectional traversal) that wrap API responses and provide methods to fetch the next or previous page of results. Pagination classes inherit from BasePage in _base_client.py, storing the client and request options privately, and delegate page-building logic to a PageInfo object that encodes the URL, params, or JSON needed for the next request.
Eight pagination types are publicly exported from src/anthropic/pagination.py: SyncPage, AsyncPage, SyncTokenPage, AsyncTokenPage, SyncPageCursor, AsyncPageCursor, SyncBidirectionalPageCursor, and AsyncBidirectionalPageCursor.[1] SyncPage and AsyncPage expose data, has_more, first_id, and last_id fields; has_next_page() returns False immediately when has_more is explicitly False, otherwise delegates to the base class.[1] SyncBidirectionalPageCursor and AsyncBidirectionalPageCursor carry both next_page and prev_page token fields to enable forward and backward traversal, but next_page_info() surfaces only the forward next_page token.[1]
SyncPage.next_page_info() uses before_id/first_id for reverse pagination when the before_id param is active, and after_id/last_id for forward pagination.[1] All page classes in src/anthropic/pagination.py return an empty list from _get_page_items() when the data field is falsy, preventing iteration errors on empty responses.[1] BasePage.has_next_page() returns False when the current page yields no items, regardless of what next_page_info() would return.[2] BasePage._info_to_options() calls options._strip_raw_response_header() before building next-page options, ensuring the internal raw-response header is not forwarded to the next request.[2]
BaseSyncPage and BaseAsyncPage in src/anthropic/_base_client.py are pydantic GenericModel subclasses that store their client, model type, and request options as pydantic PrivateAttr fields.[2] The PageInfo class in src/anthropic/_base_client.py stores the information needed to build the next-page request, requiring exactly one of url, params, or json to be set.[2] Retry and timeout constants (DEFAULT_TIMEOUT, MAX_RETRY_DELAY, DEFAULT_MAX_RETRIES, INITIAL_RETRY_DELAY) are imported from ._constants, centralizing those defaults in one place.[2] Middleware types (Middleware, AsyncMiddlewareCallable, validate_sync_middleware, and related symbols) are imported from ._middleware, with request middleware validation handled in that dedicated module — see Middleware system for full details.[2]
BaseSyncPage.get_next_page() raises RuntimeError if called when there is no next page; callers must check .has_next_page() first.[2] BaseSyncPage.__iter__ overrides pydantic's __iter__ (which normally supports dict(model)) to enable for item in page iteration; as a result, dict(page) will not work, but page.dict() still does.[2] BasePage._info_to_options() raises TypeError with the message "Pagination is only supported with mappings" if a json-typed PageInfo is used but either the new or existing json_data is not a mapping.[2]
Sources