Skip to content

Own your Telegram history. Automated, incremental backups with a local web viewer that feels just like the real app. Docker-ready and supports public chat sharing

License

Notifications You must be signed in to change notification settings

GeiserX/Telegram-Archive

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

246 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Telegram Archive Logo

Telegram Archive

Automated Telegram backup with Docker. Performs incremental backups of messages and media on a configurable schedule.

Features

📦 Backup Engine

  • Incremental backups — Only downloads new messages since last backup
  • Scheduled execution — Configurable cron schedule (default: every 6 hours)
  • Real-time listener — Catch edits, deletions, and new messages instantly between backups
  • Album support — Groups photos/videos sent together as albums
  • Service messages — Tracks group photo changes, title changes, user joins/leaves
  • Forwarded message info — Shows original sender name for forwarded messages
  • Channel signatures — Displays post author when channels have signatures enabled
  • Media deduplication — Symlinks identical files to save disk space
  • Avatars always fresh — Profile photos updated on every backup run

🎬 Media Support

  • Photos, videos, documents, stickers, GIFs
  • Voice messages and audio files with in-browser player
  • Polls with vote counts and results
  • Configurable size limits and selective download

🌐 Web Viewer

  • Telegram-like dark UI — Feels like the real app
  • Mobile-friendly — Responsive design with iOS/Android optimizations
  • Integrated lightbox — View photos and videos without leaving the page
  • Keyboard navigation — Arrow keys to browse media, Esc to close
  • Real-time updates — WebSocket sync shows new messages instantly
  • Push notifications — Get notified even when browser is closed
  • Chat search — Find messages by text content
  • JSON export — Download chat history with date range filters

🔒 Security & Privacy

  • Optional authentication — Password-protect your viewer
  • Restricted sharing — Share specific chats via DISPLAY_CHAT_IDS
  • Mass deletion protection — Rate limiting prevents accidental data loss
  • Runs as non-root — Docker best practices

🗄️ Database

  • SQLite (default) — Zero config, single file
  • PostgreSQL — For larger deployments with real-time LISTEN/NOTIFY

🗺️ Roadmap

See docs/CHANGELOG.md for complete version history.

Have a feature request? Open an issue!

📸 Screenshots

Click to view Desktop and Mobile screenshots

Desktop

Desktop View

Mobile

Mobile View

Docker Images

Two separate Docker images are available (v4.0+):

Image Purpose Size
drumsergio/telegram-archive Backup scheduler (requires Telegram credentials) ~300MB
drumsergio/telegram-archive-viewer Web viewer only (no Telegram client) ~150MB

📦 Upgrading from v3.x? See Upgrading from v3.x to v4.0 for migration instructions.

Quick Start

1. Get Telegram API Credentials

  1. Go to https://my.telegram.org/apps
  2. Log in with your phone number
  3. Create a new application (any name/platform)
  4. Note your API ID (numbers) and API Hash (letters+numbers)

2. Deploy with Docker

# Clone the repository
git clone https://github.com/GeiserX/Telegram-Archive
cd Telegram-Archive

# Create data directories
mkdir -p data/session data/backups
chmod -R 755 data/

# Configure environment
cp .env.example .env

Edit .env with your credentials:

TELEGRAM_API_ID=12345678          # Your API ID
TELEGRAM_API_HASH=abcdef123456    # Your API Hash  
TELEGRAM_PHONE=+1234567890        # Your phone (with country code)

3. Authenticate with Telegram

Option A: Using the provided scripts (recommended for fresh installs)

# Run authentication
./init_auth.sh    # Linux/Mac
# init_auth.bat   # Windows

Option B: Direct Docker command (for existing deployments or re-authentication)

If your session expires or you need to re-authenticate an existing container:

# Generic command - adjust volume paths and credentials
docker run -it --rm \
  -e TELEGRAM_API_ID=YOUR_API_ID \
  -e TELEGRAM_API_HASH=YOUR_API_HASH \
  -e TELEGRAM_PHONE=+YOUR_PHONE_NUMBER \
  -e SESSION_NAME=telegram_backup \
  -v /path/to/your/session:/data/session \
  drumsergio/telegram-archive:latest \
  python -m src auth

Example for docker compose deployment:

# If using docker compose with a session volume
docker run -it --rm \
  --env-file .env \
  -v telegram-archive_session:/data/session \
  drumsergio/telegram-archive:latest \
  python -m src auth

# Then restart the backup container
docker compose restart telegram-backup

What happens during authentication:

  1. The script connects to Telegram's servers
  2. Telegram sends a verification code to your Telegram app (check "Telegram" chat)
  3. Enter the code when prompted
  4. If you have 2FA enabled, enter your password when prompted
  5. Session is saved to the mounted volume for future use

4. Start Services

docker compose up -d

View your backup at http://localhost:8000

Common Issues

Problem Solution
Permission denied Run chmod -R 755 data/
init_auth.sh: command not found Run chmod +x init_auth.sh first
Viewer shows no data Both containers need same database path - see Database Configuration
Failed to authorize Re-run ./init_auth.sh

Web Viewer

The standalone viewer image (drumsergio/telegram-archive-viewer) lets you browse backups without running the backup scheduler.

# Example: Viewer-only deployment
services:
  telegram-viewer:
    image: drumsergio/telegram-archive-viewer:latest
    ports:
      - "8000:8000"
    environment:
      BACKUP_PATH: /data/backups
      DATABASE_DIR: /data/db
      VIEWER_USERNAME: admin
      VIEWER_PASSWORD: your-secure-password
      VIEWER_TIMEZONE: Europe/Madrid
    volumes:
      - /path/to/backups:/data/backups:ro
      - /path/to/db:/data/db:ro

Browse your backups at http://localhost:8000

Configuration

All settings are configured via environment variables. Set them in your .env file or as environment: entries in docker-compose.yml. See .env.example for a ready-to-use template.

ENABLE_LISTENER is a master switch. When set to false (the default), all LISTEN_* and MASS_OPERATION_* variables have no effect. You only need to configure those when you set ENABLE_LISTENER=true.

Environment Variables

The Scope column shows whether each variable applies to the backup scheduler (B), the web viewer (V), or both (B/V).

Variable Default Scope Description
Telegram Credentials
TELEGRAM_API_ID required B API ID from my.telegram.org
TELEGRAM_API_HASH required B API Hash from my.telegram.org
TELEGRAM_PHONE required B Phone number with country code (e.g., +1234567890)
Backup Schedule & Storage
SCHEDULE 0 */6 * * * B Cron expression for backup frequency
BACKUP_PATH /data/backups B/V Base path for backup data and media
DOWNLOAD_MEDIA true B Download media files (photos, videos, documents)
MAX_MEDIA_SIZE_MB 100 B Skip media files larger than this (MB)
BATCH_SIZE 100 B Messages processed per database batch
DATABASE_TIMEOUT 60.0 B/V Database operation timeout in seconds
SESSION_NAME telegram_backup B Telethon session file name
DEDUPLICATE_MEDIA true B Symlink identical media files across chats to save disk space
SYNC_DELETIONS_EDITS false B Batch-check ALL messages for edits/deletions each run (expensive!)
VERIFY_MEDIA false B Re-download missing or corrupted media files
STATS_CALCULATION_HOUR 3 B Hour (0-23) to recalculate backup statistics daily
PRIORITY_CHAT_IDS - B Comma-separated chat IDs to process first in all operations
LOG_LEVEL INFO B/V Logging verbosity: DEBUG, INFO, WARNING/WARN, ERROR
Chat Filtering See Chat Filtering below
CHAT_IDS - B Whitelist mode: backup ONLY these chats (ignores all other filters)
CHAT_TYPES private,groups,channels B Type-based mode: comma-separated chat types to backup
GLOBAL_EXCLUDE_CHAT_IDS - B Exclude specific chats (any type)
GLOBAL_INCLUDE_CHAT_IDS - B Force-include specific chats (any type)
PRIVATE_EXCLUDE_CHAT_IDS - B Exclude specific private chats
PRIVATE_INCLUDE_CHAT_IDS - B Force-include specific private chats
GROUPS_EXCLUDE_CHAT_IDS - B Exclude specific groups
GROUPS_INCLUDE_CHAT_IDS - B Force-include specific groups
CHANNELS_EXCLUDE_CHAT_IDS - B Exclude specific channels
CHANNELS_INCLUDE_CHAT_IDS - B Force-include specific channels
Real-time Listener See Real-time Listener below
ENABLE_LISTENER false B Master switch — enables all LISTEN_* features below
LISTEN_EDITS true B Apply text edits in real-time
LISTEN_DELETIONS true B Mirror deletions (protected by mass operation rate limiting)
LISTEN_NEW_MESSAGES true B Save new messages in real-time between scheduled backups
LISTEN_NEW_MESSAGES_MEDIA false B Also download media immediately (vs. next scheduled backup)
LISTEN_CHAT_ACTIONS true B Track chat photo, title, and member changes
MASS_OPERATION_THRESHOLD 10 B Max operations per chat before rate limiting triggers
MASS_OPERATION_WINDOW_SECONDS 30 B Sliding window for counting operations (seconds)
MASS_OPERATION_BUFFER_DELAY 2.0 B Seconds to buffer operations before applying
Database See Database Configuration below
DATABASE_URL - B/V Full database URL (highest priority, overrides all below)
DB_TYPE sqlite B/V Database engine: sqlite or postgresql
DB_PATH $BACKUP_PATH/telegram_backup.db B/V Path to SQLite database file
DATABASE_PATH - B/V Full path to SQLite file (v2 compatible alias for DB_PATH)
DATABASE_DIR - B/V Directory containing telegram_backup.db (v2 compatible)
POSTGRES_HOST localhost B/V PostgreSQL host
POSTGRES_PORT 5432 B/V PostgreSQL port
POSTGRES_USER telegram B/V PostgreSQL username
POSTGRES_PASSWORD - B/V PostgreSQL password (required when using PostgreSQL)
POSTGRES_DB telegram_backup B/V PostgreSQL database name
Viewer & Authentication
VIEWER_USERNAME - V Web viewer username (both username and password required to enable auth)
VIEWER_PASSWORD - V Web viewer password
AUTH_SESSION_DAYS 30 V Days before re-authentication is required
DISPLAY_CHAT_IDS - V Restrict viewer to specific chats (comma-separated IDs)
VIEWER_TIMEZONE Europe/Madrid V Timezone for displayed timestamps (tz database names)
SHOW_STATS true V Show backup statistics dropdown in viewer header
Security
CORS_ORIGINS * V Allowed CORS origins, comma-separated (e.g., https://my.domain.com). Credentials auto-disabled when *
SECURE_COOKIES auto V Secure flag on auth cookies. Auto-detects from request protocol (X-Forwarded-Proto / scheme). Override with true or false
Notifications
PUSH_NOTIFICATIONS basic V off = disabled, basic = in-browser only, full = Web Push (works with browser closed)
VAPID_PRIVATE_KEY auto-generated V Custom VAPID private key for Web Push
VAPID_PUBLIC_KEY auto-generated V Custom VAPID public key for Web Push
VAPID_CONTACT mailto:admin@example.com V Contact email included in Web Push requests

Chat Filtering

There are two modes for selecting which chats to backup:

Mode 1 — Whitelist (simple): set CHAT_IDS to backup only those specific chats. All other filtering variables are ignored.

CHAT_IDS=-1001234567890,-1009876543210    # Only these 2 chats, nothing else

Mode 2 — Type-based (default): use CHAT_TYPES to backup all chats of certain types, then fine-tune with include/exclude lists:

# Backup all private chats and groups (no channels)
CHAT_TYPES=private,groups

# Backup all channels except one
CHAT_TYPES=channels
CHANNELS_EXCLUDE_CHAT_IDS=-1001234567890

# Backup all groups plus one specific channel
CHAT_TYPES=groups
CHANNELS_INCLUDE_CHAT_IDS=-1001234567890

*_INCLUDE_* variables are additive — they add chats to what CHAT_TYPES already selects. For exclusive selection, use CHAT_IDS instead.

Chat ID format — Telegram uses "marked" IDs:

  • Users: positive numbers (123456789)
  • Basic groups: negative (-123456789)
  • Supergroups/Channels: negative with -100 prefix (-1001234567890)

Find a chat's ID by forwarding a message to @userinfobot.

Real-time Listener

The scheduled backup only captures new messages. To also track edits and deletions between backups, enable the real-time listener:

ENABLE_LISTENER: "true"        # Master switch — required
LISTEN_EDITS: "true"           # Track text edits (safe, default: true)
LISTEN_DELETIONS: "true"       # Mirror deletions (default: true, protected by rate limiting)
LISTEN_NEW_MESSAGES: "true"    # Save new messages instantly (default: true)

How it works: stays connected to Telegram between scheduled backups, captures changes as they happen, and automatically reconnects if disconnected.

Backup protection: when LISTEN_DELETIONS=true, deletions are protected by the mass operation rate limiter. Set LISTEN_DELETIONS=false to never delete anything from your backup.

Alternative — batch sync: set SYNC_DELETIONS_EDITS=true to check ALL backed-up messages on each scheduled run. This is expensive and slow — only use for a one-time catch-up, then switch to the real-time listener.

Mass Operation Protection

When the listener is enabled and LISTEN_DELETIONS=true, a sliding-window rate limiter protects against mass deletion attacks:

  1. Operations are buffered for MASS_OPERATION_BUFFER_DELAY seconds before being applied
  2. A sliding window tracks operations per chat over MASS_OPERATION_WINDOW_SECONDS
  3. When MASS_OPERATION_THRESHOLD is exceeded, the entire buffer is discarded — zero changes written

Example: someone deletes 50 messages in 10 seconds with default settings (threshold=10, window=30s) — the first 10 are applied, remaining 40 are blocked. For zero deletions from your backup, set LISTEN_DELETIONS=false.

Database Configuration

Telegram Archive supports SQLite (default, zero-config) and PostgreSQL (better for large deployments with real-time LISTEN/NOTIFY).

Viewer shows no data? Both backup and viewer containers must access the same database. Ensure DB_TYPE and DB_PATH (or DATABASE_URL) match in both services.

SQLite path resolution (highest priority first): DATABASE_URLDATABASE_PATHDATABASE_DIRDB_PATH$BACKUP_PATH/telegram_backup.db

Using PostgreSQL:

  1. Uncomment the postgres service in docker-compose.yml
  2. Set DB_TYPE=postgresql and POSTGRES_PASSWORD in your .env
  3. Uncomment depends_on in both backup and viewer services
  4. Run docker compose up -d

Updating to Latest Version

Using Pre-built Images (Recommended)

If you're using the default docker-compose.yml with images from Docker Hub:

# Pull latest images and recreate containers
docker compose pull
docker compose up -d

Or in one command:

docker compose up -d --pull always

Note: Running git pull only updates source code, not Docker images. You must use docker compose pull to get new container versions.

Building from Source

If you've modified the code or prefer building locally:

git pull
docker build -t drumsergio/telegram-archive:latest .
docker build -t drumsergio/telegram-archive-viewer:latest -f Dockerfile.viewer .
docker compose up -d

Pinning Versions

For production stability, pin to specific versions instead of latest:

services:
  telegram-backup:
    image: drumsergio/telegram-archive:v5.3.7  # Pin to specific version

Check Releases for available versions.

⚠️ Upgrading (Breaking Changes)

For major version upgrades with breaking changes and migration scripts, see docs/CHANGELOG.md.

CLI Commands

Local Development

Option 1: Install with pip (Recommended)

Install the package in editable mode to get the telegram-archive command:

# Install in editable mode
pip install -e .

# Now telegram-archive is available system-wide
telegram-archive --help
telegram-archive --data-dir ./data list-chats
telegram-archive --data-dir ./data stats
telegram-archive --data-dir ./data backup

# Export to JSON
telegram-archive --data-dir ./data export -o backup.json -s 2024-01-01 -e 2024-12-31

Option 2: Run directly without installation

For development without installing, use the telegram-archive executable script:

# Show all available commands
./telegram-archive --help

# Use custom data directory (instead of /data)
./telegram-archive --data-dir ./data list-chats
./telegram-archive --data-dir ./data stats
./telegram-archive --data-dir ./data backup

# Or symlink to PATH for easier access
sudo ln -s $(pwd)/telegram-archive /usr/local/bin/telegram-archive
telegram-archive --data-dir ./data list-chats

Docker Usage

All commands use the unified python -m src interface inside containers:

# Show all available commands
docker compose exec telegram-backup python -m src --help

# View statistics
docker compose exec telegram-backup python -m src stats

# List chats
docker compose exec telegram-backup python -m src list-chats

# Export to JSON
docker compose exec telegram-backup python -m src export -o backup.json

# Export date range
docker compose exec telegram-backup python -m src export -o backup.json -s 2024-01-01 -e 2024-12-31

# Manual backup run (one-time)
docker compose exec telegram-backup python -m src backup

# Re-authenticate (if session expires)
docker compose exec -it telegram-backup python -m src auth

Data Storage

data/
├── session/
│   └── telegram_backup.session
└── backups/
    ├── telegram_backup.db
    └── media/
        └── {chat_id}/
            └── {files}

Troubleshooting

Problem Solution
"Failed to authorize" Run ./init_auth.sh again
"Permission denied" chmod -R 755 data/
Media files missing/corrupted Set VERIFY_MEDIA=true to re-download them
Backup interrupted Set VERIFY_MEDIA=true once to recover missing files
"duplicate key value violates unique constraint reactions_pkey" See Reactions Sequence Fix below

Reactions Sequence Fix (PostgreSQL)

If you see this error during backup:

duplicate key value violates unique constraint "reactions_pkey"
DETAIL: Key (id)=(XXXX) already exists

Cause: The PostgreSQL sequence for reactions.id got out of sync with the actual data. This commonly occurs after database restores or migrations.

Solutions:

  1. Upgrade to v4.1.2+ (recommended) - The code automatically detects and recovers from this issue.

  2. Manual fix - Run this SQL command:

    docker exec -i <postgres-container> psql -U telegram -d telegram_backup -c \
      "SELECT setval('reactions_id_seq', COALESCE((SELECT MAX(id) FROM reactions), 0) + 1, false);"

    Or use the provided script:

    curl -O https://raw.githubusercontent.com/GeiserX/Telegram-Archive/master/scripts/fix_reactions_sequence.sql
    docker exec -i <postgres-container> psql -U telegram -d telegram_backup < fix_reactions_sequence.sql

Limitations

  • Secret chats not supported (API limitation)
  • Edit history not tracked (only latest version stored; enable ENABLE_LISTENER=true to track edits in real-time)
  • Deleted messages before first backup cannot be recovered

License

GPL-3.0. See LICENSE for details.

Built with Telethon.

About

Own your Telegram history. Automated, incremental backups with a local web viewer that feels just like the real app. Docker-ready and supports public chat sharing

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 5