mcp server
omnisaver
๐๏ธ Self-hosted content archiver for Twitter/X, YouTube, XiaoHongShu, WeChat, Reddit, Zhihu & more โ no API keys required
Set up
Runs on your computer. Pick your agent and operating system.
This project does not publish an install method we can turn into a config. Follow the README instead.
README
synced Oct 25, 2026OmniSaver โ Multi-Platform Content Archiver
A self-hosted content saver for your NAS, home server, or Raspberry Pi. Archive tweets, YouTube videos, XiaoHongShu (ๅฐ็บขไนฆ) posts, WeChat articles, and any webpage โ including images and videos โ to local storage with one click.
โจ Features
- Self-hosted โ runs on any Linux box, NAS, or Raspberry Pi
- No Twitter API key required โ uses Playwright browser automation
- Multi-platform support:
- Twitter/X โ save tweets, full threads, long-form articles, and videos
- Reddit โ save posts, galleries, inline images, videos, and author metadata
- YouTube โ save video metadata, subtitles, and channel info
- Bilibili (ๅๅฉๅๅฉ) โ save video metadata and high-quality videos
- Kuaishou (ๅฟซๆ) โ save videos via Playwright (no cookies needed)
- Instagram โ save reels, image posts, and carousels (with multiple images) via yt-dlp and Playwright
- Douyin (ๆ้ณ) / TikTok โ save videos without watermarks via Playwright (no cookies needed)
- Weibo (ๅพฎๅ) โ save posts, images, and videos via Playwright (no cookies needed)
- XiaoHongShu (ๅฐ็บขไนฆ) โ save image posts and videos via Telegram bot or REST API
- WeChat articles (ๅพฎไฟกๅ ฌไผๅท) โ save articles with images and formatting
- Any webpage โ Pocket-style read-it-later for any
http/httpsURL; uses Firefox Reader Mode algorithm (Mozilla Readability.js) to extract clean article content with images
- Full Twitter thread fetching โ when Twitter credentials are configured, entire reply chains are saved as a single archive with all media embedded inline
- Twitter long-form articles โ automatically detects and saves full article content from
/status/URLs - Twitter video downloads โ downloads videos via yt-dlp; authenticated downloads supported when credentials are configured
- Douyin/TikTok Native Scraper โ uses Playwright to bypass API restrictions and fetch unwatermarked videos directly from the original source
- Unified URL input โ paste any supported URL on the homepage; content type is auto-detected
- Tampermonkey userscript adds save buttons on Twitter/X tweets and YouTube video pages/thumbnails
- Saves content in multiple formats: plain text, Markdown, Reader-mode HTML
- Saves complete metadata (author, timestamp, stats) as JSON
- Built-in task queue with automatic retry on failure (exponential backoff)
- Redownload tasks โ manually trigger a full redownload for any task directly from the Tasks page
- Web UI with real-time log streaming, task monitoring, and content browsing
- Saved page shows a platform badge (X, YouTube, Douyin, ๅฐ็บขไนฆ, WeChat, or ๐ Web) on each card
- YouTube descriptions with clickable links โ bare URLs in video descriptions are automatically rendered as hyperlinks in the viewer
- Enhanced search: full-text search across content and article titles; filter by platform (multi-select), date range (quick presets or custom); all filters combine
- Supports infinite scroll and pagination (toggle per preference)
- Each archived post gets a unique public share link (
/view/<slug>) - Change password via the in-app user menu
- Optional: Android App โ native companion client for one-tap sharing via Android share menu (omnisaver-android)
- Optional: Telegram bot โ save content from any supported platform by forwarding links
- Optional: AI-powered tag generation via Gemini API
- Optional: video thumbnails via FFmpeg
๐ Quick Start
Prerequisites: Python 3.7+.
- yt-dlp โ required for Twitter/X and XiaoHongShu video downloads:
pip install yt-dlpor follow yt-dlp install guide - FFmpeg โ optional, for video thumbnails
# 1. Clone the repository
git clone https://github.com/yelosheng/omnisaver.git
cd omnisaver
# 2. Install Python dependencies
pip install -r requirements.txt
# 3. Install Playwright browser (required)
python -m playwright install chromium
# 4. Copy and edit the config file
cp config.ini.example config.ini
Web UI
python run_web.py
Open http://localhost:6201 in your browser. Default login: admin / admin.
Change the default password immediately after first login: click the user menu (top-right) โ Change Password.
Docker (Recommended for NAS / Home Server)
Docker is the easiest deployment method. yt-dlp and FFmpeg are included in the image.
The pre-built image is available on Docker Hub โ no local build required.
docker pull irritable0971/omnisaver:latest
# 1. Clone the repository
git clone https://github.com/yelosheng/omnisaver.git
cd omnisaver
# 2. Copy config
cp config.ini.example config.ini
# 3. Start
docker compose up -d
# 4. Open http://localhost:6201
All data (database, saved content, user credentials) is stored in ./docker-data/ on your host machine and persists across container restarts and rebuilds.
Note: The first build takes several minutes โ Playwright downloads Chromium (~200 MB) and yt-dlp is fetched during the build.
Custom port or save path โ edit docker-compose.yml before starting:
ports:
- "8080:6201" # change left side to use a different host port
volumes:
- /mnt/nas/twitter:/app/saved_tweets # point to your NAS or external drive
๐ฑ๏ธ Browser Extension (Tampermonkey) โ Best for Desktop
The most convenient way to save content on a desktop browser. A Tampermonkey userscript injects a save button directly below each tweet on Twitter/X and on YouTube video pages. On the YouTube homepage, a save icon appears on video thumbnails on hover.
Install:
- Install the Tampermonkey browser extension (Chrome, Firefox, Edge, or Safari)
- Start the web UI:
python run_web.py - Visit
http://localhost:6201/helpand click the install link โ Tampermonkey will open a confirmation dialog - Click Install โ the save button now appears on every tweet automatically
Configure the backend URL (required the first time, or when your server address changes):
- Click the Tampermonkey icon in your browser toolbar
- Find the Twitter/X Archiver Save Button script and click the settings icon
- Click โ๏ธ ่ฎพ็ฝฎๅ็ซฏๅฐๅ, then enter your server address
If the server runs on the same machine as your browser, the default http://localhost:6201 works out of the box. For a home server or NAS, use its local IP, e.g. http://192.168.1.100:6201.
The script file is at tampermonkey/twitter-saver.user.js.
๐ Twitter/X Credentials (Optional โ Enables Full Thread Fetching)
By default, the tool uses Playwright browser automation for scraping. Configuring Twitter cookies enables xreach โ a faster scraper that fetches complete reply threads and supports authenticated video downloads.
What credentials unlock:
- Full thread fetching โ entire self-reply chains saved as a single archive
- Authenticated video downloads via yt-dlp
- Faster scraping for single tweets
- Long-form Articles โ without cookies X serves only a card preview behind a login wall
Setup (via web UI):
- Log in to x.com in your browser
- Install Cookie-Editor browser extension
- On x.com, click the Cookie-Editor icon โ Export โ Export as JSON โ copy
- In the web UI, go to Settings โ Twitter/X Credentials โ paste the JSON โ Save
The tool extracts auth_token and ct0 from the JSON and stores them in config.ini. Credentials persist across restarts.
Note: Twitter sessions expire after weeks or months. If thread fetching stops working, repeat the cookie export and re-paste in Settings.
๐ฝ Reddit Credentials (Optional but Recommended)
Reddit posts can often be fetched anonymously, but cookies improve share-link resolution and reduce failures on media and profile requests.
What Reddit cookies help with:
- Resolving
reddit.com/r/.../s/...share links to canonical post URLs - More reliable image, gallery, and thumbnail downloads
- Fewer anonymous-access failures when Reddit blocks public JSON endpoints
Setup (via web UI):
- Log in to reddit.com in your browser
- Install Cookie-Editor browser extension
- On reddit.com, click the Cookie-Editor icon โ Export โ Export as JSON โ copy
- In the web UI, go to Settings โ Reddit Cookie โ paste the JSON โ Save
The cookie export must include reddit_session. It is stored locally at ~/.agent-reach/reddit/cookies.json.
Optional OAuth fallback: if Reddit starts blocking anonymous JSON access in your environment, set REDDIT_CLIENT_ID and REDDIT_CLIENT_SECRET in the environment before starting OmniSaver.
๐ค Telegram Bot โ Best for Mobile
The most convenient way to save tweets on a phone or tablet. Share any tweet directly to your private Telegram bot using the native Twitter/X share sheet โ no URL copying, no app switching.
Setup:
- Open @BotFather on Telegram, send
/newbot, follow the prompts, and copy the bot token - In the web UI, go to
/telegram, paste the token, and click Save & Start Bot - Open your new bot in Telegram and send
/startโ the first person to do this becomes the permanent owner; only the owner can trigger saves - The bot is now ready โ send or forward any
twitter.com/x.comlink to it and it will reply with a task ID and start saving immediately
On mobile (the main use case):
- Open a tweet in the Twitter/X app
- Tap the Share icon โ Share via... โ select your Telegram bot from the contact list
- The bot receives the link and queues the download โ you get a confirmation reply
Bot commands:
- Any message containing a Twitter/X URL โ queued for archiving
- Any message containing a YouTube URL โ queued for archiving
- Any message containing a XiaoHongShu URL โ saved immediately (see XHS section below)
- Any message containing a WeChat article URL โ queued for archiving
/statusโ shows current queue size
๐ฑ Android App โ Mobile Companion Client
For Android users, a dedicated companion mobile application is available:
- Repository: https://github.com/yelosheng/omnisaver-android
- Highlights:
- One-tap sharing from any app (Twitter/X, YouTube, Bilibili, ๅฐ็บขไนฆ, WeChat, Chrome, etc.) directly into your OmniSaver instance via the system Share sheet
- Real-time task progress tracking and saved archives browsing
- Configurable server address and API Key authentication
๐ XiaoHongShu (ๅฐ็บขไนฆ) Integration
XHS support is powered by agent-reach and its xiaohongshu-mcp Docker container. Once configured, you can save any XHS post by forwarding the link to the Telegram bot or calling the REST API.
Prerequisites
- Docker
- Node.js (for
mcporterandyt-dlpvia npm)
Setup
1. Install agent-reach
npm install -g agent-reach
agent-reach install
2. Start the XiaoHongShu MCP server
# Pull and start the container (cookies volume-mounted for persistence)
mkdir -p ~/.agent-reach/xhs
docker run -d --name xiaohongshu-mcp \
-p 18060:18060 \
-v ~/.agent-reach/xhs/cookies.json:/app/cookies.json \
xpzouying/xiaohongshu-mcp
3. Configure cookies (login required)
Log in to xiaohongshu.com in your browser, export cookies using Cookie-Editor (JSON format), then:
agent-reach configure xhs-cookies
# Paste the JSON cookie string when prompted
# Then copy it into the container's expected path:
docker exec xiaohongshu-mcp cp /cookies.json /app/cookies.json
4. Register the server globally
Add to ~/.mcporter/mcporter.json:
{
"mcpServers": {
"xiaohongshu": { "baseUrl": "http://localhost:18060/mcp" }
}
}
5. Verify
mcporter call 'xiaohongshu.search_feeds(keyword: "test")'
Saving XHS Posts
Via Telegram bot โ forward or paste any XiaoHongShu link. Supported formats:
- Full URL:
https://www.xiaohongshu.com/explore/<id>?xsec_token=... - App share text:
Title~ http://xhslink.cn/xxx Copy and open in XiaoHongShu!(the short link is extracted and resolved automatically; bothxhslink.cnand the olderxhslink.comwork)
The bot replies with the title, type, file count, and a /view/<slug> link.
Via REST API:
curl -X POST http://localhost:6201/api/submit/xhs \
-H "Content-Type: application/json" \
-d '{"url": "https://www.xiaohongshu.com/explore/<id>?xsec_token=<token>"}'
XHS Output Structure
saved_xhs/
โโโ 2024-01-15_Post-Title_feedid/
โโโ content.txt # Plain text description
โโโ content.md # Markdown with author info and stats
โโโ metadata.json # Full API response (no comments)
โโโ avatar.jpg # Author profile picture
โโโ images/ # Image posts: 01.webp, 02.webp, โฆ
โโโ videos/ # Video posts: <title>.mp4
โโโ thumbnails/ # Video cover image
Note: Cookies expire periodically. Re-run the configure step and restart the container when XHS calls start failing.
๐ฌ YouTube Integration
Save YouTube videos โ metadata, subtitles, and channel info are archived automatically.
Saving YouTube Videos
Via Web UI โ paste any YouTube URL into the homepage input field. Supported formats:
https://www.youtube.com/watch?v=VIDEO_ID
https://youtu.be/VIDEO_ID
https://www.youtube.com/shorts/VIDEO_ID
Via Tampermonkey userscript โ on any YouTube watch page, a save button appears in the action bar. On the homepage, a save icon appears on each video thumbnail on hover.
Via Telegram bot โ send or forward any YouTube link.
Via REST API:
curl -X POST http://localhost:6201/api/submit/youtube \
-H "Content-Type: application/json" \
-d '{"url": "https://www.youtube.com/watch?v=VIDEO_ID"}'
YouTube Settings
Go to /settings in the web UI to configure an optional YouTube Data API key (used for fetching channel avatars). Get a free key at Google Cloud Console โ Enable "YouTube Data API v3" โ Credentials โ API Key.
๐ Web Page Read-It-Later
Save any article or webpage for offline reading โ works like Pocket or Instapaper.
Saving Web Pages
Via Web UI โ paste any http:// or https:// URL into the homepage input field.
Via Telegram bot โ send any webpage link that isn't XHS/WeChat/YouTube/Twitter.
Via REST API:
curl -X POST http://localhost:6201/api/submit \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/article"}'
How It Works
Uses Playwright to render the page (executes JavaScript, triggers lazy-loaded images), then runs Mozilla Readability.js โ the same algorithm as Firefox Reader Mode โ to extract clean article content. Images are downloaded locally.
Web Page Output Structure
saved_tweets/
โโโ YYYY/MM/YYYY-MM-DD_title_hash/
โโโ content.html # Reader-mode HTML with inline images
โโโ content.txt # Plain text
โโโ content.md # Markdown with metadata header
โโโ metadata.json # Title, author, sitename, published date, source URL
โโโ images/ # Downloaded images
๐ฐ WeChat Article Integration
Save WeChat public account articles (ๅพฎไฟกๅ ฌไผๅทๆ็ซ ) with full text, images, and formatting.
Saving WeChat Articles
Via Web UI โ paste any WeChat article URL into the homepage input field.
Via Telegram bot โ send or forward any mp.weixin.qq.com link.
Via REST API:
curl -X POST http://localhost:6201/api/submit/wechat \
-H "Content-Type: application/json" \
-d '{"url": "https://mp.weixin.qq.com/s/ARTICLE_ID"}'
WeChat Output Structure
saved_wechat/
โโโ YYYY/MM/YYYY-MM-DD_article_id/
โโโ content.txt # Plain text
โโโ content.md # Markdown with title, author, publish time
โโโ metadata.json # Article metadata
โโโ images/ # Embedded images
โโโ videos/ # Embedded videos (if any)
โ๏ธ Configuration
Copy config.ini.example to config.ini and edit as needed.
| Option | Description | Default |
|---|---|---|
[storage] base_path | Directory where tweets are saved | ./saved_tweets |
[storage] create_date_folders | Create date-based subfolders | true |
[download] max_retries | Max retry attempts on download failure | 3 |
[download] timeout_seconds | Request timeout in seconds | 30 |
[scraper] use_playwright | Use Playwright browser automation (recommended) | true |
[scraper] headless | Run browser in headless mode | true |
[scraper] debug_mode | Save screenshots on errors | false |
[twitter] auth_token | Twitter auth_token cookie (optional, enables xreach thread fetching and long-form Articles) | unset |
[twitter] ct0 | Twitter ct0 cookie (required together with auth_token) | unset |
[ai] gemini_api_key | Gemini API key (optional, for AI tags) | unset |
[ai] youtube_api_key | YouTube Data API v3 key (optional, for channel avatars) | unset |
[telegram] bot_token | Telegram bot token (optional, for Telegram integration) | unset |
Environment variable overrides:
| Variable | Description |
|---|---|
SAVE_PATH | Override save path |
USE_PLAYWRIGHT | Override Playwright toggle |
PLAYWRIGHT_HEADLESS | Override headless mode |
PLAYWRIGHT_DEBUG | Set to true to enable debug screenshots |
SSL_CERT_PATH / SSL_KEY_PATH | Enable HTTPS |
๐ Usage
Web Interface
Visit http://localhost:6201 after starting.
| Route | Purpose |
|---|---|
/ | Submit any supported URL to start archiving (auto-detects platform) |
/tasks | View task queue status |
/saved | Browse and search all archived content (Twitter, YouTube, XHS, WeChat, Web) |
/tags | Manage AI-generated tags |
/retries | View failed tasks and retry manually |
/view/<slug> | View any archived post via share link |
/debug | System status and stuck task reset |
/telegram | Telegram bot configuration |
/settings | YouTube API key and XHS auto-save configuration |
/help | Tampermonkey script installation guide |
POST /api/submit | Submit any URL โ platform is auto-detected (JSON body: {"url": "..."}) |
POST /api/submit/xhs | Submit a XiaoHongShu URL (JSON body: {"url": "..."}) |
POST /api/submit/youtube | Submit a YouTube URL (JSON body: {"url": "..."}) |
POST /api/submit/wechat | Submit a WeChat article URL (JSON body: {"url": "..."}) |
CLI
# Archive a single tweet
python main.py https://x.com/username/status/1234567890
# Skip media downloads
python main.py https://x.com/username/status/1234567890 --no-media
# Specify output directory
python main.py https://x.com/username/status/1234567890 --output /path/to/save
# Show verbose output
python main.py https://x.com/username/status/1234567890 --verbose
Supported URL formats:
https://twitter.com/username/status/1234567890
https://x.com/username/status/1234567890
https://mobile.twitter.com/username/status/1234567890
https://m.twitter.com/username/status/1234567890
๐ Output Structure
saved_tweets/
โโโ 2024-01-15_1234567890123456789/
โโโ content.txt # Plain text
โโโ content.html # Reader-mode HTML
โโโ content.md # Markdown
โโโ metadata.json # Full metadata (author, timestamp, etc.)
โโโ avatar.jpg # Author avatar
โโโ images/
โโโ videos/
โโโ thumbnails/ # Video thumbnails (requires FFmpeg)
๐ท๏ธ AI Tag Generation (Optional)
Automatically generates semantic tags after each successful archive to aid categorization and search. Priority order:
- Gemini API โ set
gemini_api_keyinconfig.ini(recommended; generous free tier). - Rule-based โ no API key required; uses built-in keyword rules for basic tagging.
Manage tags on the /tags page, or trigger generation for individual items on the /saved page.
๐ง Troubleshooting
Tweet not found โ The tweet may have been deleted or made private. Verify the URL is correct and accessible in a regular browser.
Playwright browser not installed โ Run python -m playwright install chromium.
Network issues โ Check your connection and firewall. If Twitter/X is blocked in your region, configure a proxy before using this tool.
File permission errors โ Ensure write permission on the base_path directory and that sufficient disk space is available.
Tasks stuck in processing โ Visit /debug in the web UI and use the "Reset Stuck Tasks" function.
Enable debug mode โ Set debug_mode = true in config.ini or PLAYWRIGHT_DEBUG=true. Error screenshots will be saved in the project root.
โ ๏ธ Disclaimer
- For personal archival use only. This tool is intended for saving publicly available content for offline reading and personal research.
- Comply with platform Terms of Service. Users are solely responsible for their usage and its legal compliance. See Twitter/X ToS, YouTube ToS, and respective platform terms.
- No commercial use or mass scraping. Do not use this tool for commercial purposes, bulk data collection, ML training, or any form of mass scraping.
- Respect copyright. All content belongs to its original authors. Do not republish or redistribute without authorization.
- No liability for misuse. The author accepts no liability for any legal issues, account suspensions, or other consequences arising from misuse.
๐ License
MIT โ see LICENSE.
๐ค Contributing
Bug reports, feature requests, and pull requests are welcome. Please ensure existing tests pass before submitting:
python -m pytest tests/