# teloxide: A Telegram Bots Framework for Rust Developers

> teloxide is an MIT-licensed Rust framework for building Telegram bots, with typed commands, a dialogue state machine, and both long polling and webhooks. It is a good fit if you already write Rust and want compile-time command parsing; it is the wrong tool if you want a bot in a scripting language or a no-code builder.

**teloxide/teloxide** — 🤖 An elegant Telegram bots framework for Rust

- Repository: https://github.com/teloxide/teloxide
- Website: https://docs.rs/teloxide/latest/teloxide/
- Stars: 4,242 · Forks: 313
- Language: Rust
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/teloxide-teloxide

## What teloxide solves for Rust developers writing Telegram bots

Writing a Telegram bot in a language without a framework means hand-rolling a JSON parser, an update loop, and a command router. teloxide packages those three concerns. Its README describes it as "a full-featured framework that empowers you to easily build Telegram bots using Rust," and the parts it claims to handle are the ones that repeat across every bot: receiving updates, decoding them into typed structures, and routing them to handlers.

The intended reader is a Rust developer. The setup instructions assume cargo, rustup, and an environment variable rather than a config file. If you have never built a Rust binary, the framework's value is hard to reach, because the first thing you meet is a Cargo.toml with five dependencies and a minimum compiler version.

The design bet is that bot logic benefits from static typing. Commands are declared as an enum and parsed automatically, the README says, "just like JSON structures in serde-json and command-line arguments in structopt." That comparison is the clearest statement of intent in the repository: teloxide wants command handling to feel like deriving a serde type, not like writing a dispatch table by hand.

## How dptree and typed commands route an update

The routing layer is dptree, which the README calls "a functional chain of responsibility pattern that allows you to express pipelines of message processing in a highly declarative and extensible style." Handlers are composed rather than registered in a match statement, and the repository ships a separate DPTREE_GUIDE.md for it. That is a real architectural commitment: the dispatch model is a tree of handlers, and reading the guide is part of learning the framework.

The dialogue subsystem sits on top. A dialogue is an enum where each variant is a state, and handler functions move it between states, forming a finite state machine. The README states that the storage is agnostic, and that swapping one line changes persistence, with Redis and SQLite provided out of the box. In the example, the state type is parameterised by its storage: Dialogue<State, InMemStorage<State>>. Changing that second type argument is the swap the README refers to, which is a tidy design but also means your state type is bound to a storage choice at the type level.

Commands are parsed from an enum with a derive macro, and the macros feature must be enabled in Cargo.toml for that to work. The example command enum uses #[command(rename_rule = "lowercase")] and per-variant descriptions, and the framework generates the /help text from those descriptions. Parameters are typed: a variant can hold a String or a struct with named fields, and parse_with = "split" controls how the argument string is split.

## Installing teloxide and running a first bot

The README's setup path is five steps: install Rust, create a bot with @Botfather to get a token shaped like 123456789:blablabla, export TELOXIDE_TOKEN, update the toolchain, and add dependencies. The token goes into an environment variable, not a file:

```bash
export TELOXIDE_TOKEN=<Your token here>
```

On Windows the README gives the command-line form set TELOXIDE_TOKEN=<Your token here> and the PowerShell form $env:TELOXIDE_TOKEN=<Your token here>. The compiler requirement is explicit: teloxide currently requires rustc at least version 1.85, so run rustup update stable and rustup override set stable before building. Nightly is also supported via rustup update nightly and rustup override set nightly.

After cargo new my_bot, the README's Cargo.toml pins teloxide to 0.17.0 with the macros feature, alongside log, pretty_env_logger, and tokio with rt-multi-thread and macros. The macros feature is what enables the BotCommands derive used later.

```toml
[dependencies]
teloxide = { version = "0.17.0", features = ["macros"] }
log = "0.4"
pretty_env_logger = "0.5"
tokio = { version =  "1.39", features = ["rt-multi-thread", "macros"] }
```

The smallest working bot is the throw_dice example. It builds a Bot from the environment, then calls teloxide::repl with a closure that receives the Bot and a Message and returns a future. Sending a dice is one call, bot.send_dice(msg.chat.id). If the token is missing or malformed, Bot::from_env is where that surfaces, before any handler runs.

```rust
use teloxide::prelude::*;

#[tokio::main]
async fn main() {
    pretty_env_logger::init();
    let bot = Bot::from_env();
    teloxide::repl(bot, |bot: Bot, msg: Message| async move {
        bot.send_dice(msg.chat.id).await?;
        Ok(())
    })
    .await;
}
```

For a bot with commands, the README's command example derives BotCommands on an enum and calls Command::repl(bot, answer). The handler matches on the enum and replies with bot.send_message. The /help reply is generated from Command::descriptions(), so the descriptions in the enum are the user-facing help text. Run it and send /usernameandage alice 30 to see the two-field variant parse into username and age.

If you need unreleased work, the README shows pulling from git instead of crates.io: teloxide = { git = "https://github.com/teloxide/teloxide.git", features = ["macros"] }. There is no version pin in that form, so the revision you get changes with the branch.

## Where teloxide gets in the way

The compile-time model is the main cost. Every command is an enum variant and every reply is a typed call, so a small bot that would be twenty lines elsewhere can need a Cargo.toml, a tokio runtime, and a derive macro before it prints anything. The README acknowledges this indirectly by shipping a dice bot as the introductory example, which is about as little logic as a bot can contain.

API coverage is a boundary, not a promise. The README badge states coverage "Up to 9.2 (inclusively)." If Telegram ships a method after 9.2, the README does not claim teloxide exposes it, and the repository does not document a fallback path for missing methods. That matters for bots that depend on newer features.

The dialogue storage swap is described as changing one line, and in the example that line is a type alias. Persistence therefore lives in the type signature, which is elegant until you want to decide storage at runtime from configuration. The README presents InMemStorage, Redis, and SQLite as out-of-the-box options but does not document a dynamic selection mechanism.

Version churn is visible in the release list: v0.15.0 on 2025-04-04, v0.16.0 on 2025-06-19, and v0.17.0 on 2025-07-11. Three minor releases in roughly three months, all before 1.0, means the pre-1.0 upgrade tax is real. The repository ships a MIGRATION_GUIDE.md and a CHANGELOG.md, which is the mitigation, but the guide is something you read, not something the compiler enforces for you. The last push to the repository was on 2026-09-15.

## teloxide compared with Grammers and other Rust Telegram libraries

The related searches pair teloxide with Grammers, and the difference is architectural. Grammers targets the MTProto layer, the protocol Telegram clients use, while teloxide targets the Bot API, the HTTP interface documented at core.telegram.org/bots/api. That single distinction decides most choices. A bot that only needs to receive updates and send messages belongs on the Bot API, and teloxide is built for that. A client that needs to act as a user account, join channels as a person, or reach functionality the Bot API does not expose needs MTProto, and teloxide is not that tool.

Against a hand-written Bot API client in Rust, the trade is the same as against any framework: you give up control of the update loop and the JSON layer in exchange for typed commands and a dialogue machine. The README's claim that commands parse "just like JSON structures in serde-json" is the honest summary of what you gain.

Against non-Rust frameworks, the comparison is not about features but about who is on the team. If your bot is a side project and you are fluent in Python, teloxide's type safety will not repay the toolchain requirement. If your bot shares code with a Rust service, the opposite holds, because the same Cargo workspace and the same CI can build both.

## Maintenance, releases, and the MIT licence

The repository is not archived and the last push was on 2026-09-15. Releases are tagged in the workspace metadata with the pattern {{prefix}}v{{version}}, and the repository carries a RELEASE_PROCEDURE.md, so the release process is documented rather than improvised. The crate is published on crates.io, and the README points to docs.rs for the API reference, which means the docs you read are generated from the published crate.

The version you depend on decides your upgrade cost. Pinning teloxide = { version = "0.17.0", features = ["macros"] } keeps you on that minor line, and moving to 0.18.0 or later is a deliberate edit in Cargo.toml followed by a read of MIGRATION_GUIDE.md. Pulling from git instead means every cargo update can move you to a new commit with no version boundary at all, which is the higher-cost option and the README presents it only for functionality not yet released.

The workspace declares license = "MIT" and the repository contains a LICENSE file. MIT is permissive and imposes no copyleft obligation on your bot's source, but that is a statement about the licence text, not legal advice. If you redistribute teloxide inside a product, read the LICENSE file and the licences of its dependencies yourself.

## Conclusion

Adopt teloxide if your team already writes Rust and you want command parsing and dialogue state checked by the compiler, and you accept that the crate tracks Telegram Bot API 9.2 rather than the newest surface. Do not adopt it if you want a bot written in Python or JavaScript, or a hosted no-code builder. Before committing, verify two things: that your toolchain is at least rustc 1.85, since the workspace sets rust-version = "1.85", and whether the API methods you need are covered, because the README claims coverage up to 9.2 inclusively and does not promise anything newer.

## FAQ

### What is teloxide?

It is a Rust framework for building Telegram bots, described in its README as full-featured and based on the dptree chain of responsibility pattern. It provides typed command parsing, a dialogue state machine, and both long polling and webhooks.

### How do I install teloxide and set up my first bot?

Install Rust, create a bot with @Botfather to get a token, export TELOXIDE_TOKEN, then run cargo new my_bot and add teloxide 0.17.0 with the macros feature to Cargo.toml. The README requires rustc at least version 1.85, so update stable before building.

### Does teloxide support webhooks as well as long polling?

The README lists both long polling and webhooks among the framework's features, along with configuring an underlying HTTPS client, setting a custom URL of a Telegram API server, and graceful shutdown.

### Where can I find teloxide examples?

The README links examples in the crates/teloxide/examples/ directory, including throw_dice.rs, command.rs, and dialogue.rs. The dialogue example shows a bot that asks three questions and sends the answers back.

## Sources

- [License: MIT](https://github.com/teloxide/teloxide/blob/master/LICENSE)
- [Project website](https://docs.rs/teloxide/latest/teloxide/)
- [README](https://github.com/teloxide/teloxide/blob/master/README.md)
- [Releases](https://github.com/teloxide/teloxide/releases)
- [teloxide/teloxide on GitHub](https://github.com/teloxide/teloxide)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/teloxide-teloxide
