Python SDK for TDL (Telegram Downloader)
Project description
A type-safe Python SDK for TDL (Telegram Downloader). Wraps the tdl CLI binary via subprocess and provides a Pythonic, Pydantic-powered interface for all TDL operations.
Other Languages: English | 繁體中文 | 简体中文
Features
- Full coverage of all
tdlcommands: login, chat, download, upload, forward, backup, recover, migrate, extension - Strict typing with Pydantic BaseModel for all options and results
- Enum types for mode/type parameters (LoginType, ExportType, ForwardMode, ListOutput)
- Custom exception hierarchy with stdout/stderr/return_code attached
- CLI flag serialization via
@computed_fieldproperties
Prerequisites
Install the TDL CLI tool first:
# macOS / Linux
curl -sSL https://docs.iyear.me/tdl/install.sh | bash
# or via Go
go install github.com/iyear/tdl@latest
Verify installation:
tdl version
Installation
pip install tdl-python-sdk
# or with uv
uv add tdl-python-sdk
Quick Start
from tdl_sdk import TDL, GlobalOptions, LoginOptions, LoginType
# Create client with global options
client = TDL(global_options=GlobalOptions(ns="my_session", proxy="socks5://127.0.0.1:1080"))
# Login via QR code
client.login(LoginOptions(login_type=LoginType.QR))
Usage Guide
Login
TDL supports three login methods: desktop client, verification code, and QR code.
from tdl_sdk import TDL, LoginOptions, LoginType
client = TDL()
# Login via QR code (recommended)
client.login(LoginOptions(login_type=LoginType.QR))
# Login via desktop client (auto-detect path)
client.login(LoginOptions(login_type=LoginType.DESKTOP))
# Login via desktop client with custom path and passcode
client.login(
LoginOptions(
login_type=LoginType.DESKTOP, desktop="/path/to/Telegram Desktop", passcode="your_passcode"
)
)
# Login via verification code
client.login(LoginOptions(login_type=LoginType.CODE))
Chat Operations
List Chats
from tdl_sdk import TDL, ChatListOptions, ListOutput
client = TDL()
# List all chats as table
client.chat_ls()
# List chats as JSON with filter
result = client.chat_ls(ChatListOptions(output=ListOutput.JSON, chat_filter="Type == 'channel'"))
print(result.stdout)
Export Messages
from tdl_sdk import TDL, ChatExportOptions, ExportType
client = TDL()
# Export last 100 messages from a channel
client.chat_export(
ChatExportOptions(
chat="my_channel",
export_type=ExportType.LAST,
export_input=[100],
output="export.json",
with_content=True,
)
)
# Export all messages (including non-media)
client.chat_export(
ChatExportOptions(
chat="my_channel", export_all=True, with_content=True, output="full_export.json"
)
)
Export Users
from tdl_sdk import TDL, ChatUsersOptions
client = TDL()
# Export all users from a channel
client.chat_users(ChatUsersOptions(chat="my_channel", output="users.json"))
Download
from tdl_sdk import TDL, DownloadOptions
client = TDL()
# Download by Telegram message links
client.download(
DownloadOptions(
url=["https://t.me/channel/123", "https://t.me/channel/456"], download_dir="./downloads"
)
)
# Download from exported JSON with filters
client.download(
DownloadOptions(
file=["export.json"],
download_dir="./media",
include=["mp4", "mkv"], # only video files
skip_same=True, # skip duplicates
takeout=True, # use takeout for lower flood limits
template="{{ .DialogID }}_{{ .MessageID }}_{{ filenamify .FileName }}",
)
)
# Serve media as HTTP server
client.download(DownloadOptions(file=["export.json"], serve=True, port=9090))
Upload
from tdl_sdk import TDL, UploadOptions
client = TDL()
# Upload files to Saved Messages
client.upload(UploadOptions(path=["/data/video.mp4", "/data/photos/"]))
# Upload to a specific chat as photos
client.upload(UploadOptions(path=["./images/"], chat="my_channel", photo=True))
# Upload and remove local files after success
client.upload(UploadOptions(path=["./temp_files/"], chat="my_channel", rm=True))
Forward
from tdl_sdk import TDL, ForwardOptions, ForwardMode
client = TDL()
# Forward messages (direct mode)
client.forward(
ForwardOptions(forward_from=["https://t.me/source_channel/123"], to="target_channel")
)
# Clone messages (no forward header)
client.forward(
ForwardOptions(
forward_from=["https://t.me/source/123", "export.json"],
to="target_channel",
mode=ForwardMode.CLONE,
silent=True,
)
)
# Dry run to preview
result = client.forward(
ForwardOptions(forward_from=["export.json"], to="target_channel", dry_run=True)
)
print(result.stdout)
Backup / Recover / Migrate
from tdl_sdk import TDL, BackupOptions, RecoverOptions, MigrateOptions
client = TDL()
# Backup session data
client.backup(BackupOptions(dst="./my_backup.tdl"))
# Recover from backup
client.recover(RecoverOptions(file="./my_backup.tdl"))
# Migrate to file-based storage
client.migrate(MigrateOptions(to={"type": "file", "path": "/new/storage"}))
Extension Management
from tdl_sdk import TDL, ExtInstallOptions
client = TDL()
# Install an extension
client.ext_install("github.com/user/tdl-ext-name")
# Force reinstall
client.ext_install("github.com/user/tdl-ext-name", ExtInstallOptions(force=True))
# List installed extensions
result = client.ext_list()
print(result.stdout)
# Upgrade / Remove
client.ext_upgrade("ext-name")
client.ext_remove("ext-name")
Error Handling
from tdl_sdk import TDL, DownloadOptions
from tdl_sdk import TDLError, TDLNotFoundError, TDLCommandError, TDLTimeoutError
client = TDL(timeout=300)
try:
client.download(DownloadOptions(url=["https://t.me/channel/123"]))
except TDLNotFoundError:
print("tdl binary not found. Please install tdl first.")
except TDLTimeoutError as e:
print(f"Command timed out: {e}")
except TDLCommandError as e:
print(f"Command failed (exit code {e.return_code}): {e.stderr}")
except TDLError as e:
print(f"Unexpected error: {e}")
Global Options
Configure shared settings for all commands:
from tdl_sdk import TDL, GlobalOptions
client = TDL(
global_options=GlobalOptions(
ns="work_session", # session namespace
proxy="socks5://127.0.0.1:1080",
threads=8, # max threads per transfer
limit=4, # max concurrent tasks
pool=16, # DC pool size
debug=True, # enable debug output
reconnect_timeout="10m",
storage={"type": "bolt", "path": "/custom/data"},
),
tdl_path="/usr/local/bin/tdl", # custom binary path
timeout=600, # default timeout (seconds)
)
Architecture
src/tdl_sdk/
__init__.py # Public API exports
_exceptions.py # TDLError hierarchy
_enums.py # LoginType, ExportType, ForwardMode, ListOutput
_models.py # Pydantic models (GlobalOptions, *Options, TDLResult)
_runner.py # TDLRunner - subprocess execution layer
_client.py # TDL - user-facing facade
All classes are Pydantic BaseModel. Option models provide cli_dict and cli_args as @computed_field properties for automatic CLI flag serialization.
Development
git clone https://github.com/Mai0313/tdl-python-sdk.git
cd tdl-python-sdk
uv sync
make test
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tdl_python_sdk-0.0.0.tar.gz.
File metadata
- Download URL: tdl_python_sdk-0.0.0.tar.gz
- Upload date:
- Size: 128.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e676d5b17d8e7bd61d7765a7b51592d501b54c00bbb00952c31ec2dbb2b9439d
|
|
| MD5 |
5b1fbcd7ba025a54809f1bee6f6e7593
|
|
| BLAKE2b-256 |
f70ab67d5fa600536aa8d082a4e419a9712f3c427701afdf751bc4a9fd048e6f
|
File details
Details for the file tdl_python_sdk-0.0.0-py3-none-any.whl.
File metadata
- Download URL: tdl_python_sdk-0.0.0-py3-none-any.whl
- Upload date:
- Size: 12.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3dd6ecb25d4a9eba110296585240e46cfb61294594eb5d1417eec3a1c0050081
|
|
| MD5 |
15ce029d23256903e5664534a72ec474
|
|
| BLAKE2b-256 |
575568a4dd63bd154c30760f7b7ebac0b4793247ce4f220c019b011338900aa2
|