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.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.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.
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.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.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.
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, passsinceTime 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 return402 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.
Avoid unnecessary media work
Pass public media URLs directly when creating tweets. One public MP4 URL can also use themedia 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?
Readhas_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 throughlimit.
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 wheneverhas_next_page remains true.
How do I get tweets by one user efficiently?
UseGET /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
resultsLimitfor 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.