A self-contained, offline-friendly search page for your Twitter/X archive. No server, no database, no dependencies — just a Python build script and a single HTML file you open in any browser.
- Full-text keyword search across all your tweets
- Filter by year, "has photo", "has video", "replies only", or "original only"
- Inline photo grid and video player on each tweet card
- Lightbox for full-size image viewing
- Sort newest or oldest first
- Works entirely offline — no data ever leaves your computer
Go to Settings → Your account → Download an archive of your data on Twitter/X. You'll get an email with a .zip file when it's ready. Unzip it.
At minimum you need your tweet data files. Copy whichever of these exist in your archive:
| File | Format |
|---|---|
data/tweets.js |
Newer archive format (rename to tweet.js) |
data/tweet.js |
Alternate newer format |
data/2007_02.js … |
Old monthly Grailbird files |
data/deleted-tweets.js |
Optional deleted tweets |
For photos and videos, copy these folders too (optional but recommended):
| Folder | Contents |
|---|---|
data/tweets_media/ |
Named files: TWEETID-MEDIAID.jpg |
data/tweet_media/ or data/archive_tweet_media/ |
Hash-named files from older archives |
Your folder should look like:
tweet-search/
├── build.py
├── tweet.js ← your archive data
├── tweets_media/ ← your photos (optional)
└── archive_tweet_media/ ← older photos (optional)
python3 build.pyThis reads all your .js files, builds an in-memory index, maps photos/videos to tweets, and writes a single tweet_search.html file. It takes about 10–30 seconds depending on archive size.
Open tweet_search.html in any browser. Everything is embedded — you can move the HTML file anywhere as long as the tweets_media/ and/or archive_tweet_media/ folders stay next to it.
At the top of tweet_search.html (after running the builder), find this block and update your name and handle:
<div class="display-name">Your Name</div>
<div class="screen-name">@yourhandle</div>Or edit build.py and change the two placeholder strings in build_html() before running.
- Tweet data: All tweet JS files use one of three formats (newer
window.YTD.tweets, flatwindow.YTD.tweet, or old Grailbird monthly). The builder handles all of them, deduplicating by tweet ID. - Media mapping:
tweets_media/files are namedTWEETID-MEDIAID.ext, so the link is direct.archive_tweet_media/files are named with a SHA-256 hash of the originalhttps://pbs.twimg.com/media/…URL. The builder re-derives that hash from each tweet's media entities to find the right file.
- Search: All tweet text is embedded as JSON in the HTML. Search is pure client-side JavaScript — instant, no server needed.
- Python 3.7+ (standard library only, no
pip installneeded) - A Twitter/X data export
MIT — do whatever you like with it.
