vccs
Vue 3용 차트 컴포넌트 모음, Recharts에서 포팅
Telegram 채팅 기록을 CLI·GUI·WebUI·MCP·Skill으로 다운로드한다
Download any Telegram chat history: CLI, GUI, WebUI, MCP, Skill
데이터Python · ShellGitHub @popstas직접 설치운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A powerful command-line, GUI and web interface utility to download and analyze Telegram chat history in multiple formats.
Need to send or manage messages? This tool is download-only. To send
messages, create groups/topics, manage members and folders, see
popstas/telegram-assistant.
Need live monitoring instead of a one-off export? To watch chats, channels
and folders and forward matching messages in real time, see
popstas/telegram-resender.README 전문 보기 ↗A powerful command-line, GUI and web interface utility to download and analyze Telegram chat history in multiple formats.
Need to send or manage messages? This tool is download-only. To send messages, create groups/topics, manage members and folders, see popstas/telegram-assistant.
Need live monitoring instead of a one-off export? To watch chats, channels and folders and forward matching messages in real time, see popstas/telegram-resender.
--stt), cached so nothing is transcribed twice--presetLog in once before the first download. In a terminal, a download without a
session offers to log you in right there; everywhere else — the GUI, a cron job,
the console-less Windows build — it never prompts and tells you to run login
instead, so an unattended run fails with a message rather than waiting forever
for an answer nobody can type.
# Log in with a code from Telegram
telegram-download-chat login
# Log in by scanning a QR code with an app you are already logged into
telegram-download-chat login --qr
The login code is delivered by Telegram, and for third-party clients it usually
arrives in the Telegram app, in the chat named "Telegram" rather than by
SMS. If no code arrives at all, use login --qr: the code is confirmed from a
device where you are already logged in, so it does not depend on SMS. Add
--debug to see how Telegram chose to deliver the code.
Since September 2026 Telegram sometimes reports the code as sent to the app
(--debug shows SentCodeTypeApp with next_type=None) and then never
delivers it, on any device (#91).
The app cannot change how Telegram delivers codes, so QR login is the
way in for such accounts.
In the GUI, the same two options live on the Settings tab: fill in the phone and code, or press "Log in with QR code". For accounts with two-step verification, fill the Password field before scanning.
# Download chat by username
telegram-download-chat username
# Download chat by numeric ID (negative for groups/channels)
telegram-download-chat -123456789
# Download chat by invite link
telegram-download-chat https://t.me/+invite_code
# Download chat by phone number (must be in your contacts)
telegram-download-chat +1234567890
# Download multiple chats at once
telegram-download-chat chat1,chat2,chat3
# Download with a limit on number of messages
telegram-download-chat username --limit 1000
# Download all chats from folder
telegram-download-chat folder:folder_name
# Download messages on or after a specific date (YYYY-MM-DD)
telegram-download-chat username --min-date 2025-05-01
# Download last N days of messages from a specific date
telegram-download-chat username --max-date 2025-06-05 --last-days 1
# Filter messages by specific user
telegram-download-chat group_username --user 123456
# Filter messages containing given keywords (comma-separated, case-insensitive)
telegram-download-chat username --keywords "hello,bye"
# Download messages from a specific thread/reply chain
telegram-download-chat group_username --subchat 12345
# Specify custom output file
telegram-download-chat username -o custom_output.json
# Enable debug logging
telegram-download-chat username --debug
# Download messages with media attachments (photos, videos, documents, etc.)
telegram-download-chat username --media
# Include media type indicators in TXT output (e.g. [photo], [file=report.pdf])
telegram-download-chat username --media-placeholders
# Download a channel together with the comments under each post
telegram-download-chat channel_username --comments
# Cap comments fetched per post (here: 50 per post)
telegram-download-chat channel_username --comments --comments-limit 50
# Keep only comments with at least 2 total reactions
telegram-download-chat channel_username --comments --comments-min-reactions 2
# Include each message's reactions inline in the TXT output
telegram-download-chat username --reactions
# Transcribe voice messages and round video notes (Telegram Premium)
telegram-download-chat username --stt
# Split output into separate files by month or year
telegram-download-chat username --split month
# Split a forum into one subdirectory per topic
telegram-download-chat group_username --split topics
# Export a Telegram-style HTML page (alongside JSON/TXT)
telegram-download-chat username --html
# Export HTML with clickable media file-path captions
telegram-download-chat username --media --html --html-media-links
# Export a PDF document (alongside JSON/TXT)
telegram-download-chat username --pdf
# Disable parallel multi-connection media downloads (use single-stream)
telegram-download-chat username --media --no-fast-download
# Show current configuration
telegram-download-chat --show-config
# Output results summary as JSON to stdout
telegram-download-chat username --results-json
# Use predefined preset
telegram-download-chat username --preset short
# Resume download starting after a specific message ID
telegram-download-chat username --since-id 5000
usage: telegram-download-chat [-h] [-o OUTPUT] [--limit LIMIT] [--max-date DATE] [--last-days DAYS]
[--min-date DATE] [--subchat SUBCHAT]
[--subchat-name NAME] [--user USER] [--config CONFIG] [--debug]
[--sort {asc,desc}] [--show-config] [-v]
[chat]
Download Telegram chat history to JSON and TXT formats.
positional arguments:
chat Chat identifier (username, phone number, chat ID, or URL)
options:
-h, --help show this help message and exit
-o, --output OUTPUT Output file path (default: chat_<chat_id>.json)
-l, --limit LIMIT Maximum number of messages to download (default: 0 - no limit)
--since-id SINCE_ID Start downloading after this message ID
--min-date DATE Only download messages on or after this date (format: YYYY-MM-DD). Aliases: --until
--max-date DATE Only download messages on or before this date (format: YYYY-MM-DD). Aliases: --from
--last-days DAYS Number of days back from --max-date (or today) to download
--subchat SUBCHAT Filter messages by thread/reply chain (message ID or URL)
--subchat-name NAME Custom name for subchat directory
--user USER Filter messages by sender ID
-c, --config CONFIG Path to config file
--debug Enable debug logging
--sort {asc,desc} Sort messages by date (default: asc)
--split {month,year,topics}
Split output: by month, by year, or by forum topic
(one <chat>/<topic_slug>/ subdirectory per topic)
--show-config Show config file location and exit
--results-json Output results summary as JSON to stdout
--keywords KEYWORDS Only save messages containing these keywords (comma-separated)
--preset PRESET Use preset from config
--media Download media attachments to a separate folder
--no-fast-download Disable parallel multi-connection media downloads (use single-stream Telethon downloader)
--media-placeholders Insert media type indicators (e.g. [photo], [file=name.pdf]) in TXT output
--reactions Append each message's reactions as an inline text suffix (e.g. [👍5 ❤️2]) in the TXT output
--stt Transcribe voice messages and round video notes via Telegram speech-to-text (requires Telegram Premium; results are cached locally)
--html Export chat as a Telegram-style HTML file (alongside JSON/TXT)
--html-media-links Show clickable file path captions under each media element in HTML export
--pdf Export chat as a PDF document (alongside JSON/TXT)
--comments Download post comments from a channel's linked discussion group (channel-only; no-op on other entities and channels without comments)
--comments-limit N Max comments to fetch per post (requires --comments; omit for unlimited)
--comments-min-reactions N Drop comments with fewer than N total reactions before saving (requires --comments; 0 = keep all; applied after --comments-limit)
--overwrite Replace existing output files instead of resuming
--proxy-url URL Proxy URL for Telegram connection (socks5://host:1080, http://host:8080)
-v, --version Show program's version number and exit
pip install telegram-download-chat
Run it directly without installing:
uvx telegram-download-chat username
Or install it as a persistent tool:
uv tool install telegram-download-chat
For those who prefer a graphical interface, a GUI version is available.
Windows build is available in the releases page.
Install with GUI dependencies:
pip install "telegram-download-chat[gui]"
Launch the GUI:
telegram-download-chat gui
A portable, no-installer Windows distribution is produced with
build_windows_embed.ps1. It splits the distribution into two parts so updates
are tiny:
.\build_windows_embed.ps1
Outputs:
dist\telegram-download-chat-base-<version>.zip — the first install. Extract
anywhere and run telegram-download-chat.cmd (CLI) or the
telegram-download-chat-gui.vbs shortcut (GUI). No installer/registry changes.
It contains:
runtime\ — the base: the official Windows embeddable CPython plus all
third-party packages (PySide6/Qt, telethon, …) and the launchers. Installed
once; only re-downloaded when Python or a dependency is bumped.app\ — our source package only.dist\app-<version>.zip — the update (~150 KB). Each release ships just
this; the base is reused.Updating: in the GUI, open Settings → Software Update → Check updates; when
an update is available the button becomes Update now, which downloads
app-<version>.zip and swaps app\ in place, then offers to restart. To update
from the command line instead (atomic swap of app\):
runtime\python\python.exe -m telegram_download_chat.core.app_updater apply app-<version>.zip <install-dir>
Because our code and the dependencies live in separate parts, a normal release
update is a ~150 KB download instead of re-shipping the ~100 MB runtime. The base
changes only on a Python or dependency bump (then re-install the base zip). Note
the embeddable Python minor version is pinned by the base, so any dependency's
native .pyd is ABI-locked to it.
To wrap the portable tree into a classic setup.exe with Start Menu / desktop
shortcuts and an uninstaller, install Inno Setup 6
and run:
.\build_windows_installer.ps1
This runs build_windows_embed.ps1 first, then compiles installer.iss into
dist\telegram-download-chat-v<version>-setup.exe. The installer is per-user
(installs under %LOCALAPPDATA%\Programs, no admin) on purpose, so the in-app
"Update now" can swap app\ in place without elevation. Releases publish this
telegram-download-chat-v<version>-setup.exe alongside app-<version>.zip (the
in-app update asset).
A lightweight web interface built with Streamlit is also available.
Install with web dependencies:
pip install "telegram-download-chat[web]"
Launch the web UI:
telegram-download-chat-web
The CLI ships as an installable skill/plugin for AI coding agents, so you can ask
your agent to "download/export this Telegram chat" and it drives the CLI for you.
All three are generated from one source of truth —
skills/telegram-download-chat/SKILL.md — by scripts/gen_agent_plugins.py
(a test fails if they drift). After editing the skill, run:
python scripts/gen_agent_plugins.py
Claude Code — add this repo as a plugin marketplace, then install the
plugin (bundles the skill under skills/):
/plugin marketplace add popstas/telegram-download-chat
/plugin install telegram-download-chat
Manifests: .claude-plugin/marketplace.json, .claude-plugin/plugin.json.
Cursor — the project rule .cursor/rules/telegram-download-chat.mdc is
picked up automatically when this repo is open. To use it elsewhere, copy that
file into the target project's .cursor/rules/.
Codex (OpenAI Codex CLI) — copy .codex/prompts/telegram-download-chat.md
into ~/.codex/prompts/ to expose a /telegram-download-chat slash command
(pass the chat id / username / export path as the argument).
To use this tool, you'll need to obtain API credentials from my.telegram.org:
api_id and api_hash to your config.ymlThe configuration file is automatically created on first run in your application data directory:
%APPDATA%\telegram-download-chat\config.yml~/Library/Application Support/telegram-download-chat/config.yml~/.local/share/telegram-download-chat/config.yml# Telegram API credentials (required)
settings:
api_id: your_api_id # Get from https://my.telegram.org
api_hash: your_api_hash # Get from https://my.telegram.org
session_name: session # Optional: Custom session file name
request_delay: 1 # Delay between API requests in seconds
max_retries: 5 # Maximum number of retry attempts
log_level: INFO # Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
log_file: app.log # Path to log file (relative to app dir or absolute)
stt_cache_path: '' # Optional: custom path for the --stt transcript cache
# Map user IDs to display names for text exports
# Names for users and bots are automatically fetched and stored here, you can change them here.
users_map:
123456: "Alice"
789012: "Bob"
# Presets for frequently used argument sets
presets:
- name: short
args:
limit: 100
You can also specify a custom config file location using the --config flag.
You can extract messages from a Telegram export archive (result.json) that you've downloaded from Telegram Desktop:
# Extract all messages from all chats
telegram-download-chat "/path/to/Telegram Desktop/DataExport/result.json"
# Extract only messages from a specific user (by their Telegram ID)
telegram-download-chat "/path/to/Telegram Desktop/DataExport/result.json" --user 123456
# Save to a custom output file
telegram-download-chat "/path/to/Telegram Desktop/DataExport/result.json" -o my_exported_chats.json
This feature is particularly useful for:
--min-date or --last-days)The tool will process the archive and generate both JSON and TXT files with the exported messages.
If the download is interrupted, you can simply run the same command again to resume from where it left off. The tool automatically saves progress to a temporary file.
You can also resume later using --since-id with the last downloaded message ID or let the tool read it from the existing JSON file. Use --overwrite to replace existing output files instead of resuming.
Interrupted --comments runs resume by simply running the same command again. Comments are fetched in a single pass over the channel's linked discussion group (there is no per-post checkpoint file), so a restart re-fetches that group and merges the results, removing duplicates automatically. A re-run also recovers any comment media links that an earlier interrupted export saved without them.
Display names for users and bots are collected automatically. You can override them in the users_map section:
users_map:
123456: "Alice Smith"
789012: "Bob Johnson"
Titles for group and channel chats are fetched automatically. Use chats_map only if you want to override them:
chats_map:
100123456: "MyGroup"
Use --keywords to save only messages that contain at least one of the given words. This reduces output size when you need messages about specific topics.
--keywords "word1,word2,@user".--results-json) still includes a keywords block with counts and sample messages per keyword.# Save only messages containing "после" or "hello"
telegram-download-chat username --min-date 2026-01-01 --keywords "после,hello"
Extract conversations from specific threads or reply chains:
# Extract messages from a specific thread
telegram-download-chat group_username --subchat 12345 --subchat-name "Important Discussion"
# Or use a direct message URL
telegram-download-chat group_username --subchat "https://t.me/c/123456789/12345"
--stt transcribes voice messages and round video notes using Telegram's own
speech-to-text, the same one the official clients show. It requires a Telegram
Premium account — without one the export runs normally and logs a warning
instead of transcribing.
# Transcribe voice messages while downloading
telegram-download-chat username --stt
# Combine with media and HTML: the player and its transcript sit together
telegram-download-chat username --stt --media --html
Each transcription is saved to the message's transcript field in
messages.json, printed on its own [stt] ... line in messages.txt, and shown
under the message in the HTML and PDF exports. Because the field lives in the
JSON, converting an existing export (--convert) renders the transcripts too.
Results are cached in stt-cache.jsonl in the application data directory, keyed
by the audio file's Telegram document id. The same voice message is therefore
transcribed only once — re-downloading the chat, or meeting the same message
forwarded into another chat, reuses the cached text without an API call (which
also means an account that later loses Premium keeps everything already
transcribed). Point the cache somewhere else with stt_cache_path in the config,
or delete the file to force re-transcription.
For users who prefer a visual interface, the application includes an optional GUI that provides an intuitive way to download Telegram chats.
# Launch the GUI application
telegram-download-chat gui
The large Chat field at the top of the Download tab accepts the same
identifiers as the CLI's positional chat argument (@username, link or chat_id). Enter exactly one of the following, depending on what you want to
download:
| What you want to download | What to type in the Chat field | Notes |
|---|---|---|
| Your own Saved Messages | me | me always resolves to your own account, so its message history is your Saved Messages. You can also use your own @username or numeric user ID. |
| A private group you belong to | the invite link, e.g. https://t.me/+AbCdEf123456, or the group's numeric ID (negative, e.g. -1001234567890) | You must already be a member — the tool downloads through your account and cannot join on your behalf. Private groups have no public @username, so use the invite link or the numeric ID. |
| A public chat, group or channel | @username or its https://t.me/username link | Public entities can be addressed by their @username. |
Tips:
t.me/+… link you used to join the private group;
open the group in Telegram → group name → Invite Links to copy it again.--debug, or check the
chats_map / users_map entries written to your config.yml after a first
download.messages.json; in the HTML export they render in a
collapsible per-post block (collapsed shows the comment count), and in TXT/PDF
they nest under their parent post. Under --media, comment attachments are
downloaded into the chat's attachments/ folder and rendered inline in HTML
like post media.This help is also shown inside the app: click ⓘ How to fill this? under the
field to expand the full list. An ⓘ icon with a hover tooltip next to the
Chat label is also available but off by default. Toggle either via
gui_chat_hint_tooltip (default off) / gui_chat_hint_help (default on) in
config.yml.
The Settings tab has a Software Update group showing the current
version. Click Check updates to query GitHub for the latest release. If a
newer version is available the button is replaced by Download: on Windows it
fetches the telegram-download-chat.exe asset directly, and on other platforms
it opens the releases page in your browser.
The tool generates the following files for each chat:
[chat_name]/messages.json)Contains complete message data including metadata like:
user_display_name from users_mapattachment_path — relative path to the downloaded media file (when --media is used)transcript — voice message transcription (when --stt is used)[chat_name]/messages.txt)A human-readable version of the chat with:
users_map, sender name -> recipient name--media-placeholders (e.g. [photo], [video], [file=report.pdf])--reactions (e.g. Nice post [👍5 ❤️2]; custom/premium emoji show as ⭐)--stt, on their own [stt] ... line under the message[chat_name]/attachments/)When using the --media flag, media files are downloaded alongside the message files, organized by media type:
[chat_name]/
├── messages.json
├── messages.txt
└── attachments/
├── images/
│ └── 12345_123456789000.jpg
├── videos/
│ └── 12346_2937458923.mp4
├── documents/
│ └── 12347_report.pdf
├── audio/
├── stickers/
├── archives/
├── contacts/
├── locations/
├── polls/
└── other/
Files are named <message_id>_<original_filename> and sorted into category subdirectories.
[chat_name]/messages.html, [chat_name]/messages.pdf)Generated when the --html / --pdf flags are used (alongside the usual JSON/TXT output, and combinable with --media for inline images). Both render inline Telegram formatting — bold, italic, underline, strikethrough, code, spoilers, and links (only http(s), mailto, and tg schemes are kept; bare domains default to https://; others such as javascript: are stripped). The HTML view additionally:
Top 20%: 3+ (12)). Clicking hides comments below that reaction count live in the browser; nothing is removed from the export.When a downloaded reply cites a message whose date falls outside the requested --min-date/--max-date window (or a finite --limit), that referenced message is automatically fetched by id so the quoted citation is populated in JSON/TXT/HTML.
The TXT and JSON output is unchanged by these flags.
Supported media types:
2025-05-25 10:30:15 Alice -> MyGroup:
Hello everyone!
2025-05-25 10:31:22 Bob -> MyGroup (replying to Alice):
Hi Alice! How are you?
2025-05-25 10:32:45 Charlie -> MyGroup:
Welcome to the group!
API Errors
Missing Messages
Slow Downloads
request_delay in config for more reliable downloadslimit parameterProgress bar
Session file locked on Windows
session.session file cannot be deleted during logoutIf you encounter any issues, please:
app.log (by default in the application directory)--debug flag for detailed outputThe package includes an MCP (Model Context Protocol) server that allows AI assistants like Claude to retrieve messages from your Telegram chats.
pip install "telegram-download-chat[mcp]"
# stdio transport (for Claude Desktop)
python -m telegram_download_chat.mcp
# HTTP transport (for debugging/testing)
python -m telegram_download_chat.mcp -t http -p 8000
Add to your Claude Desktop config file (claude_desktop_config.json):
{
"mcpServers": {
"telegram": {
"command": "python",
"args": ["-m", "telegram_download_chat.mcp"]
}
}
}
Or using uvx:
{
"mcpServers": {
"telegram": {
"command": "uvx",
"args": ["--from", "telegram-download-chat[mcp]", "telegram-download-chat-mcp"]
}
}
}
| Tool | Description |
|---|---|
telegram_get_messages | Fetch messages from a chat with datetime filter |
Before using the MCP server, you must authenticate via CLI or GUI at least once to create a valid Telegram session.
Run the standard test suite (fast, no network):
pytest
The end-to-end export tests (tests/test_e2e_export.py, marked @pytest.mark.e2e)
validate the HTML/PDF export against a live private Telegram group that contains
all formatting, replies, and reposts. They are skipped by default and are not
part of CI, because they require:
config.yml (api_id / api_hash, not the
placeholders), andsession.session for an account that is a member of the
test group.Enable them explicitly with the TG_E2E opt-in and the e2e marker:
# Run only the e2e export tests against the default test group
TG_E2E=1 pytest -m e2e
# Override the target group (must be an account you are a member of)
TG_E2E=1 TG_E2E_GROUP="https://t.me/+XXXXXXXX" pytest -m e2e
The e2e download uses --overwrite (a clean download) so the export reflects the
live group rather than a cached/resumed partial. When TG_E2E is unset, or the
credentials/session are missing, the tests skip with a clear reason and the
default pytest run is unaffected.
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.