tgbacky saves media from Telegram chats to local folders.
It uses your normal Telegram account. It keeps a small local SQLite DB so it can resume later instead of starting from zero.
It can save:
- photos
- image documents
- videos
- animations
- audio
- voice notes
- normal documents
Files sent as files stay files. tgbacky does not convert PNG to JPG, WebP to
PNG, video to MP4, or anything like that. It saves Telegram bytes as-is.
Not here yet: bot tokens, invite links, stickers, profile photos, contacts, and multi-chat batch export.
Most users should install a release binary. You do not need Rust or Cargo for this.
- Open GitHub Releases.
- Download the archive for your system:
Linux: tgbacky-v0.1.0-linux-x86_64.tar.gz
macOS Apple Silicon: tgbacky-v0.1.0-macos-aarch64.tar.gz
macOS Intel: tgbacky-v0.1.0-macos-x86_64.tar.gz
Windows: tgbacky-v0.1.0-windows-x86_64.zip
- Optional but recommended: verify the download if
SHA256SUMS.txtis attached to the release. You can't trust anyone online. - Extract the archive.
- Move the binary somewhere in your
PATH.
Linux:
tar -xzf tgbacky-v0.1.0-linux-x86_64.tar.gz
cd tgbacky-v0.1.0-linux-x86_64
chmod +x tgbacky
sudo mv tgbacky /usr/local/bin/tgbacky
tgbacky --versionmacOS Apple Silicon:
tar -xzf tgbacky-v0.1.0-macos-aarch64.tar.gz
cd tgbacky-v0.1.0-macos-aarch64
chmod +x tgbacky
xattr -d com.apple.quarantine ./tgbacky
sudo mv tgbacky /usr/local/bin/tgbacky
tgbacky --versionFor Intel Macs, replace macos-aarch64 with macos-x86_64. If macOS blocks
the downloaded binary, allow it from System Settings > Privacy & Security,
or run this before moving it to /usr/local/bin:
Windows PowerShell:
Expand-Archive .\tgbacky-v0.1.0-windows-x86_64.zip
cd .\tgbacky-v0.1.0-windows-x86_64\tgbacky-v0.1.0-windows-x86_64
.\tgbacky.exe --versionFor regular use on Windows, move tgbacky.exe to a folder that is already in
your Path, or add the extracted folder to your user Path.
Release archives contain the tgbacky binary, README.md, LICENSE, and
env.example.
Use this only if there is no release binary for your system, or if you want to test local changes. Install Rust 1.85 or newer first.
From this checkout:
cargo install --path .
tgbacky --versionOr build without installing:
cargo build --release
./target/release/tgbacky --versionLogin once:
tgbacky authFirst run asks for API ID and API hash once. They are app/client credentials, not Telegram user credentials. All Telegram account profiles can reuse same API credentials.
Get API ID and API hash from my.telegram.org:
- Sign in.
- Open
API development tools. - Create an app.
- Copy
api_idandapi_hash.
List chats:
tgbacky chats listPick a chat id, username, or exact title. Numeric id is safest.
Export one chat:
tgbacky export --chat -1001234567890 --out ./downloadsRun same command again later. It resumes.
Use another profile:
tgbacky auth --profile work
tgbacky chats list --profile work
tgbacky export --profile work --chat @example --out ./downloads/workShow profiles:
tgbacky profiles list
tgbacky profiles current
tgbacky profiles use workManage API credentials:
tgbacky api list
tgbacky api add --name default
tgbacky api add --name backup --api-id 123456 --api-hash abcdef
tgbacky api use backup
tgbacky api delete backup --yesUse one API profile for one command:
tgbacky auth --profile work --api-profile backupExport only some media:
tgbacky export --chat @example --out ./downloads --only photo,video
tgbacky export --chat @example --out ./downloads --skip document,audio,voiceForce rescan:
tgbacky export --chat @example --out ./downloads --rescanPlan first, download later:
tgbacky export plan --chat @example --out ./downloads --save-queue
tgbacky export --chat @example --out ./downloadsVerify files:
tgbacky verify --chat @example --out ./downloads
tgbacky verify --chat @example --out ./downloads --deep
tgbacky verify --chat -1001234567890 --out ./downloads --deep --jsonVerify defaults to a fast local check: tracked status, missing files,
unreadable paths, and file sizes. Add --deep to also read file bytes and
check SHA-256 hashes when available. Add --json for script-friendly output.
Check local setup:
tgbacky doctor
tgbacky doctor --liveSee previous runs:
tgbacky runs list --limit 20
tgbacky runs list --failed-onlyFind old .part files:
tgbacky recover stale-parts --out ./downloads
tgbacky recover stale-parts --out ./downloads --deleteReset one chat in local DB:
tgbacky chats reset --chat @example --keep-files --yesRemove --keep-files if you also want to delete tracked files.
--chat <CHAT> username, exact title, or numeric chat id
--out <DIR> where files go
--only <KINDS> save only these media kinds
--skip <KINDS> skip these media kinds
--workers <N> download workers
--rescan scan history again
--verbose-progress show more live details
--json-report print JSON report after run
Media kinds:
photo,image_doc,video,animation,audio,voice,document
Runtime flags:
--delay-ms <MS>
--flood-sleep-threshold-secs <SECS>
--jitter-ms <MS>
--retry-count <N>
--retry-backoff-ms <MS>
--download-stall-timeout-secs <SECS>
Example for gentle but not too slow export:
tgbacky export \
--chat @example \
--out ./downloads \
--workers 4 \
--delay-ms 700 \
--retry-count 5 \
--download-stall-timeout-secs 120 \
--verbose-progressTelegram can rate limit very large exports. This is normal, especially when one chat contains tens or hundreds of gigabytes of media.
For example, downloading about 120G from one conversation can trigger Telegram
RPC errors such as FLOOD_PREMIUM_WAIT_X. X is the number of seconds Telegram
asks the client to wait before continuing. tgbacky treats these like normal
flood waits, respects the delay, and continues the download afterward. This
protects the account and avoids corrupting partial files, but very large exports
can take a while.
Files go under output dir, then chat folder, then media type and date:
downloads/
my_chat/
photos/2026/04/...
videos/2026/04/...
audio/2026/04/...
files/2026/04/...
animations/2026/04/...
State DB is separate from media files.
Default profile data lives under your OS app-data folder. You can override paths:
tgbacky auth \
--profile work \
--session ./data/work.session.db \
--db ./data/work.state.db \
--download-dir ./downloads/work \
--artifacts-dir ./data/work-artifactsImportant paths:
tgbacky_API_PROFILE default API credential set name
tgbacky_SESSION_PATH Telegram login/session DB
tgbacky_DB_PATH chat state, checkpoints, media records, run history
tgbacky_DOWNLOAD_DIR default output folder
tgbacky_RUN_ARTIFACT_DIR JSON run artifacts
Most people can skip .env and use CLI flags.
Config order:
- CLI flags
- environment variables
- profile defaults
See env.example for all env vars.
Keep these private:
- Telegram session DB
- local API credential fallback file
.envwith API ID/API hash- downloaded private media
- state DB if chat names or file paths are private
tgbacky tries OS keychain first for API credentials. If keychain fails, it asks
before writing local plaintext credentials. API credentials are global, not
stored inside each Telegram account profile.
On macOS, Keychain may ask whether tgbacky can read saved API credentials.
Choose Always Allow if you trust this tgbacky binary. If you rebuild or
run an unsigned/dev binary, macOS may ask again because it sees a changed tool.
This is normal macOS behavior, not data loss.
Do not commit session files, state DBs, .env, or downloads.
More notes: SECURITY.md.
Use:
tgbacky export --chat @example --out ./downloads --verbose-progressLook at:
active=0: no download runningactive=1: one download running or stuckcooldown=yes: Telegram asked tool to waitpending=N: queued downloads waitingfailed=N: files failed after retries
If a download stalls, default timeout is 120 seconds. Change it:
tgbacky export --chat @example --out ./downloads --download-stall-timeout-secs 60cargo fmt --all
cargo clippy --all-targets --all-features -- -D warnings
cargo test
cargo build --releaseRelease notes live in CHANGELOG.md.
License: MIT.