Telegram Backup Downloader v5

Docker Image Platforms Docker Hub GitHub

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.

Platform support: Docker images are built for linux/amd64 and linux/arm64 only. Legacy 32-bit ARM (arm/v7) is not supported because the cryptg Telethon extension has no prebuilt wheel for it. This covers servers, desktops, NAS devices, Raspberry Pi 4/5, and Apple Silicon via emulation.

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

  1. Create a virtual environment and install dependencies: python -m venv .venv then .venv\Scripts\pip install -r requirements.txt on Windows, or .venv/bin/pip install -r requirements.txt on Linux/macOS.
  2. Copy config.example.json to config.json and enter your Telegram values.
  3. 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

The example docker-compose.yml uses the pre-built image from Docker Hub and supports linux/amd64 and linux/arm64.

Before running, create the folders and config file so the container can write to them. The compose file mounts local paths for config, session, data, channels, and logs:

mkdir -p data channels logs
cp config.example.json config.json
# edit config.json with your Telegram values

On Linux, if the container runs as a non-root user, make sure the current user has read+write access to these folders (the example compose runs as root).

Then start the stack:

docker compose up -d
docker compose logs -f telegram-backup

This is the docker-compose.yml:

version: "3.9"

services:
  telegram-backup:
    image: hoelee/telegram-backup-downloader:latest
    container_name: telegram-backup
    restart: unless-stopped
    user: root
    volumes:
      - ./config.json:/app/config.json:ro
      - ./telegram_session.session:/app/telegram_session.session
      - ./data:/app/data
      - ./channels:/app/channels
      - ./logs:/app/logs
    ports:
      - "8080:8080"
    environment:
      - TZ=Asia/Kuala_Lumpur
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080/health', timeout=3)"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 15s

Set status_port to 8080 in config.json to use the health check and expose the status API.

Option B: docker run

mkdir -p data channels logs
cp config.example.json config.json

docker run -d \
  --name telegram-backup \
  --restart unless-stopped \
  -v $(pwd)/config.json:/app/config.json:ro \
  -v $(pwd)/telegram_session.session:/app/telegram_session.session \
  -v $(pwd)/data:/app/data \
  -v $(pwd)/channels:/app/channels \
  -v $(pwd)/logs:/app/logs \
  -p 8080:8080 \
  -e TZ=Asia/Kuala_Lumpur \
  hoelee/telegram-backup-downloader:latest

Follow logs with docker logs -f telegram-backup.

Option C: Build from source

cp config.example.json config.json
docker compose -f docker-compose.yml up -d --build
docker compose logs -f telegram-backup

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 controls. Use turnon: false to skip a channel without removing it from channels. Example: {"-1001":{"turnon":false}}. Change is detected by config watcher — no restart needed.
manual_downloads No {} Message IDs to prioritize, keyed by channel ID. Useful to force-retry specific messages. Example: {"-1001":[42,43,44]}. Change is detected by config watcher — no restart needed.

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 /status or 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 in logs/dropped_downloads.jsonl when enabled.
  • Port unavailable: set status_port to another free port, update compose port mapping if needed, and restart.
  • Database location in Docker: set db_path to data/telegram_state.db if you want the database in the mounted data directory.
Description
No description provided
Readme Apache-2.0 99 KiB
Languages
Python 99%
Dockerfile 1%