Twitter Thread API | Reconstruct a Tweet Thread
Given the first tweet of a thread, return the ordered list of tweets that make up the author's connected thread. The endpoint reads forward from the tweet you pass and does not walk backwards, so pass the thread's first tweet, which is the conversation_id carried on every tweet in that thread. Passing a later tweet returns only the tail of the thread. Cost: $0.0040 per call.
Tweet Thread takes the ID or URL of a thread's first tweet (its conversation_id) and returns the author's connected thread, read forward from that tweet, as an ordered list of tweet objects. It saves you from manually walking the reply chain to rebuild a multi-part post. Each call is a $0.004 premium read (full thread expansion): the entire connected thread comes back in one response, with no pagination to manage.
Authorization
bearerAuth Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.
In: header
Query Parameters
Numeric ID of the thread's first tweet (its conversation_id). The endpoint reads forward and does not walk backwards, so a later tweet's ID returns only the tail from that tweet onward. Provide either id or url.
Full status URL of the thread's first tweet. The endpoint reads forward and does not walk backwards, so a later tweet's URL returns only the tail from that tweet onward. Provide either id or url.
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.
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.
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/tweet/thread?id=1759123456789012345&url=https%3A%2F%2Fx.com%2Fnaval%2Fstatus%2F1759123456789012345&fields=id%2Ctext%2Ccreated_at%2Cauthor.username&compact=1&paid_promotion=only"{ "tweets": [ { "id": "1759123456789012345", "text": "1/ Here is how we made the API 100x cheaper.", "author": { "id": "745273", "username": "naval" } }, { "id": "1759123456789012346", "text": "2/ It starts with batching ~20 tweets per call.", "author": { "id": "745273", "username": "naval" } } ], "count": 2}{ "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.", "top_up_url": "https://www.twitterapis.com/dashboard/buy-credits?utm_source=api&utm_medium=402"}{ "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
| Unit | Price |
|---|---|
| Per call | $0.0040 |
| Per 1,000 calls | $4.00 |
A thread returns in one $0.004 call; the endpoint takes no cursor, so there is no second page. Passing a mid-thread tweet still costs the full $0.004 while returning an incomplete thread, so resolve the conversation_id first.
When to use
Use it to capture a whole multi-tweet thread from one link, for example archiving a founder's 20-part launch thread. Resolve the link to its conversation_id first and pass that, or you will only get the tail of the thread.
Related endpoints
- Tweet Detail: Fetch a single tweet's full object by ID.
- Tweet Replies: Page through the replies to a tweet.
- Tweet Retweeters: List the users who retweeted a tweet.
FAQ
Do I need the first tweet of the thread?
Yes. The endpoint reads forward from the tweet you pass and does not walk back to the thread start, so a mid-thread tweet returns only that tweet and the ones after it. Every tweet carries conversation_id, which is the ID of the thread's first tweet: read it from Tweet Detail and pass that.
What counts as a thread here?
It is the author's own connected chain of tweets, not the replies from other accounts. Use Tweet Replies for those.
How are very long threads handled?
The whole thread is returned in a single call. There is no cursor and no second page, which is what the $0.004 premium buys.
Tweet Retweeters GET
Fetch the users who retweeted a given tweet, cursor-paginated. Useful for amplification analysis and identifying the accounts that spread a post. Cost: $0.0008 per call.
Tweet Quotes GET
Fetch the quote tweets of a given tweet, cursor-paginated as full tweet objects, so you can read the commentary people attached rather than just count it. This endpoint is search-backed rather than served by a dedicated X operation, and every response says so in-band via source, search_query and quote_matched. Cost: $0.0008 per call.