WEIR

Download All Tweets from a User to CSV (2026 Guide)

How to download all tweets from a user: your own X archive in a few clicks, or a Python script that walks any public account back to 2006 into CSV.


Published · Updated · 8 min read

Cover image: Every tweet, back to 2006

To download all tweets from a user, use X's archive for your own account, or search any public account year by year into a CSV.

This guide is for researchers, marketers and developers who need every post from an X (Twitter) account in a spreadsheet. You get the archive steps, a Python script and the real cost. We run Weir, the API in the examples, so weigh our view knowing that.

This pulls one year of an account's posts:

curl --request POST \
  --url https://api.weirapp.io/v1/x/search \
  --header "Authorization: Bearer $WEIR_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{"fromUsers":["jack"],"since":"2006-01-01T00:00:00Z","until":"2007-01-01T00:00:00Z","limit":20}'

Here is the whole job:

  1. Check whose tweets they areYour own? The X archive beats any API.
  2. Get a keySign up, copy a key, set WEIR_API_KEY.
  3. Search one yearfromUsers plus since and until.
  4. Page to the endSend meta.nextCursor back until it is null.
  5. Loop every year into CSVOne file, one row per post.

Step 1: Download your own tweets from your X archive

If the tweets are yours, skip the API. X builds a full archive of your account for free.

X's Help Center lists these steps:

  1. Open Settings and privacy, then Your account.
  2. Choose Download an archive of your data and verify yourself with a code.
  3. Request the data. X says it may take a few days to prepare.
  4. Download the ZIP from the email or push notification X sends.

The ZIP holds HTML and JSON files, with a "Your archive" page that opens in a desktop browser. It covers your posts, and also your media and Direct Messages.

It only works for the account you're signed in to. For anyone else, read on.

Step 2: Get a key and search one year of posts

Sign up with no card, create a key under API keys, and set it:

pip install requests
export WEIR_API_KEY="weir_live_..."

Weir's search takes fromUsers for the account, and since and until for the dates. since is inclusive and until is not, both in UTC.

import csv, os, sys, time, requests

API = "https://api.weirapp.io/v1/x/search"
HEADERS = {"Authorization": f"Bearer {os.environ['WEIR_API_KEY']}"}

body = {"fromUsers": ["jack"], "since": "2006-01-01T00:00:00Z",
        "until": "2007-01-01T00:00:00Z", "limit": 20}
r = requests.post(API, headers=HEADERS, json=body, timeout=60)
for post in r.json()["data"]:
    print(post["createdAt"][:10], post["id"], post["text"][:60])
print("credits:", r.headers["x-credits-charged"])

Search reaches X's first days. We ran it on 21 October 2026 for @jack, X's co-founder, with until set to 22 March 2006. At limit: 3, the second page held post number 20:

{
  "id": "20",
  "text": "just setting up my twttr",
  "url": "https://x.com/jack/status/20",
  "createdAt": "2006-03-21T20:50:14.000Z",
  "author": { "username": "jack", "followersCount": 12533336 },
  "likeCount": 311641,
  "retweetCount": 124594
}

That is the first public post on X, and it came back in the same shape as a post from today.

Keep id as a string. Modern ids are too big for a float.

Step 3: Page through the year with the cursor

X serves about 20 posts per call. Every response carries meta.nextCursor; send it back unchanged for the next page.

null is the only stop:

def year_of_posts(user, year, max_pages=200):
    body = {"fromUsers": [user], "limit": 20, "since": f"{year}-01-01T00:00:00Z",
            "until": f"{year + 1}-01-01T00:00:00Z"}
    for _ in range(max_pages):
        r = requests.post(API, headers=HEADERS, json=body, timeout=60)
        if r.status_code == 429:  # too fast: wait, then retry the same page
            time.sleep(int(r.headers.get("Retry-After", "5")))
            continue
        r.raise_for_status()  # a 402 means out of credits: stop
        page = r.json()
        yield from page["data"]
        body["cursor"] = page["meta"]["nextCursor"]
        if not body["cursor"]:
            return

Our @jack walk ended the way every walk does. After post 20, the next call came back empty:

{ "data": [], "meta": { "nextCursor": null } }

That last call cost 1 credit. The three calls together cost 7 credits for four posts.

Step 4: Download all tweets from a user into one CSV

Loop over the years, newest first, and write each post as a row. Run it as python all_tweets.py XDevelopers:

FIELDS = ["id", "createdAt", "text", "likeCount", "retweetCount",
          "replyCount", "viewCount", "url"]
user = sys.argv[1]

with open(f"{user}.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.DictWriter(file, fieldnames=FIELDS, extrasaction="ignore")
    writer.writeheader()
    for year in range(2026, 2005, -1):  # back to 2006, X's first year
        for post in year_of_posts(user, year):
            writer.writerow(post)
        file.flush()  # a stopped run keeps every finished year

Put the three Python blocks in one file, in order, and that's the full script.

Years before the account existed come back empty, at 1 credit each. extrasaction="ignore" keeps the columns you named and drops the rest.

Search returns posts and replies. Add "onlyOriginal": True to the body to skip replies. More filters are in our X advanced search operators guide.

Can the Twitter API get all tweets from a user?

Yes, but not through the timeline. X's docs say its user Posts timeline returns up to the 3,200 most recent posts. That cap is why so many old scripts stop at 3,200.

X's full-archive search has no such cap. Per X's search docs, it reaches back to March 2006 and returns up to 500 posts per request.

It's open to X's pay-per-use accounts. Each post read costs $0.005 as of October 2026, so 3,200 posts cost $16.

For Tweepy code on the official API, see how to get tweets with Python.

What does it cost to download 3,200 tweets?

On Weir, a search call costs 1 credit plus 1 per post. A full page of 20 is 21 credits.

Downloading 3,200 posts from one account
Official X API$16
Weir, $5 packabout $0.68
TwitterAPI.ioabout $0.48

So 3,200 posts take 160 pages, plus one closing call per year. That's about 3,400 credits.

It fits inside the 5,000 free credits Weir gives every month, so your first account like this costs nothing. Price bigger jobs with the X API cost calculator.

Time matters too:

21credits for a full page of 20 posts
15search pages a minute on the free tier
12 minfor 3,200 posts on the free tier

The free tier allows 30 requests a minute, and a search counts as 2. The 429 branch in the script waits when you hit that limit.

If it doesn't work

  • A 402 stops the run. You're out of credits, and retrying won't help. Wait for next month's free grant or buy a pack.
  • A 400 on page two means the body changed. Start that year again without a cursor.
  • Reposts are missing. Search hides them. The timeline endpoint, /v1/x/users/{user}/posts, includes recent ones.
  • The run stopped halfway. Look up the last id in the file with the tweet ID to date converter, then restart from that year.
  • Excel shows ids as 2.0E+18. That's only the display. Import the id column as text.

Protected accounts can't be downloaded. Their posts never show up in search.

X's Terms of Service forbid scraping without X's written consent. Weir reads public data only and can't post. Whether your project fits the terms that apply to you is your call, and this isn't legal advice.

When not to use Weir

  • It's your own account. The archive is free and complete, Direct Messages included.
  • You need reposts from years ago. Search doesn't return old reposts.
  • Bulk volume is the whole job. TwitterAPI.io lists $0.15 per 1,000 tweets, below our paid rate, and it can also post and stream.
  • You need a contract with X itself. Use the official API's full-archive search.

FAQ

Can you download all tweets from a user for free?

For your own account, yes: request your archive in X's settings. For any public account, Weir's 5,000 free monthly credits cover about 4,700 posts. The official X API has no free tier for reading posts.

Can I download all tweets from a Twitter account I don't own?

Yes, if the account is public. Search with fromUsers one year at a time and page each year to the end. Protected accounts are visible only to approved followers, so no API returns them.

Why does my Twitter scraper stop at 3,200 tweets?

It reads the user timeline. X's docs cap that at the 3,200 most recent posts. Search by date range goes further: we reached @jack's first post from March 2006.

How do I export tweets to CSV in Python?

Use csv.DictWriter with extrasaction="ignore" and encoding="utf-8". Write each post as a row and flush after each year. The script in Step 4 does exactly that.

Sources