2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00
2025-07-19 14:13:08 +00:00
2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00
2026-07-27 15:16:01 +02:00

telegram-sticker-downloader

Download Telegram sticker packs to your disk — one folder per pack, in the file formats you ask for.

  • Downloads static (.webp), animated (.tgs), video (.webm) stickers and PNG thumbnails, filtered to whichever types you want.
  • Downloads files in parallel, with retries and Telegram rate-limit handling.
  • Resumable: files already on disk are skipped without spending API calls.
  • Writes a pack.json per pack with each sticker's emoji, size and file names.
  • Works as a scriptable CLI and as the original interactive prompt.

Requirements

  • Python 3.10 or newer
  • A Telegram bot token (free, takes a minute — see below)

Install

git clone https://git.hiddenden.cafe/Hiddenden/telegram-sticker-downloader
cd telegram-sticker-downloader

python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate

pip install -e .                   # installs the `tg-stickers` command
# or, without installing the package:
pip install -r requirements.txt

Get a bot token

  1. Open Telegram and message @BotFather.
  2. Send /newbot and follow the prompts.
  3. Copy the token it gives you.
  4. Save it next to the project:
cp example.env .env
# then edit .env:
# TELEGRAM_BOT_TOKEN=123456:ABC-DEF...

The token can also come from the TELEGRAM_BOT_TOKEN environment variable or from --token. You do not need to add the bot to any chat — reading public sticker packs is enough.

Usage

# One pack
tg-stickers https://t.me/addstickers/SomePack

# Several packs, only the static images and thumbnails
tg-stickers SomePack AnotherPack --types webp,png

# Everything listed in urls.txt, 16 files at a time
tg-stickers --from-file urls.txt --concurrency 16

# From a pipe
printf 'PackOne\nPackTwo\n' | tg-stickers --from-file -

# See what would happen without writing anything
tg-stickers --from-file urls.txt --dry-run

# No arguments: the original interactive prompts
tg-stickers

Without installing the package, the same thing works as python -m sticker_downloader ... or python app.py ....

Pack references

Anything recognisable is accepted, so you can paste straight from Telegram:

https://t.me/addstickers/SomePack     t.me/addstickers/SomePack
https://telegram.me/addstickers/Pack  tg://addstickers?set=SomePack
https://t.me/addemoji/SomePack        SomePack

In a --from-file list, blank lines and # comments are ignored, and duplicate packs are downloaded only once.

Options

Option Description
PACK ... One or more pack URLs / names
-f, --from-file PATH Read references from a file, one per line (- for stdin)
-t, --types LIST webp, tgs, webm, png, comma-separated, or all (default: all)
-o, --output DIR Where packs are written (default: downloads)
-c, --concurrency N Files downloaded in parallel per pack (default: 8)
--retries N Attempts per network call (default: 3)
--overwrite Re-download files that already exist
--emoji-names Put each sticker's emoji in its file name
--no-metadata Skip writing pack.json
--no-pack-thumbnail Skip the pack's own cover image
--dry-run Report what would be downloaded, write nothing
--token TOKEN Bot token (overrides the environment)
--env-file PATH dotenv file to read the token from (default: .env)
-v, --verbose Log every file individually
-q, --quiet Only report fatal errors
--version Print the version

File types

Type What it is Notes
webp Static stickers Regular image, opens anywhere
tgs Animated stickers Gzipped Lottie JSON, not a video file
webm Video stickers VP9 with alpha
png Thumbnails Small preview Telegram generates per sticker

A sticker has exactly one primary type — --types tgs on a pack of static stickers downloads nothing but the thumbnails you asked for.

Output

downloads/
└── SomePack/
    ├── 001.webp
    ├── 001_thumb.png
    ├── 002.webp
    ├── 002_thumb.png
    ├── _pack_thumbnail.webp
    └── pack.json

Files are numbered in pack order. With --emoji-names they become 001_🦊.webp. pack.json records what was downloaded:

{
  "pack": {
    "reference": "https://t.me/addstickers/SomePack",
    "name": "SomePack",
    "title": "Some Pack",
    "sticker_type": "regular"
  },
  "generated_at": "2026-07-27T12:00:00+00:00",
  "downloader_version": "1.0.0",
  "requested_file_types": ["webp", "png"],
  "sticker_count": 2,
  "stickers": [
    {
      "index": 1,
      "emoji": "🦊",
      "file_unique_id": "AgADBAADwqbcCw",
      "type": "regular",
      "width": 512,
      "height": 512,
      "is_animated": false,
      "is_video": false,
      "files": ["001.webp", "001_thumb.png"]
    }
  ]
}

How it works

Packs are processed one at a time so progress stays readable; the files inside a pack download concurrently, bounded by --concurrency.

  • Resume. Existing files are detected before any API call, so re-running a large batch costs almost nothing. Use --overwrite to force a refresh.
  • Atomic writes. Files land via a temporary .part file, so an interrupted run never leaves a half-written sticker that a later run would skip.
  • Retries. Timeouts, connection errors and HTTP 429/5xx are retried with exponential backoff; Telegram's own retry_after hint is respected. Genuine errors (unknown pack, bad token) fail immediately instead of being retried.
  • Partial failure is not fatal. A file that cannot be downloaded is reported and the rest of the pack continues; the run's exit code reflects it.

Exit codes

Code Meaning
0 Everything downloaded
1 One or more packs or files failed
2 Bad arguments, missing/rejected token, or aborted

Development

pip install -r requirements-dev.txt

pytest                  # test suite
ruff check .            # lint
ruff format .           # format

The tests use fakes for the Telegram bot, plus a real local HTTP server for the download layer, so the whole suite runs offline in well under a second.

.gitea/workflows/ci.yml runs lint and tests on Python 3.10–3.13. It needs Gitea Actions enabled on the repository and a registered act_runner; without a runner the file is simply ignored.

Layout:

Module Responsibility
sticker_downloader/cli.py Argument parsing, interactive prompts, wiring
sticker_downloader/downloader.py Planning and downloading a pack
sticker_downloader/urls.py Pack-reference parsing
sticker_downloader/config.py Settings and file-type handling
sticker_downloader/fetcher.py HTTP layer behind a small protocol
sticker_downloader/retry.py Retry policy and backoff
sticker_downloader/progress.py Console reporting
sticker_downloader/results.py Result and totals objects

Limitations

  • The Bot API only serves files up to 20 MB. Stickers are far smaller, so this is not normally a concern.
  • .tgs and .webm are downloaded as-is; no conversion to GIF/APNG is done.
  • Private or deleted packs cannot be read, and are reported as sticker pack not found.

License

MIT — see LICENSE.

S
Description
a python telegram sticker downloader
Readme MIT
10 MiB
v.0.1.0
Latest
2025-07-19 14:20:57 +00:00
Languages
Python 100%