Telegram Backup Downloader v5
Downloads text, photos, videos, and documents from configured Telegram channels. Message text is stored in messages.txt and JSONL metadata; media is sorted into per-channel folders. SQLite tracks completed work, failed downloads, and sync progress.
Prerequisites
- Python 3.12 or Docker
- A Telegram API ID and API hash from my.telegram.org
- A Telegram account that can access every configured channel
Local Quick Start
- Create a virtual environment and install dependencies:
python -m venv .venvthen.venv\Scripts\pip install -r requirements.txton Windows, or.venv/bin/pip install -r requirements.txton Linux/macOS. - Copy
config.example.jsontoconfig.jsonand enter your Telegram values. - Run
python downloadv5.py. The first run requests Telegram login verification if no session file exists.
Backups are written to channels/; logs are written to logs/app.log. Stop gracefully with Ctrl+C.
Docker
- Create and configure
config.jsonfrom the example. - Run
docker compose up -d --build. - Follow logs with
docker compose logs -f telegram-backup.
The compose configuration persists channels, logs, data, and the Telegram session. Set status_port to 8080 to use the supplied health check and publish the status API.
Configuration
| Key | Required | Default | Description |
|---|---|---|---|
api_id |
Yes | - | Numeric Telegram API ID. |
api_hash |
Yes | - | Telegram API hash. |
phone_number |
Yes | - | Account phone number in international format. |
session_name |
Yes | - | Telethon session basename. |
channels |
Yes | - | Channel usernames or numeric peer IDs. |
parallel_downloads |
No | 3 |
Number of media workers. |
download_timeout_seconds |
No | 600 |
Per-download timeout. |
download_retry_count |
No | 3 |
Attempts made in one processing pass. |
max_lifetime_retries |
No | 20 |
Total failed passes before an item is dropped; 0 disables the cap. |
queue_max_size |
No | 5000 |
Normal download queue capacity. |
min_disk_space_gb |
No | 6 |
Pause media downloads below this free space. |
channel_auto_disable_after |
No | 5 |
Consecutive resolution failures before disabling a channel; 0 disables this. |
media_record_ttl_days |
No | 90 |
Retention for completed media DB records; 0 disables pruning. |
retry_drop_log |
No | true |
Write discarded downloads to logs/dropped_downloads.jsonl. |
resync_interval_minutes |
No | 60 |
Periodic backfill interval; 0 disables it. |
status_port |
No | 0 |
HTTP port; 0 disables the server. |
db_path |
No | telegram_state.db |
SQLite state database path. |
channel_overrides |
No | {} |
Per-channel turnon controls, for example {"-1001":{"turnon":false}}. |
manual_downloads |
No | {} |
Message IDs to prioritize, keyed by channel ID. |
config.json is watched every 10 seconds. Changes to channels, overrides, and manual downloads are applied without restarting. Do not set status_port, db_path, worker count, or API credentials expecting a live process to rebind/recreate those resources; restart after changing them.
HTTP API
The API listens on 0.0.0.0:<status_port> with no authentication. Only expose it on a trusted network.
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Returns {"status":"ok"}. |
| GET | /status |
Connection, queue, workers, disk, database, failure, and channel status. |
| GET | /logs?lines=100 |
Last 1-5000 lines of logs/app.log. |
| POST | /reload |
Reloads config.json. |
| POST | /db/cleanup |
Prunes expired records and vacuums SQLite. |
| POST | /channel/{id}/enable |
Enables a channel override and resolves channels. |
| POST | /channel/{id}/disable |
Disables a channel override. |
Troubleshooting
- Login problems: delete only the session file if you intentionally need to authenticate again, then restart.
- No downloads: verify the account belongs to or can view the channel, and confirm the channel override is enabled.
- Downloads paused: inspect
/statusor the log for disk-space warnings. Downloads resume automatically after space is recovered. - Repeated failed media: inspect
logs/app.log; items reaching the lifetime cap are recorded inlogs/dropped_downloads.jsonlwhen enabled. - Port unavailable: set
status_portto another free port, update compose port mapping if needed, and restart. - Database location in Docker: set
db_pathtodata/telegram_state.dbif you want the database in the mounteddatadirectory.