A Python-based X (Twitter) media downloader integrating a Discord bot and a Web interface.
- Discord Bot
- Web Interface
- Dual Modes: Automatic and Manual
- Auto Download: Set a Discord channel as a "Tweet Download Channel" via
/set_channel. Any X links detected will be downloaded immediately. - Manual Download: Use the
/downloadcommand to preview tweet content and choose specific media (or all) to download.
- Auto Download: Set a Discord channel as a "Tweet Download Channel" via
- Multi-language Support (i18n)
- Discord commands support Traditional Chinese, Simplified Chinese, and English.
- Web Frontend Management
- Built-in FastAPI-driven web service for easy searching and viewing of download history.
- Python 3.12
- Tweety
- FastAPI (Web interface)
- TypeScript (Web interface)
- Tailwind CSS (Web interface)
- SQLite3 (Database)
- The project's frontend is located in
frontend/. Services for FastAPI and Discord are modularized insrc/services/, withmain.pyinheriting fromsrc/abc.py's ServicesABC.
- Python 3.12 or higher.
- Node.js installed.
- Recommended to use uv.
git clone https://github.com/NotKeKe/XMD.git
cd XMDTo save download time, the project does not provide pre-built frontend files. Please build the frontend yourself following these instructions:
- Enter the
frontenddirectory:cd frontend - Install dependencies:
npm install - Execute build:
- TypeScript:
npm run build - CSS (Tailwind):
npm run build:css
- TypeScript:
- Modify your
config.toml: config.toml Introduction. - Create a
data/folder. - Create
data/cookies.json- Log in to X (Twitter) in your browser.
- Get cookies (I use the Cookie Editor extension in Chrome, but any method works).
- Paste your X (Twitter) Cookies into
data/cookies.json. - The format should look like this:
{ "auth_token": "", "ct0": "" ... // Other cookie key-value pairs }
-
Using uv (Recommended)
- Sync virtual environment:
uv sync - Run program:
uv run main.py
- Sync virtual environment:
-
Using pip
- Install dependencies:
pip install -r requirements.txt - Run program:
python main.py
- Install dependencies:
-
Using Docker
- Build image:
docker build -t xmd . - Run container:
docker run -d \ -v $(pwd)/config.toml:/app/config.toml \ -v $(pwd)/data:/app/data \ -v $(pwd)/logs:/app/logs \ -p 8000:8000 \ --name xmd xmd
- Build image:
/set_channel: Toggle auto-download for the current channel./download <url>: Parse and download media from a specific tweet URL./my_id: Query your Discord User ID./help: Show full command help message.
- First Start
- After the first run, a
config.tomlwill be generated in the current directory, and the program will exit automatically. - If you choose to use docker, then rename
config.toml.exampletoconfig.toml.cp config.toml.example config.toml
- After the first run, a
- services_open
- Pay attention to
services_open. It includes options fordiscordandfastapi. At least one must be set totruefor the project to run. - If you enable
discord, make sure to fill in your bot_token in thediscordconfiguration.- If you don't know how to create a Discord Bot, refer to this guide.
- Pay attention to
- *_only_you (Crucial option, please read!!!):
- (
*_only_you, e.g.,x_only_you,discord_only_you) - If you want the X or Discord bot to reply to everyone, set
*_only_youtofalse. - Risk: Enabling replies for everyone carries a risk. Since media is downloaded directly to the local machine, it could be used for malicious attacks (e.g., multiple calls causing disk space depletion). If possible, *set _only_you back to true immediately after setting your user_id.
- (
- user_id:
- Both
twitteranddiscordsections have auser_idfield. The project defaults to only replying to "YOUR_USER_ID". Make sure to replace it with your own ID.- (You can find your Discord ID by right-clicking your avatar in Discord and selecting "Copy User ID", or by using the
/my_idcommand after the bot is running.)
- (You can find your Discord ID by right-clicking your avatar in Discord and selecting "Copy User ID", or by using the
- Both
❗Please do not use this project for any purposes that infringe on others' copyrights or violate laws. I am not responsible for any misuse.❗
- If you find this project helpful, remember to give me a Star 🌟!
- If you use this tool in your project or redistribute it, please remember to credit the source or Tag me. Thanks for your support!
- For bugs or suggestions, feel free to submit an Issue.


