Skip to main content
Use this Twitter API pagination guide for tweets, profiles, followers, and exports. Choose one matching route. Save every returned ID and cursor. Resume that checkpoint instead of repeating completed pages.
Quick answer: batch known IDs. Use profile timelines for one account. Search tweets for keywords. Use extractions for saved CSV, JSON, or XLSX.

Choose the smallest Twitter API route

The smallest matching route reduces duplicate tweets and unnecessary requests. Do not force every job through Twitter advanced search. Check each route before reusing a parameter name. Twitter API endpoints do not share one page-size parameter.

Known tweet IDs

Use GET /api/v1/x/tweets?ids=... for up to 100 comma-separated tweet IDs in one request.

Known user IDs

Use GET /api/v1/x/users/batch?ids=... for up to 100 comma-separated user IDs in one request.

One profile timeline

Use GET /api/v1/x/users/{id}/tweets for one user’s profile timeline. Pass a username or numeric X user ID.

Keyword or advanced search

Use GET /api/v1/x/tweets/search for keywords, hashtags, operators, date filters, and advanced search pages.

Authenticated home timeline

Use GET /api/v1/x/timeline for the connected account’s home timeline. Pass cursor and optional seenTweetIds.

Saved file export

Use POST /api/v1/extractions/estimate, POST /api/v1/extractions, and GET /api/v1/extractions/{id}/export for CSV, JSON, or XLSX.

Batch known tweet or profile IDs

Batch known IDs before starting a cursor loop. One batch accepts up to 100 comma-separated IDs. Duplicate user IDs preserve only their first position.
Keep the submitted ID list beside each response. Match returned tweets or profiles by their stable string IDs. Retry only IDs missing from the completed response. Batch profile responses expose reconciliation fields. Inspect requested_count, processed_count, and returned_count. Also inspect unavailable_ids and unprocessed_ids. Do not treat an unavailable profile as a transient pagination failure. Batch lookups are single-page requests. Do not send an empty next_cursor into another batch request.

Match Twitter search, timeline & feed intent

These routes can return similar tweet objects. Their collection intent remains different.

Profile timeline

Use /x/users/{id}/tweets for one account’s posts. Add includeReplies when replies belong in the result.

Tweet search

Use /x/tweets/search for keywords, hashtags, operators, dates, or engagement filters.

Home timeline

Use /x/timeline for one connected account’s ranked home feed. It is not a keyword search route.
Use profile timelines for complete account-oriented collection. Use tweet search when the query meaning matters most. Use home timelines for feed-style inboxes or routing. Plain from:username date searches can use timeline-oriented collection. Add keywords when ranked search semantics matter more. Keep q, filters, dates, and queryType unchanged across pages.

Use the correct page-size parameter

Page-size names vary across Xquik routes. Copy the parameter from that endpoint’s API reference. A requested size is an upper bound. Filters, source availability, or credits can reduce returned rows. Continue while the response says another page exists. Larger pages reduce HTTP calls. Smaller pages reduce memory and checkpoint loss after failures. Choose the largest size your worker can safely store atomically.

Use extraction jobs for saved files

Use extractions for durable Twitter scraper API jobs. They support saved results and repeatable file handoffs.
1

Estimate

Send the planned tool, target, and resultsLimit. Review the estimate before creating the job.
2

Create

Call POST /api/v1/extractions. Store its job id, status, and poll path.
3

Poll JSON

Poll GET /api/v1/extractions/{id} until completion. Pass nextCursor back through cursor for more stored rows.
4

Export

Download CSV, JSON, Markdown, Markdown document, PDF, TXT, or XLSX. Check the export page’s row and format limits first.
Direct routes suit live application pages. Extractions suit durable exports, analysts, and asynchronous workflows. Store the export format, job ID, row count, and completion state. Do not call the export route before the job completes.

Store cursor checkpoints

Store the request and response cursor together. Treat each cursor as an opaque string. Never decode, trim, or construct one.
Most X reads return next_cursor and accept cursor. Stored extraction pages return nextCursor and accept cursor. Events and draws also accept cursor. Radar accepts after. Drafts accept afterCursor. The normalized REST contract uses has_more and next_cursor. Each route still preserves its documented request parameter. Write the rows and checkpoint in one database transaction. Advance only after the row write succeeds. Keep the previous checkpoint until validating its replacement.

Implement a bounded tweet search loop

This TypeScript example preserves query intent across cursor pages. It also stops repeated cursors and duplicate tweet rows.
Move status-specific recovery outside this collection function. Resume only after correcting the failed condition.

Guard high-volume Twitter API pagination

Bound every high-volume tweet scraper loop. A filter can produce an empty page before later matches. An empty page does not prove pagination finished.
1

Bound the run

Set maximum rows, pages, elapsed time, and expected credits.
2

De-duplicate rows

Store tweets by tweet ID. Store profiles by user ID.
3

Follow advancing cursors

Continue while the response reports more pages. Permit empty filtered pages when the cursor advances.
4

Stop stalled pagination

Stop when the next cursor is missing, unchanged, or previously seen.
5

Persist after each page

Save both cursors, unique rows, and the last stable ID.
Schedule multiple accounts or searches fairly. Fetch one bounded page slice from each stream. Then resume deeper cursors in later rounds. One large timeline should not starve every other target. For agent calls, return counts or bounded field projections. API MCP output is limited to 24,000 characters. Use REST, SDKs, or exports for every complete row.

Resume recurring tweet collection

Do not restart recurring searches from their first page. Save the last accepted tweet timestamp and stable ID. For time-based searches, pass sinceTime and untilTime. Use a small overlap between runs. Then deduplicate overlapping tweets by tweet ID. For recurring account or keyword checks, consider monitors. Signed webhooks push matching tweet or profile events. The events API supports replay and reconciliation. Keep separate checkpoints for each route and query. Changing filters creates a different result stream. Never reuse a cursor after changing its query. The official X pagination guide confirms two durable principles. Pagination tokens are opaque. Short pages can still have successors. Xquik exposes those principles through its documented cursor fields.

Recover without losing the cursor

Use the HTTP status before deciding whether to retry. Never advance the checkpoint after a failed response. Never charge a failed page to the unique-row count. Record partial completion when a retry budget expires.

Control credits, requests & memory

Estimate work before starting large exports. Multiply expected unique rows by the route’s documented result cost. Keep rate-limit budgets separate from credit budgets. Requested rows can exceed affordable rows. A paid endpoint can return a smaller page. Zero affordable paid results return 402 insufficient_credits. Use these controls before every large run:
  • Maximum unique tweets or profiles.
  • Maximum cursor pages.
  • Maximum elapsed time.
  • Maximum expected credits.
  • Maximum retry attempts per cursor.
  • Maximum in-memory rows before flushing.
See Twitter API rate limits for request pacing. See pricing and billing for metered result rules.

Avoid unnecessary media work

Pass public media URLs directly when creating tweets. One public MP4 URL can also use the media field. Do not upload already public tweet media first. Upload media when a direct message needs a mediaId. DM writes accept one item in media_ids. Keep tweet media URLs separate from DM media IDs.

Twitter API pagination questions

How do I paginate Twitter API tweets?

Read has_next_page and save next_cursor. Send that value as the next request’s cursor. Stop only when the response reports no next page.

Can I get every tweet in one API request?

No. Collection routes return bounded pages. Tweet search can request up to 200 results through limit. Larger collections still require cursors or extraction jobs.

Why did the API return fewer tweets than requested?

Page size is an upper bound. Filters, source availability, and remaining credits can reduce results. Continue whenever has_next_page remains true.

How do I get tweets by one user efficiently?

Use GET /x/users/{id}/tweets with pageSize and cursor. Add includeReplies=true only when replies belong in scope. Use search when keywords or advanced filters define the job.

Should I use a cursor or a timestamp?

Use cursors within one continuous collection run. Use timestamps to define windows between recurring runs. Apply a small overlap and deduplicate by tweet ID.

How do I prevent duplicate tweets across pages?

Store every tweet ID in a unique index. Track cursors separately from tweet IDs. Reject repeated cursors before requesting another page.

Should I use direct API pages or a Twitter export?

Use direct pages for live application responses. Use extractions for durable CSV, JSON, or XLSX handoffs. Use stored extraction pages when streaming beyond file limits.

Efficient Twitter API usage checklist

  • Choose the route matching IDs, users, search, feed, or export intent.
  • Batch up to 100 known tweet or user IDs.
  • Preserve exact filters throughout every cursor run.
  • Store rows and checkpoints atomically.
  • Count unique IDs instead of raw array lengths.
  • Continue through short or empty pages when cursors advance.
  • Stop missing, unchanged, or repeated cursors.
  • Bound pages, rows, time, credits, retries, and memory.
  • Use resultsLimit for extraction estimates and jobs.
  • Resume the same cursor after recoverable errors.
  • Use monitors and webhooks for recurring checks.
  • Keep tweet media URLs separate from uploaded DM media IDs.

Tweet search API

Search tweets by keywords, dates, authors, media, or engagement.

Extraction workflow

Estimate, create, poll, paginate, and export durable jobs.

Rate limits

Pace requests and recover from 429 responses safely.