# Download an Account's Full Tweet History via API Canonical: https://www.twitterapis.com/answers/how-to-download-a-full-account-tweet-history Description: user/tweets/complete takes a numeric user_id and a max, paginates internally, and returns the archive in one $0.0024 call instead of dozens of pages. Generated: 2026-08-26T06:52:18.735Z ---[Pricing](/pricing)[Docs](https://docs.twitterapis.com)[Blog](/blogs) Compare and Tools [MCP Server](/mcp)[Integrations](/integrations)[Language Clients](/sdk)[Free Tools](/tools)[Twitter ID Finder](/tools/twitter-id-finder)[Twitter API Cost Calculator](/twitter-api-cost-calculator)[Twitter Search API](/twitter-search-api)[Twitter Followers API](/twitter-followers-api)[Twitter Scraper](/twitter-scraper)[Twitter API Use Cases](/twitter-api-usecases)[Twitter API Rate Limits](/twitter-api-rate-limits)[Twitter Unofficial API](/twitter-unofficial-api)[Twitter Free API](/twitter-free-api)[Twitter API Alternatives](/twitter-api-alternatives)[TwitterAPIs vs Tweepy](/twitterapis-vs-tweepy)[TwitterAPIs vs RapidAPI](/twitterapis-vs-rapidapi)[TwitterAPIs vs GetXAPI](/twitterapis-vs-getxapi) Company [About](/about)[Status](/status)[Affiliates](/affiliates)[Trust](/privacy-and-data-handling)[Changelog](/changelog)[Contact](/contact) [Start Free](/signup) 1. [Home](/) 2. /[Answers](/answers) 3. /How do you download an account's entire tweet history? # How do you download an account's entire tweet history? Last updated August 24, 2026 user/tweets/complete takes a numeric user\_id and a max, paginates inside the request, then returns the posts together rather than one cursor page at a time. It bills $0.0024 against $0.0008 for a standard timeline page, so 800 posts that would take 40 paged reads at $0.032 arrive in a single call for roughly a thirteenth of that. 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](/pricing)). ## Three routes, and which one old posts come from There are three ways to reach an account's back catalogue and they differ in who drives the loop. user/tweets pages a public timeline of original posts and reposts at $0.0008 a page, roughly twenty posts at a time, with your code holding the cursor and deciding when to stop. user/tweets\_and\_replies pages that same timeline with the account's replies included. user/tweets/complete is the premium route: it walks the history internally and hands everything back at once for $0.0024, whatever the volume turns out to be. If the question is how to get old posts specifically rather than recent ones, the premium route is the one that reaches backwards without dozens of round trips, and it is the only one where a single request can span years. ## What the archive call actually does differently Instead of returning a cursor and making your code drive the walk, this endpoint paginates inside the request and returns a count alongside a tweets array, newest first. There is no next\_cursor in the envelope at all, because there is no second page to fetch and no chain to resume. max defaults to 800 and controls how far back the internal walk reaches, so raising it buys history at the cost of wall clock time. The reference is explicit that large values can take tens of seconds, which makes this a job-shaped call rather than something to drop inside a request handler with a short timeout. It also means a failed call is retried whole rather than resumed, so pick a max you are willing to pay for twice. ## It wants a user\_id, never a handle The required parameter is user\_id, the numeric identifier such as 44196397, and the reference says plainly that it is not the @handle. If all you hold is a handle, resolve it through user/info first, which returns the full user object with id on it for one standard read. Cache that id against the account, because it is stable in a way the handle is not: someone can rename themselves tomorrow and the numeric id will not move. Every later archive run for that account then skips the lookup entirely and goes straight to the premium call. The reverse lookup exists too, user/info\_by\_id, for when you have the id from an archived row and want the current profile behind it. ## Reaching one old window instead of everything Sometimes the goal is not the whole history but a specific stretch of it, a launch week two years ago or the run-up to one announcement. That is a search job rather than an archive job. Put a from: clause and a date bound into the query parameter on tweet/advanced\_search and you pay $0.0008 a page for exactly that window instead of pulling everything newer to reach it. Post ids are monotonically increasing and therefore time-sortable, so since\_id: and max\_id: bound the same range when you already know the id sitting at each edge. Pick the archive route when completeness is the requirement and the search route when precision is, and note that the search route lets you apply an engagement floor while the archive route does not. ## Decide about replies before you archive The plain timeline route covers original posts and reposts. Only user/tweets\_and\_replies is documented as also including the replies an account wrote to other handles, and its rows carry in\_reply\_to\_username so you can separate the two kinds afterwards without guessing. That distinction matters more than it sounds: for a heavy replier, the replies are most of the volume, and an archive missing them is not a public record of anything. If a complete picture of public activity is the goal, plan a second pass rather than assuming one pull already holds it, then merge the two sets on the post id. Deciding this before the first call is cheaper than discovering it after you have stored a partial archive. ## The fields you get on every row Each archived row is a standard post object: id as a string, text with URLs already expanded, created\_at in X's date format, and an author block holding id, username, name and the verification flags. Engagement counters ride along where the upstream source exposes them, favorite\_count, retweet\_count, reply\_count and view\_count. Those counters are snapshots taken when you fetched rather than values frozen at posting time, so an archive pulled today and the same archive pulled next year will show identical text against different numbers. Store the fetch time next to each row, or any comparison you run later is measuring two different moments and reporting the difference as growth. The text field being pre-expanded means outbound link analysis needs no extra resolution pass. ## Arithmetic on a genuinely large account An account sitting on 5,000 posts is roughly 250 cursor pages through the standard timeline route at about twenty a page, which comes to $0.20 and 250 separate round trips your code has to sequence. The premium route charges $0.0024 per call regardless of what a single call returns, and the documented lever for reaching further back is a larger max rather than more calls. Archiving a hundred accounts at that rate is $0.24 in total, which is less than a single cup of coffee for a dataset that would take an afternoon to assemble by hand. The $0.50 sitting in a new account at signup covers more than two hundred archive calls before a card is ever involved, which is enough to validate the whole pipeline. ## Concurrency when archiving many accounts The ceiling is 600 requests a minute per key with 20 concurrent, and a fleet of archive calls is the one job that genuinely uses that concurrency, because each account is independent of every other. Run twenty in flight and the limiting factor becomes the tens of seconds a large max takes upstream, not the request allowance, which you will never come close to exhausting with calls this slow. Since it is a pooled read with no session registration involved, there is no per-account credential to rotate and nothing to keep warm between runs. The worker pool stays as simple as a queue of numeric user ids, a concurrency of twenty, and a retry that repeats the whole call. ## Dedupe, re-runs and merging two pulls Every id arrives as a string precisely so a 19 digit number does not lose its trailing digits to JavaScript precision, and that string is your deduplication key. Sort on created\_at rather than on array position when you merge two datasets, because two pulls taken at different times put the same post at different offsets. Overlapping a backfill with an earlier run is normal and safe: duplicate ids collapse cleanly and nothing about the endpoint holds state between calls, so there is no watermark to maintain and no cursor to persist. That is what makes an incremental top-up strategy work with no bookkeeping on the server side at all. Run it monthly, overlap generously, and let the id key absorb the repeats. $0.0008 a call, per our published pricing. ## Three routes to an account's posts Endpoint Per call What one call returns user/tweets $0.0008 About twenty timeline posts plus a cursor user/tweets\_and\_replies $0.0008 The same page, with the account's replies included user/tweets/complete $0.0024 Up to max posts, default 800, in one response user/info $0.0008 The user object, which is where the numeric id comes from tweet/advanced\_search $0.0008 One page of a from: query bounded to a date window tweet/detail $0.0008 A single post resolved by id, with its counters > The Timelines endpoints let you retrieve Posts from user timelines, mention feeds, and home feeds. X Developer Platform, Timelines documentation. [Source](https://docs.x.com/x-api/posts/timelines/introduction) ## Questions and answers How far back can I pull an account's posts? The archive endpoint fetches up to whatever max you request, defaulting to 800, and the reference states directly that larger values fetch more history and take longer to return. Start with a small max, around forty, to see the shape of the response and confirm your parser handles it, then raise it once the pipeline is stable. Opening with the largest number you can think of just makes the first failure slower and more expensive to diagnose. How do I get old tweets from a specific year? Use search rather than the archive route. Put a from: clause together with since: and until: bounds into the query parameter on tweet/advanced\_search and page the cursor at $0.0008 a page. That returns exactly the window you asked for instead of everything newer as well, which is usually cheaper when the target is one stretch of history. It also lets you add an engagement floor, which the archive route has no way to express. Why does it reject the @ handle? The parameter is user\_id and expects the numeric identifier, which stays constant even when someone renames their account. Resolve a handle into that id through user/info once, store it against the account record, and every later archive run skips the lookup entirely. Handles change and get recycled by other people; the numeric id does not, which is exactly why the premium route insists on it rather than accepting the friendlier-looking input. Does the archive include the account's replies? Treat that as a separate pass. The plain timeline route covers original posts and reposts, and user/tweets\_and\_replies is the endpoint documented as also carrying the replies an account sent to other handles. Run both if the goal is a full public record, then merge on the post id, using in\_reply\_to\_username to label which rows came from the reply side. For a heavy replier the two datasets differ by most of the total volume. Is one big call cheaper than paging? For a full history, clearly. Eight hundred posts through the standard timeline is roughly forty cursor pages, near $0.032, while a single archive call is $0.0024 regardless of how much comes back. Paging still wins when you only want the newest handful, since one timeline page is $0.0008 and returns immediately instead of taking tens of seconds. Pick by what you need, not by which number looks smaller in isolation. Why is the post id a string and not a number? Post ids run to 19 digits, which overflows the precision an ordinary JavaScript number carries, so they are serialised as strings to keep the trailing digits intact. Store and compare them as text throughout your pipeline, including in whatever database column holds them. A silently rounded id is the classic cause of duplicate rows in an archive, and it stays invisible until two records that should be distinct collide on the same key. Do I need a logged-in X account for this? No. The archive endpoint is documented as a pooled read, so no session registration is involved and your key alone authorises the call. Sessions matter for write actions and for the routes that read private surfaces, not for pulling a public timeline. That keeps a bulk archive job simple, with no cookie to register, nothing to refresh partway through a long run, and no per-account credential to rotate across a worker pool. How long does a large archive call take? The reference warns that larger max values can take tens of seconds, because the endpoint is doing internally the pagination you would otherwise be driving yourself. Give the request a generous client timeout, run it from a worker rather than a web handler, and treat a single archive call as a background job that produces a result. There is no cursor to resume from, so a timeout means repeating the whole call and paying for it again. Can I archive many accounts at once? Yes, and it is the job that best fits the allowance. Each account is independent, so twenty concurrent calls stay inside the 20 concurrent and 600 per minute ceilings while overlapping the upstream wait that dominates the wall clock. A hundred accounts at $0.0024 each is $0.24 in total. Since these are pooled reads there is no per-account credential to manage, so the worker pool is just a queue of numeric ids. What happens if I run the same archive twice? Nothing breaks. The endpoint holds no state between calls, so a second run simply returns the history again, newest first. Duplicate ids collapse against your existing rows if you key on the id string, which makes an overlapping incremental top-up the safe default rather than something to engineer around. Expect the engagement counters to differ between runs, since those are read at fetch time rather than frozen when the post was published. ## Keep reading - [Twitter Timeline API](/twitter-timeline-api?utm_source=aio&utm_medium=organic&utm_campaign=aeo-answers-how-to-download-a-full-account-tweet-history) - [Twitter User API](/twitter-user-api?utm_source=aio&utm_medium=organic&utm_campaign=aeo-answers-how-to-download-a-full-account-tweet-history) - [How do you get a Twitter user ID?](/answers/how-to-get-a-twitter-user-id?utm_source=aio&utm_medium=organic&utm_campaign=aeo-answers-how-to-download-a-full-account-tweet-history) - [Pay per use pricing](/pay-per-use-pricing?utm_source=aio&utm_medium=organic&utm_campaign=aeo-answers-how-to-download-a-full-account-tweet-history) - [Cost calculator](/twitter-api-cost-calculator?utm_source=aio&utm_medium=organic&utm_campaign=aeo-answers-how-to-download-a-full-account-tweet-history) ### Start with $0.50 in free credits No credit card. Roughly 12,500 tweets to test every endpoint. [Get your API key](/signup?utm_source=aio&utm_medium=organic&utm_campaign=aeo-answers-how-to-download-a-full-account-tweet-history)[See pricing](/twitter-timeline-api?utm_source=aio&utm_medium=organic&utm_campaign=aeo-answers-how-to-download-a-full-account-tweet-history) [ TwitterAPIs](/) The cheapest pay-as-you-go Twitter and X API. $0.0008 per call, which works out to $0.04 per 1,000 tweets on a full 20-tweet page. No subscriptions and no developer account. ## Product / API - [Pricing](/pricing) - [Pay-Per-Use Pricing](/pay-per-use-pricing) - [Cost Calculator](/twitter-api-cost-calculator) - [Rate Limits](/twitter-api-rate-limits) - [MCP Server](/mcp) - [Integrations](/integrations) - [Language Clients](/sdk) - [Changelog](/changelog) - [Status](/status) ## Developers - [Documentation](https://docs.twitterapis.com) - [API Reference](https://docs.twitterapis.com/docs/reference/search/tweet-advanced-search) - [User Info](https://docs.twitterapis.com/docs/reference/user-reads/user-info) - [User Tweets](https://docs.twitterapis.com/docs/reference/user-reads/user-tweets) - [Advanced Search](https://docs.twitterapis.com/docs/reference/search/tweet-advanced-search) - [Verified Followers](https://docs.twitterapis.com/docs/reference/follower-graph/user-verified-followers) ## Resources / Compare - [Answers](/answers) - [Reviews](/reviews) - [Free Tools](/tools) - [Twitter ID Finder](/tools/twitter-id-finder) - [Get a Twitter API Key](/twitter-api-key) - [Official X API Comparison](/twitter-api-pricing) - [Twitter API Use Cases](/twitter-api-usecases) - [Twitter API Alternatives](/twitter-api-alternatives) - [Twitter Unofficial API](/twitter-unofficial-api) - [Twitter Free API](/twitter-free-api) - [TwitterAPIs vs twitterapi.io](/twitterapis-vs-twitterapi-io) - [TwitterAPIs vs GetXAPI](/twitterapis-vs-getxapi) - [TwitterAPIs vs TweetAPI](/twitterapis-vs-tweetapi) - [TwitterAPIs vs TwexAPI](/twitterapis-vs-twexapi) - [TwitterAPIs vs RapidAPI](/twitterapis-vs-rapidapi) ## Legal - [About](/about) - [Security](/security) - [Trust](/privacy-and-data-handling) - [Terms of Service](/terms-of-service) - [Affiliates](/affiliates) - [Contact](/contact) - [Jobs](/jobs) © 2026 TwitterAPIs. All rights reserved. TwitterAPIs is an independent third-party API for developers and researchers. Not affiliated with, endorsed by, or sponsored by X Corp. All systems operational