Skip to content

Build your Telegram bots
in a Django way.

Decorator routing. Edit messages and keyboards from the admin. Fully typed.

Get started Handlers

from dj_telegram_bot.core.handlers import command_handler

@command_handler("start")
def start(ctx):
    ctx.bot.send_message(ctx.chat_id, "Hello!")

Start here

New to the library? Read these three pages in order. Everything else can wait until you need it.

  1. Getting started: install, connect the webhook and answer /start.
  2. Handlers: reply to commands, messages and buttons.
  3. Examples: copy a working example for what you are building.

What's inside

  • Decorator routing


    Commands, messages, callbacks, inline queries, steps and * wildcards. Write functions or classes.

    Handlers

  • Built-in guards


    @staff_required, @superuser_required, @sponsor_required (make users join your channels first), and @before_handler for your own checks.

    Access control

  • Edit from the admin


    Messages and keyboards live in the database. Build them visually, change them without a redeploy.

    Messages & keyboards

  • Fully typed


    Every Telegram type is a Pydantic model. Autocomplete and type safety everywhere.

    Telegram client

  • Maintenance mode


    Pause the bot and show a custom message, from the admin or from code.

    Before handlers

  • Optional user model


    Let the bot create users for you, bring your own model, or use none at all.

    User model

  • Proxy and local server


    SOCKS5 proxy and local Bot API server (TDLib) support.

    Configuration

How it works

Telegram ──webhook──▶ TelegramWebhookView
                          │
                       Dispatcher        picks a handler class by update type
                          │
                    before handlers      your checks, run on every update
                          │
                   Router.find(...)      exact → step → wildcard
                          │
                     your function or method
  1. Telegram POSTs an update to /telegram/webhook/.
  2. The Dispatcher wraps it in a handler object for its update type (command, message, callback, inline query or chosen inline result).
  3. Every @before_handler runs. If one returns True, processing stops.
  4. The Router looks for a matching route and calls it.