Skip to content

Pagination with cursors

List endpoints (followers, timelines, search, replies, list members…) return one page of results at a time. Every list response carries two fields for paging:

  • has_next_page — true if more results exist.
  • next_cursor — an opaque string. Pass it back as the cursor query parameter to get the next page.

The first request has no cursor. Keep requesting until has_next_page is false.

{
"followers": [ /* … */ ],
"has_next_page": true,
"next_cursor": "1847…|2103…",
"status": "success"
}
import requests
API = "https://api.relayxapi.com"
HEADERS = {"X-API-Key": "YOUR_KEY"}
def paginate(path, key, max_pages=5, **params):
"""Yield items from a list endpoint, following next_cursor."""
cursor = None
for _ in range(max_pages):
q = dict(params, **({"cursor": cursor} if cursor else {}))
body = requests.get(API + path, params=q, headers=HEADERS).json()
yield from body.get(key, [])
if not body.get("has_next_page"):
break
cursor = body["next_cursor"]
for user in paginate("/twitter/user/followers", "followers", userName="NASA"):
print(user["userName"])
  • Page size is decided by X and varies by endpoint and by page, so don’t rely on a fixed count. Treat the cursor as the only way forward.
  • Each page is a separate, separately billed call. Cap max_pages to what your task actually needs; see credits in practice.
  • Cursors are opaque. Store them as strings and pass them back unchanged; don’t build or edit them.
  • The item key depends on the endpoint (tweets, followers, followings, users, replies, ids…). Each endpoint’s page in the API reference shows an example response.
  • tweet/thread_context returns the whole thread in one response, so its has_next_page is always false.