Skip to content

How do you get an entire Twitter thread with an API?

Last updated August 24, 2026

Hand tweet/thread the id of the thread's first post, the conversation_id every post in it carries, and it returns the ordered array of tweets making up that author's connected chain, plus a count, in a single call however long the chain runs. You do not walk the reply chain yourself. It sits in the premium tier at $0.004, five times a standard read, because one request does the whole expansion.

Every rate here is the pricing TwitterAPIs publishes. The billed rate is $0.0008 per call; $0.04 per 1,000 tweets is derived from it at a full 20-tweet page, which is the default page size rather than a guaranteed yield (source: twitterapis.com/pricing).

Start from the first post in the chain

The route reads forward from the post you pass and does not walk backwards, so pass the thread's first post. Hand it a post from the middle and you get that post and the rest of the chain after it, which is the tail rather than the thread. In practice the id you hold is rarely the opener: it arrived from a search hit, a mentions feed, or somebody quoting the middle of a chain at you. You do not need to walk back to find the start, because every post carries conversation_id, the id of the post that opened the conversation. Read it from the post you have, with tweet/detail if you only hold an id, and send that to tweet/thread. When the opener is the author's own post, which it is for an ordinary thread, that one extra lookup turns any id you were handed into the whole chain.

What comes back

The response has two fields. tweets is an array of tweet objects in reading order, each carrying its own id, text, created_at and author. count is how many posts the thread holds. Because the array is already ordered, rendering a thread is an iteration and nothing more: no sorting by timestamp, no reassembling parent and child links, no deciding which of several replies continues the chain. The tweet objects are the same shape the rest of the surface returns, so a component that renders a search result renders a thread entry unchanged. Numeric ids come back as strings throughout, deliberately, because a tweet id overflows a JavaScript number.

Paging a very long thread

There is nothing to page. The whole thread comes back in one call, so the response carries no cursor and there is no second request to make, however long the chain is. That is a deliberate difference from the list style endpoints across the surface, where next_cursor drives a loop and the rule is to stop when the collection array comes back empty. Here the loop does not exist: send the id, read tweets, and the count field tells you how many posts the author wrote in the chain. If you are migrating code that expected a cursor on this route, delete the loop rather than keeping it as a safeguard, since a second call with the same id simply pays $0.004 again for the same answer.

What it does not return

This returns the author's own connected thread, which is the chain that one account wrote, not the conversation around it. Replies from other people are a different question with a different route: tweet/replies pages the direct replies to a given post, taking an id and a cursor, and it is billed at the ordinary read rate rather than the premium one. Keeping the two apart is what lets the thread call stay a single request. The selection of which posts belong to the author's narrative and which are bystanders happens upstream, which is precisely the work this endpoint exists to absorb on your behalf, and it is the part that is genuinely awkward to reimplement.

The single tweet companion

tweet/detail is the cheap companion and usually the first call. It resolves one id into the complete tweet object: author, favorite_count, retweet_count, reply_count and view_count, plus attached media and any quoted tweet. That is where you check whether an opening post is worth expanding at all, since engagement on the first tweet is a reasonable proxy for whether the chain matters to you. The division of labour is simple enough to state in one line. Use tweet/detail when you have one id and want everything about that single post, and reach for tweet/thread only when you actually want every post in the sequence rather than the one you happened to be handed.

Why the price tier is different

The cost table marks tweet/thread as premium for full thread expansion and prices it at $0.004. The reasoning is stated on the route priced beside it, grok/chat, which sits at the same tier: the premium is attributed to the wall clock cost of holding a long connection open plus the upstream work behind it, rather than to metering per record returned. That framing is useful because it tells you what you are actually paying for. You are not being charged by the tweet. You are paying for a request whose duration is not proportional to anything you control, and whose length you could not have predicted before you made it.

The arithmetic against doing it by hand

Work the numbers before building the manual version. One expansion is $0.004, so five threads cost the same as twenty five ordinary reads, and expanding a hundred threads comes to forty cents. Against that, stitching a chain yourself is an unbounded number of standard calls at $0.0008 each, and the count is not knowable up front because thread length is not knowable up front. The comparison flips the other way for engagement figures: if you want favorite and view counts per post, a twelve post thread means twelve detail lookups at just under a cent in total, which is more than double what the expansion itself cost you. For scale, the $0.50 of credit a new account starts with is 125 expansions, or 625 ordinary reads if you spend it the other way.

Rate ceiling and batching

One ceiling covers every route on a key: 600 requests a minute and 20 concurrent. Because expansions are the expensive call here, that ceiling is rarely what limits a thread job, spend is. Six hundred expansions inside a minute is $2.40, so a queue saturating the rate limit with this endpoint is burning money faster than most crawls justify. Run it at whatever concurrency your pipeline wants up to twenty, and if you do reach the ceiling the response is a 429 carrying a Retry-After header, which tells you how long to wait rather than leaving you to model a separate quota for every endpoint you touch. The ceiling is flat across routes and applies per key, so a cheap search loop and an expensive expansion loop draw on the same allowance instead of each getting one of their own.

Where the ids come from

Thread ids come from wherever you already read posts. A keyword search returns tweet ids, a mentions feed returns tweet ids, and a reply or a quote carries one too, so any of those pipelines can hand an id straight to this route with no resolution step in between. The practical pattern is a two stage job: find candidate posts cheaply with search or a timeline read at the standard rate, filter them on engagement with tweet/detail, then expand only the ones that survived the filter. That keeps the premium call rare, which is the only real budget control this endpoint gives you. A detail lookup is a fifth of an expansion, so discarding four candidates in five already pays for the filter. $0.004 a call, per the rates we publish.

How to unroll a thread in one call

Unrolling a thread means turning a chain of posts one author wrote into a single readable piece. With this API it is one request: GET /twitter/tweet/thread with the id or url of the thread's first post returns the author's connected chain as an ordered tweets array, plus a count. Join the text of each entry in order and you have the unrolled thread. Strip the leading numbering many authors use, such as 1/ or 2/10, if you are rendering prose. Keep each entry's id beside its text, so a reader can jump back to the original post. Media on any entry sits under that entry's media array, so an unrolled view can show images inline. The call costs $0.004 whatever the thread length, which is what makes it cheaper than walking the chain post by post for anything beyond a handful of entries.

Is it legal to scrape Twitter threads?

Reading public posts through an API is a different act from logging in and scraping pages, and that distinction carries most of the legal weight. This endpoint returns posts that are already public, and you never accept X's terms as a logged-in user to get them, because you do not use an X account at all. What you do with the data afterwards is where the obligations sit: personal data rules such as GDPR apply to stored posts that identify people, copyright stays with the authors, so republishing whole threads is not the same as analysing them, and deleted posts should leave your store when you learn of the deletion if you serve them to others. Quoting a short excerpt with a link, summarising, and aggregate analysis are the common, low-risk uses. This is a practitioner's read, not legal advice; a commercial product built on stored posts deserves a lawyer's review.

One thread call against stitching it by hand

Questiontweet/threadHand rolled walk
Requests neededOne, from the first post, however long the chainOne per hop, count unknown before you start
OrderingAlready in reading order in the tweets arrayYou reconstruct it from timestamps and reply links
Picking the author's own postsSelected upstreamYou filter other people's replies yourself
Price per call$0.004$0.0008 each, total depends on thread length
Engagement counts per postLook each id up with tweet/detailAlready present if you fetched every post
End of chain signalThe response holds the whole chain; count says how many postsYou decide when to stop walking
The Timelines endpoints let you retrieve Posts from user timelines, mention feeds, and home feeds.
X Developer Platform, Timelines documentation. Source

Questions and answers

Do I need the first tweet of the thread?
Yes. The route reads forward from the post you pass, so a post from the middle returns only the tail of the chain from that point on. If the id you hold is not the opener, read its conversation_id, which every post carries and which names the post that started the conversation, and pass that instead. For an ordinary thread that is the author's first post, and the call then returns the whole chain.
Does it include other people's replies?
No. It returns the author's connected thread, so what comes back is the chain that one account wrote rather than the discussion around it. For the answers other accounts left, tweet/replies pages the direct replies to a given post and is billed at the ordinary read rate rather than the premium one. The two routes answer genuinely different questions and are priced accordingly.
How do very long threads paginate?
They do not need to. tweet/thread returns the whole connected chain in one call, with the posts in a tweets array and their number in count, so there is no cursor to follow and no second page to request. One call at $0.004 covers a three post thread and a fifty post thread alike.
Why does a thread cost more than a tweet lookup?
It sits in a premium tier at $0.004 against $0.0008 for a normal read. The cost table calls it full thread expansion, and on the route priced beside it attributes that tier to the wall clock cost of holding a long connection open plus the upstream work behind it, rather than to how many records land in the array you get back.
Can I get engagement numbers for each post in the thread?
The thread array holds tweet objects, and tweet/detail is the route documented with favorite_count, retweet_count, reply_count and view_count on a single id. If you need those figures pinned down per post, take the ids from the thread and look each one up, which is a standard read apiece. On a twelve post chain that costs more than the expansion did.
Should I call tweet/detail or tweet/thread?
Call tweet/detail when you have one id and want everything about that post, including its engagement counts, attached media and any quoted tweet. Call tweet/thread when you want every post in the author's chain in reading order. The cheap pattern is both in sequence: detail first as a filter, expansion only on the posts that clear whatever bar you set.
Are the tweet ids safe to store as numbers?
No. Ids are returned as strings throughout this API precisely because a tweet id is large enough to lose precision in a JavaScript number. Keep them as strings from the response all the way into storage. Converting one to a number and back is the classic way to end up requesting a tweet that is close to the one you meant but is not it.
Can I combine thread expansion with search?
Yes. A search hit gives you a tweet id, and that id is all the thread route needs, so a pipeline that finds posts by keyword can expand each interesting one into its full chain. Budget for it, because the expansion sits in a higher tier than the search that found the post, which makes filtering before expanding the whole game.
How many thread calls can I make per minute?
One flat ceiling covers every route on a key: 600 requests a minute with 20 concurrent. For this endpoint the practical limit is money rather than throughput, since 600 expansions in a minute is $2.40. If you do hit the ceiling, the response is a 429 carrying a Retry-After header telling you how long to hold off, rather than a per endpoint quota you have to model. The allowance is shared across every route on the key, so a search loop running beside your expansions draws on the same 600.
How do I know when a thread is finished?
Read count and next_cursor together. A null or empty next_cursor on a page that returned tweets is the end of the chain. The reliable rule across this API is to stop when the collection array comes back empty, because a couple of endpoint families keep returning a cursor even after the last row, and a loop trusting only the cursor will spin.

Start with $0.50 in free credits

No credit card. Roughly 12,500 tweets to test every endpoint.