XStash is a free, open-source desktop app for exporting your X (Twitter) bookmarks and likes, downloading attached media, and keeping account-specific exports organized locally.
No cloud. No API keys. Just your data, on your machine.
- Browser-based auth capture — a local Chromium extension bridges your real X session to the desktop app. No passwords, tokens, or API keys leave your device.
- Multi-account support — connect and switch between multiple X accounts.
- Bookmarks & Likes export — scrape your full bookmark and likes timelines.
- Rich export formats — JSON, CSV, JSONL, SQLite, XLSX, media index, and ZIP bundle.
- Media downloads — images, videos, and GIFs organized by account and media owner.
- Local-first — all data stays on your machine. No cloud backend, no telemetry.
- Node.js 18+ (LTS recommended)
- A Chromium-based browser (Chrome, Edge, Brave, etc.)
npm installnpm run devXStash captures authentication through a small local browser extension that reads request headers from your real X session.
- Open your Chromium-based browser's extensions page (
chrome://extensions). - Enable Developer mode.
- Click Load unpacked and select the
browser-extension/xstash-auth-bridgefolder. - Start XStash and click Connect account.
- XStash opens
x.com/i/bookmarksin your default browser — log in normally if needed.
The extension only communicates with the local XStash app over http://127.0.0.1:45873/xstash-auth.
# Type-check
npm run typecheck
# Build for production
npm run build
# Package installer (auto-detects OS)
npm run package
# Platform-specific
npm run package:win
npm run package:macXStash writes exports into the folder you choose in the app.
{selected-folder}/{mode}_{timestamp}.json
Optional companion files in the same folder:
| Format | Extension |
|---|---|
| CSV | .csv |
| JSONL | .jsonl |
| SQLite | .sqlite |
| Excel | .xlsx |
| Media index (CSV) | _media_index.csv |
| Media index (JSON) | _media_index.json |
| ZIP bundle | _bundle.zip |
{selected-folder}/
media/
{selected-account}/
{media-username}/
...
The download sync manifest is stored under Electron app data:
{userData}/xstash-sync-manifest.json
On Windows this is typically:
C:\Users\{you}\AppData\Roaming\xstash\xstash-sync-manifest.json
The main JSON export includes stable bridge fields for downstream tools:
| Field | Description |
|---|---|
sourceApp |
Always "xstash" |
schemaVersion |
Export schema version number |
exportedAt |
ISO 8601 timestamp |
mode |
"bookmarks" or "likes" |
accountUsername |
The X account used for scraping |
mediaRoot |
Relative path to media folder |
count |
Number of tweets in this export |
tweets |
Array of tweet objects |
- Auth data is stored locally and never uploaded to any remote service.
- Scraping and media downloads happen inside the desktop app after auth is captured.
- The browser extension is used only for auth capture, not for the scrape runtime.
- The local auth bridge uses CORS restrictions and a body size cap.
Contributions are welcome! Please open an issue first to discuss what you'd like to change.
- Fork the repo
- Create a feature branch (
git checkout -b feature/my-feature) - Commit your changes
- Push to the branch and open a pull request
If XStash is useful to you, support helps keep it maintained:
XStash is licensed under the GNU Affero General Public License v3.0.