TwitterAPIs Docs
API ReferenceUser Reads

Full Tweet History API

Collect a user's tweet history in bulk, auto-paginating server-side across upstream pages. Unlike GET /user/tweets (one upstream page per call), this drives pagination for you and returns a large batch in one request. Each call is bounded by both `max` and a server-side time budget, so it always returns inside a normal client timeout. When more history remains the response carries a `next_cursor` — pass it back as `cursor` to continue, and repeat until `next_cursor` is null. A public read: no registered session required. Cost: $0.0024 per call.

GET user/tweets/complete returns a large batch of a Twitter/X user's tweet history in one call by auto-paginating across multiple upstream pages server-side. It accepts a numeric user_id, an optional max tweet count (default 200), and an optional cursor to resume a prior request, returning up to Twitter's roughly 3200-tweet ceiling, newest first, including retweets.

GET
/user/tweets/complete

Authorization

bearerAuth
AuthorizationBearer <token>

Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.

In: header

Query Parameters

user_id*string

Numeric ID of the target account. Resolve a handle with GET /user/info first.

max?integer

Target number of tweets to collect in this call. Defaults to 200. This is a MINIMUM target, not a hard cap: pages arrive in whole chunks, so a response may contain up to one page (<=100) more than requested. Twitter's ~3200-per-user history ceiling still applies overall.

cursor?string

Resume point from a previous response's next_cursor. Omit on the first call. Pass it back to continue collecting where the last call stopped.

fields?string

Comma-separated list of dotted field paths to keep in the response (one parameter, never repeated), applied to every object in the returned lists and to nested objects (for example fields=id,text,author.username; the list's own name may prefix a path, fields=tweets.id). A path prefix that lands on an array applies to each element (media.media_url_https). Pagination and envelope keys (next_cursor, cursor, has_more, count, partial, error, message, reason) are always kept. Unknown paths are ignored; up to 50 paths of up to 6 segments. Projection never changes status codes or billing, and applies to data reads only: account, feedback, session status, monitor (other than deliveries), webhook and stream-compat reads return their bodies unchanged.

compact?string

Set to 1 (or true) to apply the built-in compact preset: ids, url, text, created_at, lang, the engagement counts, the is_retweet/is_reply/is_quote flags, conversation ids, the author's id/username/name/followers_count/verification, and the quoted or retweeted tweet's id/url/author username. The preset trims what it recognises and leaves alone what it would empty, so it never turns a body into {}. Combine with fields to add paths on top of the preset. Typically cuts a tweet page by 70 to 90 percent for LLM tool callers.

paid_promotion?string

Filter this page's tweets by X's Paid partnership label: only keeps tweets whose is_paid_promotion is true, exclude keeps the rest. Omit it for every tweet. It filters the page X returned and does not fetch more, so a filtered page can hold fewer tweets than asked for, or none, while next_cursor still pages on. The response carries paid_promotion_filter { mode, kept, removed }, and count reflects what is returned. Any other value is a 400. Billing is the same as without it.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/user/tweets/complete?user_id=44196397&max=200&cursor=DAAHCgABHNqVL6L__zs&fields=id%2Ctext%2Ccreated_at%2Cauthor.username&compact=1&paid_promotion=only"
{  "count": 201,  "next_cursor": "DAAHCgABHNqVL6L__zsLAAIAAAAT",  "tweets": [    {      "id": "2071092912000246106",      "text": "RT @XFreeze: xAI models now support Zero Data Retention (ZDR) on OpenRouter",      "created_at": "Sun Jun 28 04:46:43 +0000 2026",      "lang": "en",      "is_retweet": true,      "is_quote": false,      "author": {        "id": "44196397",        "username": "elonmusk",        "name": "Elon Musk",        "verified": true,        "followers_count": 240574388      },      "retweet_count": 208,      "view_count": 599857    }  ]}
{  "error": "bad_request",  "message": "Missing or malformed parameter. Fix the request before retrying."}
{  "error": "unauthorized",  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}
{  "error": "insufficient_credits",  "message": "Your balance is exhausted. Top up your credits to continue."}
{  "error": "forbidden",  "message": "X refused this resource for the acting account: on a read, the account is not a participant in the DM thread, the target is protected or has blocked it, or the session was attestation-blocked for calling from a datacenter or rotating IP; on a write, the account is not authorized for the action or has no logged-in session. The credentials are still valid, so do not re-register."}
{  "error": "not_found",  "message": "The resource does not exist, for example a deleted tweet or a private account."}
{  "error": "rate_limited",  "message": "Too many requests. Back off and retry with exponential backoff."}
{  "error": "server_error",  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."}

Pricing

UnitPrice
Per call$0.0024
Per 1,000 calls$2.40
Per 1,000 records (~200 per call)~$0.01

When to use

Use this endpoint instead of GET /user/tweets when you need a large chunk of a user's tweet history in as few calls as possible, since it drives pagination across upstream pages server-side rather than returning one page per request. Reach for GET /user/tweets instead if you only need the most recent page of tweets or want to control pagination timing yourself.

Notes

  • CURSOR-PAGINATED. Check next_cursor on every response: non-null means this call was truncated and more history remains, so call again with cursor set to that value and repeat until it is null. A client that ignores next_cursor silently gets only part of the history.
  • Each call is bounded by a server-side time budget as well as by max, so a response can be truncated even when it returned fewer tweets than you asked for. That is why next_cursor, not count, is the signal for 'am I done'.
  • max is a target, not a hard cap: pages arrive in whole chunks of up to 100, so you may receive slightly more than requested. Never assume count === max.
  • Billed at $0.0024 per CALL, flat, regardless of how many tweets or upstream pages that call collected. Collecting a full history therefore costs one call-unit per request you make, so a larger max is cheaper per tweet.
  • Public read: no registered session required.

Pagination

This endpoint is cursor-paginated and returns a large batch per call (~200 by default, not ~20). Pass the next_cursor from each response back as the cursor parameter to continue. Stop when next_cursor is null — that is the reliable stop signal here, and unlike the follower-graph endpoints you should NOT wait for an empty array. Each call is also bounded by a server-side time budget, so a response can be truncated even when it returned fewer tweets than you asked for; next_cursor, not count, tells you whether you are done. See Pagination for the full loop.

FAQ

How do I collect a user's full tweet history beyond one response?

Check has_more (or next_cursor) in the response. If has_more is true, issue another request with cursor set to the previous response's next_cursor and the same user_id to continue from where you left off, repeating until has_more is false or you hit Twitter's roughly 3200-tweet ceiling.

How many tweets does one call return, and does that include retweets?

By default max is 200 tweets per call, but you can raise max to collect a larger batch in a single request since this endpoint auto-paginates upstream pages for you. The tweets array includes retweets alongside original tweets, and count reports how many items came back in that specific response.

Was this page helpful?