Skip to main content

Python SDK for TDL (Telegram Downloader)

Project description

TDL Python SDK

python uv Ruff Pydantic v2 tests code-quality license PRs

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 tdl commands: 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_field properties

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tdl_python_sdk-0.0.0.tar.gz (128.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tdl_python_sdk-0.0.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

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

Hashes for tdl_python_sdk-0.0.0.tar.gz
Algorithm Hash digest
SHA256 e676d5b17d8e7bd61d7765a7b51592d501b54c00bbb00952c31ec2dbb2b9439d
MD5 5b1fbcd7ba025a54809f1bee6f6e7593
BLAKE2b-256 f70ab67d5fa600536aa8d082a4e419a9712f3c427701afdf751bc4a9fd048e6f

See more details on using hashes here.

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

Hashes for tdl_python_sdk-0.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3dd6ecb25d4a9eba110296585240e46cfb61294594eb5d1417eec3a1c0050081
MD5 15ce029d23256903e5664534a72ec474
BLAKE2b-256 575568a4dd63bd154c30760f7b7ebac0b4793247ce4f220c019b011338900aa2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page