What Is Cursor-Based Pagination? An API Design Guide

What Is Cursor-Based Pagination?

Scrapeless Scraping Browser maintains browser sessions across page interactions so data workflows can follow cursor-driven, load-more, and infinite-scroll states on public websites.

TL;DR

  • Cursor-based pagination divides an ordered result set into pages and gives the client an opaque continuation value that represents a position in that ordering. A typical response contains an items array plus a next cursor, a previous cursor, or page-information fields such as hasNextPage.
  • Establish a stable sort. The server orders results by one or more fields and adds a unique tiebreaker. The sort direction, filters, and scope form part of the traversal contract and should remain unchanged while the client walks the pages.
  • Send the token unchanged. The next request includes the exact token in the documented parameter. The server validates it, restores the relevant boundary, and applies the same filters and ordering before selecting the next slice.
  • Keep filters, account scope, sort fields, and direction unchanged throughout one traversal. Repeated pages usually mean the client is sending the wrong token, dropping a filter, or following a stale continuation link.
  • Cursor-based pagination replaces numeric position with a server-defined continuation boundary.

Definition and Short Answer

Cursor-based pagination divides an ordered result set into pages and gives the client an opaque continuation value that represents a position in that ordering. The client sends the returned cursor to request the next or previous slice. Unlike a page number, the cursor is not a human-facing location such as page five. It is server-defined state, often derived from the last record’s sort values, a snapshot marker, or an encoded token that lets the service continue efficiently.

A typical response contains an items array plus a next cursor, a previous cursor, or page-information fields such as hasNextPage. The client must preserve the cursor exactly as returned. Decoding, editing, or synthesizing a cursor couples the client to implementation details and can break when the service changes its token format. An absent next cursor or an explicit false end marker normally means the traversal is complete.

Cursor pagination works best with a deterministic order. Sorting only by a non-unique field such as created time can leave records tied at the page boundary. A stable design adds a unique tiebreaker, commonly an immutable identifier, so every record has a total order. The continuation condition can then select records after the last tuple, such as values later than a given creation time and identifier.

The approach is especially useful for feeds and changing data sets. Deep pages do not require the database to count and discard every earlier row, and newly inserted records before the current position are less likely to shift later pages. Cursor pagination does not automatically create a frozen snapshot, however. Deletions, edits to sort fields, and changes outside the cursor boundary can still affect what the client sees unless the API documents snapshot semantics.

How a Cursor Advances Through an Ordered Set

  1. Establish a stable sort. The server orders results by one or more fields and adds a unique tiebreaker. The sort direction, filters, and scope form part of the traversal contract and should remain unchanged while the client walks the pages.
  2. Return the first page and token. The initial request omits a cursor or uses a documented starting value. The server returns a bounded item set and an opaque token that represents the continuation boundary after the final item.
  3. Send the token unchanged. The next request includes the exact token in the documented parameter. The server validates it, restores the relevant boundary, and applies the same filters and ordering before selecting the next slice.
  4. Stop on an explicit terminal signal. The traversal ends when the next cursor is absent, null, or paired with an end flag. Clients should also deduplicate by stable record identity and keep a bounded page guard for malformed or repeating tokens.

Cursor-Based Pagination in Real Systems

Activity feeds

New events can arrive at the front while a reader continues from a stable boundary without page numbers shifting underneath the session.

Large API collections

Keyset-style queries can continue from indexed sort values instead of scanning through a deep numeric offset.

Infinite scroll

A user interface can append each batch and keep the next cursor in memory until the service reports the end.

Data collection

A crawler can checkpoint the cursor beside the last committed batch and resume from a known continuation state after an intentional stop.

Cursor Fields You Commonly Encounter

A side-by-side view prevents nearby concepts from being treated as interchangeable. Use the comparison to identify which contract is active before changing client or server behavior.

Concept or SignalMeaningOperational Note
next_cursorOpaque token for the following pageStore exactly; stop when absent
previous_cursorOpaque token for the prior pageUseful for bidirectional navigation when supported
has_next_pageBoolean end signalUse with the returned cursor, not as a cursor replacement
end_cursorBoundary associated with the last edgeCommon in GraphQL connection responses
page_size or firstMaximum items requestedThe service can still return fewer items

Cursor-Based Pagination Diagnosis and Operational Design

Repeated pages usually mean the client is sending the wrong token, dropping a filter, or following a stale continuation link. Log a hash of each cursor rather than the full value when tokens may contain sensitive state. Record the first and last stable record identifiers in each page. If the token changes but item boundaries do not, inspect server ordering and tie handling.

Missing records often appear when the sort is not stable or a mutable field is part of the cursor. A record whose score or update time changes can move across the current boundary during traversal. Use immutable ordering where possible, add a unique tiebreaker, and document whether the API promises snapshot consistency or only forward progress over a live collection.

A browser-driven page may hide the cursor in an internal network response rather than the visible URL. Inspect the page’s fetch or GraphQL traffic, the load-more control, and the application state. Keep the same browser session when the token is bound to cookies or session state, and treat the returned token as opaque even when it looks like base64 or readable JSON.

Cursor-Based Pagination Implementation Checklist

The checklist below turns the concept into verifiable engineering work. Apply only the items that match the active protocol and product contract, but keep the evidence together so another engineer can reconstruct the decision.

  • Keep filters, account scope, sort fields, and direction unchanged throughout one traversal.
  • Store every continuation token exactly as returned and avoid deriving page numbers from it.
  • Deduplicate output by a durable record identifier instead of page position.
  • Checkpoint the cursor only after the corresponding batch is committed successfully.
  • Stop on the documented end signal and add a bounded page guard for unexpected cycles.
  • Log page boundaries and cursor hashes so repeated or skipped segments can be investigated.
  • Test inserts, deletes, and sort-field changes at page boundaries before claiming snapshot behavior.

After implementation, test normal behavior, boundaries, malformed input, missing state, concurrent activity, and deliberate access denial in a controlled environment. Record expected status, body shape, end condition, and state transition for each case. Production monitoring should report the same dimensions used during the test so an incident can be compared with a known baseline.

Documentation should name the responsibility on each side of the interface. Clients need required fields, stable identifiers, ordering rules, limits, terminal signals, and error meanings. Operators need the internal policy, storage or routing decision, observability fields, and safe public response. Vague contracts cause teams to fix the visible symptom in the wrong layer.

Common Mistakes With Cursor-Based Pagination

Do not infer success, absence, permission, ordering, or completion from one field without the surrounding contract. Status codes, tokens, page sizes, and transport headers each answer a narrow question. The response body, method, identity, filters, protocol version, and server documentation provide the rest of the meaning.

Do not remove diagnostic context in the name of simplicity. A short log line that omits the request identifier, target, version, scope, or boundary can turn a small defect into hours of guesswork. At the same time, observability must redact credentials, session secrets, signed URLs, and sensitive payload fields.

Do not turn a temporary operational workaround into the permanent contract. Fix the underlying ordering, permission, routing, pacing, framing, or error-mapping issue and add a regression check. A system becomes dependable when the failure is explicit and bounded, not when one manual run happens to complete.

Conclusion

Cursor-based pagination replaces numeric position with a server-defined continuation boundary. Its strengths come from stable ordering, indexed continuation queries, opaque tokens, and explicit end signals. Clients succeed when they preserve cursors unchanged, keep traversal parameters fixed, checkpoint only committed pages, and distinguish forward progress over live data from a guaranteed snapshot.

Ready to Build a More Reliable Data Workflow?

Connect the protocol concepts in this guide to a documented Scrapeless product surface and keep every request measurable from submission through result.

Sign up today and get $5 in free creditno credit card required.

Claim Your $5 Credit →

FAQ

Is a cursor always a database record ID?

No. A cursor can encode several sort values, a snapshot marker, account scope, or server-side state. Clients should treat it as opaque and rely only on the API’s documented request and response fields.

Can cursor pagination jump directly to page 50?

Usually not. Cursor pagination is designed for sequential continuation, so reaching a distant position requires a cursor from an earlier response or a separate search boundary. Numeric random access is one area where offset pagination is simpler.

Does cursor pagination prevent duplicates?

No. Stable ordering reduces page shifting, but live updates, mutable sort fields, and service behavior can still create overlap. Clients should deduplicate by stable record identity and monitor page boundaries.

Should a client decode a cursor?

A client should not depend on decoded cursor contents unless the API explicitly defines the format as public. An apparently readable token can change without notice, include a signature, or contain state that must not be modified.

How should a crawler resume cursor pagination?

Persist the cursor together with the committed batch boundary, filters, sort order, and scope. Resume only with the same traversal parameters, and retain stable record identifiers for deduplication and audit.

References