The Python/Telethon exporter is retired in favor of iyear/tdl, which
covers the same purpose and is actively maintained. README now carries
only migration instructions, including the rclone rolling-pipeline
recipe for exporting to WebDAV. Full implementation remains at d170986.
5.3 KiB
telegram-exporter — ⚠️ churned
Status: churned as of 2026-08-25. No further development, no maintenance, no issue support. This repo now contains only these instructions; the retired Python implementation lives in git history (see the last section).
Why
iyear/tdl — an actively maintained Telegram toolkit in Go, built on gotd/td — already covers this project's purpose: export chat history and download media from DMs, groups and channels over MTProto with a user account (so neither Bot API limit applies: it can read history, and there is no 20 MB download cap). Maintaining a parallel tool is not justified.
In short: a gotd-based rewrite was researched and judged feasible but not
worth it, since tdl already exists and is proven; the original project's
research and build reports are in git history at commit 3286ee2.
Use tdl instead
Install: see https://docs.iyear.me/tdl/getting-started/installation/.
tdl login # user-account login (phone + code + 2FA)
# 1) export message metadata to JSON
tdl chat export -c @mygroup --all --with-content -o export.json
# 2) download the media it references
tdl dl -f export.json -d ./exports --takeout --group --skip-same --continue
Flag notes, mapped to what this project used to do:
--takeout— takeout session with lower flood-wait limits for bulk export (an improvement this project never had).--group— detect albums (grouped_id) and download grouped messages together.--skip-same+--continue— resume: skip files matching existing name+size, continue interrupted downloads without prompting.--all --with-content— include text-only messages with their content (equivalent of--include-text).- Filters: time range / message-id range via
-i, plus expression filters, e.g.-f "Media.Size > 5*1024*1024". Extension filters via-i jpg,png/-e mp4. - tdl defaults to aggressive parallelism (
-t 8 -l 4). If you hit flood waits on a large export, lower it (-t 4 -l 1).
What tdl does not replicate from this project's contract: per-post album
folders keyed on message id, the messages.jsonl append-only sidecar, the
cursor with filter-mismatch refusal, and the dry-run disk estimate. If you need
those guarantees, the old implementation is in this repo's history and src/.
Special case: exporting to WebDAV
tdl can only write to a local directory — it has no WebDAV (or any remote) destination. When the group's media is larger than local disk, use a rolling pipeline: tdl downloads into a small staging directory while rclone concurrently moves (upload + delete local) finished files to WebDAV. Local disk then only needs to hold the files currently in flight plus one sync interval of throughput — Telegram caps a single file at 2 GB (4 GB from premium uploaders), so a few dozen GB of staging covers the worst case regardless of the group's total size.
One-time rclone remote setup:
rclone config create tg-webdav webdav \
url=https://dav.example.com/remote.php/dav/files/you \
vendor=other user=YOU pass=SECRET
Pipeline (bash):
tdl dl -f export.json -d ./staging --takeout --group --skip-same --continue &
TDL_PID=$!
while kill -0 "$TDL_PID" 2>/dev/null; do
rclone move ./staging tg-webdav:tg-export --min-age 2m --delete-empty-src-dirs
sleep 60
done
rclone move ./staging tg-webdav:tg-export --delete-empty-src-dirs # final sweep
Pipeline (PowerShell):
$tdl = Start-Process tdl -ArgumentList 'dl','-f','export.json','-d','./staging','--takeout','--group','--skip-same','--continue' -PassThru -NoNewWindow
while (-not $tdl.HasExited) {
rclone move ./staging tg-webdav:tg-export --min-age 2m --delete-empty-src-dirs
Start-Sleep -Seconds 60
}
rclone move ./staging tg-webdav:tg-export --delete-empty-src-dirs
Why it works:
--min-age 2mkeeps rclone away from files tdl is still writing; the final sweep after tdl exits catches everything else.- Both legs are independently resumable: re-run tdl (
--skip-same --continue) and re-run the rclone loop; nothing is downloaded or uploaded twice. - Caveat:
--skip-samecompares name+size against the staging dir, which is empty after files move to WebDAV. Cross-run dedupe therefore rests on--continue(tdl's own completion tracking) — keep the sameexport.jsonbetween runs. If you restart with a fresh export, narrow it to the missing message-id range (-T id -i <last>,<max>) instead of re-downloading everything.
Zero-staging streaming (no local disk at all) is not possible with tdl. It
requires custom code that pipes download chunks straight into a WebDAV PUT —
both Telethon (iter_download) and gotd (Stream(ctx, w)) support that; see
the reports in plans/reports/ if you ever need to build it.
The retired implementation
A complete, tested (214 offline tests) Python/Telethon exporter with per-post
album folders, a messages.jsonl sidecar, resumable cursor semantics and a
dry-run size estimator lives at commit 3286ee2:
git show 3286ee2:README.md # its documentation
git checkout 3286ee2 -- src tests pyproject.toml requirements.txt # resurrect it
It is unmaintained and pins Telethon <2; expect bit-rot.