Docs menu: Pagination

Pagination

Collections return one page per request. Pass the cursor back until has_more is false.

How it works

Every Moderate and Contentful collection response has the same shape:

Page
{
  "items": [ … ],
  "count": 20,
  "pagination": {
    "next_cursor": "DAABCgAB…",
    "has_more": true
  }
}
itemsRecords on this page. Posts, accounts or trends depending on the route.
countNumber of records on this page. You pay for this many records.
pagination.next_cursorOpaque string for the next page, or null.
pagination.has_moretrue when a next cursor was returned.

X sets the page size. There is no page-size parameter.

Request the next page

Pass the cursor exactly as received, URL-encoded.

cURL
curl -G "https://twitterxapi.com/api/v1/users/marclou/tweets" \
  -H "Authorization: Bearer $TWITTERXAPI_KEY" \
  --data-urlencode "cursor=DAABCgAB…"

Read every page

import os, requests

def pages(path):
    """Yield every item from a collection endpoint."""
    url = f"https://twitterxapi.com/api{path}"
    headers = {"Authorization": f"Bearer {os.environ['TWITTERXAPI_KEY']}"}
    cursor = None
    while True:
        params = {"cursor": cursor} if cursor else {}
        response = requests.get(url, headers=headers, params=params, timeout=60)
        response.raise_for_status()
        page = response.json()
        yield from page["items"]
        cursor = page["pagination"]["next_cursor"]
        if not page["pagination"]["has_more"] or not cursor:
            return

for post in pages("/v1/users/marclou/tweets"):
    print(post["id"], post["content"][:80])

Rules for reliable loops

  • Stop when has_more is false or next_cursor is empty.
  • Do not decode, edit or reuse a cursor with a different route or query.
  • Save each page before requesting the next, and store the last cursor so a stopped job can resume.
  • Deduplicate by ID. Live timelines and follower lists change while you read them.
  • Retry 429 and 5xx responses with backoff. Honour Retry-After when it is present.
  • Do not send limit. Live routes reject it with 400 limit_removed.
  • Raw responses have no pagination object. See Raw responses.

Larger collections

For an account's post history or a large search, a queued job collects the pages and delivers one file.