Skip to main content

CursorProof: linked pages with a verification shield

CursorProof

PyPI Python CI License

CursorProof is a command-line tool for checking cursor pagination in REST APIs. It traverses an endpoint at several page sizes, checks duplicates, ordering and termination, and saves a trace that can be replayed without the API.

An API can return 200 OK on every page while skipping records or repeating a page. An independent oracle, such as an unpaginated endpoint or database query, lets CursorProof compare the returned stream with the expected records.

Install

Requires Python 3.10 or newer.

pipx install cursorproof
# or
python -m pip install cursorproof

Check your API

Save a configuration as cursorproof.yml. This example expects results and next_cursor in each response and records identified by id:

url: http://localhost:8000/api/orders
response:
  items: $.results
  next_cursor: $.next_cursor
  id: $.id
ordering:
  - field: id
    type: number
limits: [10, 50, 100]

Validate the configuration, run the checks, and replay the saved trace:

cursorproof check cursorproof.yml
cursorproof run cursorproof.yml
cursorproof replay cursorproof-repro.json

Token pagination is the default: the next request sends the returned token in the cursor query parameter and the selected page size in limit. For APIs that return a continuation URL, including Django REST framework, add:

pagination:
  mode: url
  cursor_param: cursor
  limit_param: page_size
response:
  items: $.results
  next_cursor: $.next
  id: $.id

URL mode requires CursorProof 0.2.0 or newer. To install the version from a checkout, run uv tool install . from the repository root.

URL mode follows server-provided links after checking the origin, endpoint, scope parameters and page size. It does not follow redirects. The user guide explains authentication, response paths, ordering, oracles and the continuation URL contract.

Try the local demo

Clone the repository and run these commands from its root directory.

Install from the checkout with uv:

uv sync --locked

To install the checkout as an isolated CLI tool instead, run uv tool install ..

Start the demo API in one terminal:

uv run python examples/demo_api.py

In another terminal, run the broken example:

uv run cursorproof run examples/broken.yml

Replay its saved trace offline with:

uv run cursorproof replay cursorproof-repro.json

The demo has 40 records with repeated sort values. /broken continues using only the timestamp and skips records at page boundaries despite successful responses. CursorProof reports CP003 MISSING_ITEMS and differences between limits. The /correct endpoint also uses the unique ID; try it with:

uv run cursorproof run examples/correct.yml --format json --repro correct-repro.json

Understand the result

  • Exit 0: all executed checks passed.
  • Exit 1: CursorProof found a pagination invariant violation.
  • Exit 2: configuration or execution failed, or a traversal could not finish.

Use --format json for a machine-readable report and --repro PATH to choose the trace file. A passing run describes the tested data and configuration. Without an oracle, it cannot establish completeness: every tested page size could omit the same records. See the guide for oracle configuration, finding codes and trace privacy.

Django REST framework example

The DRF configuration uses standard CursorPagination links. The Django REST framework example shows how a large group of equal sort values can repeat a page. It includes a local HTTP/SQLite setup, a unique-ordering control and traces you can replay without Django.

Additional checks

CursorProof also supports snapshot consistency, live keyset checks, mutation hooks, cardinality boundary tests and cursor binding probes. Mutation hooks and boundary tests execute commands supplied in your configuration and can change data. Use controlled test environments and read the consistency and mutation documentation before enabling them. URL mode does not support boundary tests or cursor binding probes.

Run cursorproof --help or cursorproof COMMAND --help for command options.

Development

uv sync --locked
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run mypy
uv build

The analyzer checks recorded observations without network I/O. The runner makes requests, and the CLI displays reports. Tests use HTTPX transports, Hypothesis and the local demo API.

The optional locked integration group adds Django/DRF for tests against a real HTTP endpoint. Follow the integration instructions to use a separate environment and the built wheel. CI runs the core checks on Python 3.10 through 3.14. The Django/DRF integration tests require Python 3.12 or newer and run on Python 3.12 through 3.14.

Metadata

Release files for cursorproof 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cursorproof 0.2.0
File Size Uploaded Provenance Actions
cursorproof-0.2.0.tar.gz 111.4 kB With provenance Details for cursorproof-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for cursorproof 0.2.0
File Interpreter ABI Platform Actions
cursorproof-0.2.0-py3-none-any.whl Python 3 none any Details for cursorproof-0.2.0-py3-none-any.whl

Total release size: 147.2 kB

Release files / cursorproof-0.2.0.tar.gz

Download URL cursorproof-0.2.0.tar.gz
Size 111.4 kB
Tags Source
SHA-256 checksum
How to use checksums
153bf7de17ae862000785c895deb6fec5ccd0f3aae6bacc30c8398cea21dde23
BLAKE2b-256 checksum
How to use checksums
132a45ce03a1c1bd1f73c65fe8511d3296f3e1e9c5bca48da4de2aba83a48944
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / cursorproof-0.2.0-py3-none-any.whl

Download URL cursorproof-0.2.0-py3-none-any.whl
Size 35.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d002896d0d7dea069e36d40ba0095b520f73e4bd00aee2b580e2f88f8dcb75c5
BLAKE2b-256 checksum
How to use checksums
ee3428645656f9c4d77c7a544442b614560937c669fca9ac3f170671658dc3ff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Security for cursorproof 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for cursorproof-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page