Skip to content

How to search tweets by date and archive an account's tweets

How to search tweets by date with X's since: and until: operators, real advanced search examples, and an API script that archives any account's tweets to JSON.

Piyushh · October 14, 2026 · 8 min read

To search tweets by date on X, add since: and until: to any search, for example from:nasa since:2024-04-01 until:2024-04-15, or use the Dates fields in Advanced search. That works for one-off lookups. Archiving an account's tweets is a different job. You want every tweet in a date range saved as data, and that takes an API and a loop.

This guide covers both. The first part shows how to search tweets by date in the X app: which operators do the filtering and which ones X's own API rejects. The second part is a working script that pulls an account's tweets into JSON, plus a way to reach dates the timeline won't page back to.

X's advanced search help page (checked 2026-10-14) walks through the form: search, click Advanced search under Search filters (or More options), fill in the fields, and run the search. In the Dates section you can set a "from" date, a "to" date or both, and X says you can search "for posts from any date since the first public post."

The help page covers the form but not the operators you can type. X's developer docs confirm that web search uses the names min_faves: and min_retweets: (operator docs, checked 2026-10-14). Everything else below is long-standing X search syntax. Typing operators is faster than filling in the form:

OperatorWhat it doesExample
since:YYYY-MM-DDTweets on or after a datelaunch since:2026-09-01
until:YYYY-MM-DDTweets before a datelaunch until:2026-10-01
from:handleTweets by one accountfrom:levelsio
to:handleReplies sent to one accountto:XDevelopers
min_faves:NAt least N likesmin_faves:500
min_retweets:NAt least N repostsmin_retweets:100
min_replies:NAt least N repliesmin_replies:20
filter:linksOnly tweets with linksfilter:links
-filter:repliesDrop replies-filter:replies
lang:xxOne languagelang:en

On until:: treat the end of a range as fuzzy. For all of September, set until:2026-10-01 and check each tweet's timestamp in your own code instead of trusting the boundary to the minute. API timestamps (createdAt) are in UTC, so they may not match the day you saw on your screen.

Search tweets by date: worked examples

  • Everything one account posted in a two-week window: from:nasa since:2024-04-01 until:2024-04-15
  • Replies people sent a brand during an outage: to:github since:2026-06-10 until:2026-06-12
  • Popular tweets on a topic in a month: "cold email" min_faves:200 since:2026-09-01 until:2026-10-01
  • Your own old tweets about a subject: from:yourhandle "conference" until:2020-01-01
  • Original tweets with links only: from:levelsio filter:links -filter:replies since:2026-01-01

Growth people mine ideas with the same operators. @LoganTGott's recipe: "Type a general topic followed by min_faves:1000", click the Top tab, and "Every result is a post with 1,000+ likes" (post, October 2026).

Why X search misses tweets you know exist

X search does not index every tweet, and nothing on the search box tells you that. In r/Twitter, u/Wanginmang guessed that "old and no any engagement" posts are left out of search, and u/apokrif1 noticed "You may get more results in "top" than in "latest"!" (thread). The original poster later said search came back after a few months, which points to a glitch rather than a policy. In August 2026 another user wrote that search had been "completely broken for well over a month" while they were trying to find old tweets "for archival purposes" (thread).

These are user reports, not measurements. They matter because any tool built on X search, an API's search endpoint included, inherits whatever X search returns. A search endpoint can't return a tweet that X search is missing. For your own account, there is a better source.

Your own tweet archive: the complete record

X lets you download everything you've posted. The archive help page (checked 2026-10-14) gives the steps in the app: Settings and privacy, Account, Your X data, verify your identity with a code, then Request data next to X. When the .zip is ready, X emails you a link, and it warns this "may take a few days." The archive holds your posts, DMs, media, followers and following as HTML and JSON files.

Since search started misbehaving, people have been turning the archive into their own search engine. Ken Wheeler suggested you "download your whole twitter archive and have the clankers build a search that works and find any tweet of yours ever like basically instantly" (post). @ZyMazza did the same: "twitter search is still broken, but you can download your twitter archive, point hermes at it, and then find any tweet you want" (post).

This only covers your own account. To get a tweet archive for anyone else, or to search archives across many accounts, you need an API.

Archive any account's tweets with an API

Two ChatterAPI endpoints cover this. Both are read-only and both run on the same key:

  • x.tweets (GET /v1/x/users/{handle}/tweets) pages through one account's recent tweets, newest first, at 3 credits per page of about 20. The free X timeline scraper makes the same call from a browser.
  • x.search (GET /v1/x/tweets/search) accepts any X operators in q, plus since and until parameters in YYYY-MM-DD, sort (latest or top), lang and includeRetweets. It costs 3 credits per page of about 20. You can try it without code in the free X tweet search.

Neither needs an X developer account. There's no key to apply for and no OAuth app.

Search tweets by date over the API

This is a date-bounded search. The response below is real, recorded with a test key, which returns one sample per endpoint for free. We trimmed it to three rows and the useful fields.

curl -G "https://api.chatterapi.com/v1/x/tweets/search" \
  -H "Authorization: Bearer $CHATTERAPI_KEY" \
  --data-urlencode 'q=crm recommendation' \
  --data-urlencode 'until=2026-10-01'
{
  "data": [
    {
      "id": "2099495333231288346",
      "text": "meta ads: how important is the “connect to your crm” recommendation? ...",
      "url": "https://x.com/HesomParhizkar/status/2099495333231288346",
      "createdAt": "2026-09-14T13:47:48.000Z",
      "likes": 2,
      "replies": 2,
      "views": 138,
      "isReply": false,
      "author": { "handle": "HesomParhizkar", "followers": 584 }
    },
    {
      "id": "2040879100261458222",
      "text": "Here's a live audit on what happens when buyers ask AI for a CRM recommendation. ...",
      "createdAt": "2026-04-05T19:47:49.000Z",
      "likes": 4,
      "author": { "handle": "apoorvshrm", "followers": 2316 }
    },
    {
      "id": "2030294157340860574",
      "text": "Biggest thing I learned building LeadSignal: ...",
      "createdAt": "2026-03-07T14:47:02.000Z",
      "likes": 3,
      "author": { "handle": "mohitbajoriaa", "followers": 531 }
    }
  ],
  "page": { "nextCursor": "AcWNIo1WFWYR…", "hasMore": true },
  "credits": { "charged": 0, "remaining": 719 },
  "requestId": "req_01M4X1JQMHXQYRQW06M8",
  "cached": true
}

The sample page held 20 tweets, newest first, going back to 2019. A live key charges 3 credits for it, and the test key shows charged: 0. To get the next 20, pass page.nextCursor back as cursor. The operators can go in q (from:levelsio since:2026-09-01), or you can use the since and until parameters. Either works. Pick one and stay consistent.

A Python script that archives an account by date

This script pulls every tweet from one account in a date range and writes JSON lines. The main block walks the range in monthly windows with x.search and from:, and timeline() is there for when you only need the recent stretch from x.tweets. Windows are the default because timelines don't page back forever: X's own API docs say its user timeline endpoint returns "up to 3,200 most recent Posts" (X docs, checked 2026-10-14). A search by date window doesn't depend on how many tweets came after.

import json, os, datetime as dt
import requests

API = "https://api.chatterapi.com/v1"
H = {"Authorization": f"Bearer {os.environ['CHATTERAPI_KEY']}"}

def get(path, **params):
    r = requests.get(f"{API}{path}", headers=H, params=params, timeout=60)
    r.raise_for_status()
    return r.json()

def timeline(handle, since, max_pages=50):
    """Newest-first pages from x.tweets until we pass `since`."""
    cursor, pages = None, 0
    while pages < max_pages:
        body = get(f"/x/users/{handle}/tweets", includeRetweets="false",
                   **({"cursor": cursor} if cursor else {}))
        pages += 1
        rows = body["data"]
        yield from (t for t in rows if (t["createdAt"] or "") >= since)
        oldest = min((t["createdAt"] or "" for t in rows), default="")
        print(f"page {pages}: {len(rows)} tweets, oldest {oldest[:10]}, "
              f"credits left {body['credits']['remaining']}")
        if oldest < since or not body["page"]["hasMore"]:
            return
        cursor = body["page"]["nextCursor"]

def window(handle, start, end, max_pages=20):
    """Every tweet by `handle` between two dates, via x.search."""
    cursor = None
    for _ in range(max_pages):
        body = get("/x/tweets/search", q=f"from:{handle}", since=start, until=end,
                   includeRetweets="false", **({"cursor": cursor} if cursor else {}))
        yield from body["data"]
        if not body["page"]["hasMore"]:
            return
        cursor = body["page"]["nextCursor"]

def months(start, end):
    d = dt.date.fromisoformat(start)
    stop = dt.date.fromisoformat(end)
    while d < stop:
        nxt = (d.replace(day=1) + dt.timedelta(days=32)).replace(day=1)
        yield d.isoformat(), min(nxt, stop).isoformat()
        d = nxt

if __name__ == "__main__":
    handle, since, until = "levelsio", "2026-01-01", "2026-10-01"
    seen = set()
    with open(f"{handle}.jsonl", "w") as f:
        for start, end in months(since, until):
            for t in window(handle, start, end):
                if t["id"] not in seen and since <= (t["createdAt"] or "") < until:
                    seen.add(t["id"])
                    f.write(json.dumps(t) + "\n")
    print(f"saved {len(seen)} tweets")

If you only need recent weeks, swap window() for timeline(). It's simpler and stops on its own once tweets are older than since. A few details keep it reliable:

  • Dedupe on id. Monthly windows can overlap at the edges, and timeline pages can overlap too if the account tweets while you're paging.
  • Filter by createdAt in code, so the range is exact no matter how the operator handles boundaries.
  • Treat max_pages as a budget. Every page is a charge, and a busy account can run to hundreds of pages.
  • Store the raw JSON. Likes and views change over time, so a snapshot dated to when you pulled it is more honest than a single "current" number.

What it costs

At 3 credits for about 20 tweets per page, plan on roughly 15 credits per 100 tweets. An account posting 10 times a day produces about 300 tweets a month, which is 15 pages and 45 credits. A full 3,200-tweet timeline comes to around 160 pages, or about 480 credits. Failed calls cost nothing. Every response includes credits.remaining, and the script prints it so you can stop early.

Search vs timeline: which to use

You wantUseWhy
Tweets matching words in a date rangex.search with since/untilOperators filter on X's side, so you only pay for matches
An account's last few weeksx.tweetsNewest first, no query to tune
One account across older monthsx.search with from: per monthEach window is independent of how much the account posted since
Your own complete historyX's archive downloadIt's the only complete record, and it's free
A live feed of new matchesx.search with sort=latest on a scheduleDedupe on id between runs

If you also track Reddit, our AI agent guide to Reddit and X data shows how to wire these endpoints into an agent. To have an agent run the searches for you in plain English, the best MCP servers for Reddit and X compares the options. To search Reddit and X together in one request, see how to search Reddit and X in one API call.

The case for just using X's own tools

You can make a fair case for skipping APIs entirely. For your own tweets, the archive download is complete, free and yours. Searching it locally with a script, or handing it to an AI tool as several people above did, beats any search endpoint because there's no search index in the way. For occasional lookups of other accounts, the operators in X search cost nothing.

An API is worth it when you need other people's public tweets as data, on a schedule, or across many accounts and date ranges. It won't fix the gaps in X search, since a search endpoint can only return what X search returns. The timeline endpoint and date windows reduce that dependence. If completeness is a legal or research requirement, though, check X's terms and consider X's own paid API, which offers full-archive search on pay-per-use plans according to X's search docs.

Try it

ChatterAPI gives your code and your agents Reddit and X data through one key, over REST or MCP, and you don't have to apply for a developer account. Sign up with Google and you get 100 free credits without entering a card. That covers about 33 pages of tweet search, or roughly 650 archived tweets. Try the script above on an account you follow. Plans start at $19 a month for 25,000 credits.

FAQ

How do I search tweets from a specific date on X?
Type your keywords in X search and add since:YYYY-MM-DD and until:YYYY-MM-DD, for example from:nasa since:2024-04-01 until:2024-04-15. Or open Advanced search from the search results page and pick a from and to date in the Dates section.
Can I search someone else's old tweets?
Yes, if the account is public. Combine from:handle with since: and until: in X search, or page through the account with an API. Protected accounts are only visible to approved followers.
Why doesn't X search find tweets I know exist?
X search does not promise complete results. In r/Twitter, users report old posts with no engagement missing from search and getting more results in Top than in Latest. For your own tweets, the downloadable X archive is the complete record.
How do I download my own tweet archive?
Go to Settings and privacy, Account, Your X data, verify your identity with a code and tap Request data. X emails a link when the .zip is ready, which X says can take a few days. It includes your posts as HTML and JSON.
Can I archive another account's tweets with an API?
Yes, for public accounts. With ChatterAPI, x.tweets pages through an account's recent tweets at 3 credits per page of about 20, and x.search with from:handle plus since and until reaches specific older date ranges.

More from the blog

Make your first call on 100 free credits.

Sign up with Google, no card. One key for Reddit and X, over REST or MCP.