aiogram-webhook is a modular Python library for seamless webhook integration with multiple web frameworks in aiogram. It enables both single and multi-bot operation via webhooks, with flexible routing and security features.
- π§± Modular and extensible webhook engine
- π Flexible routing (static, tokenized, custom)
- π€ Single-bot and multi-bot support
- β‘ Adapters for FastAPI and aiohttp
- π Security: secret tokens, IP checks, custom security
- π§© Easily extendable with your own adapters, routing, and security
uv add aiogram-webhook
# or
pip install aiogram-webhookfrom contextlib import asynccontextmanager
from fastapi import FastAPI
from aiogram import Bot, Dispatcher, Router
from aiogram.filters import CommandStart
from aiogram.types import Message
from aiogram_webhook import SimpleEngine, FastApiWebAdapter
from aiogram_webhook.routing import StaticRouting
router = Router()
@router.message(CommandStart())
async def start(message: Message):
await message.answer("OK")
dispatcher = Dispatcher()
dispatcher.include_router(router)
bot = Bot("BOT_TOKEN")
engine = SimpleEngine( # or other engine
dispatcher,
bot,
web_adapter=FastApiWebAdapter(),
routing=StaticRouting(url="https://example.com/webhook"),
# security=Security(...)
)
@asynccontextmanager
async def lifespan(app: FastAPI):
engine.register(app)
await engine.set_webhook(
drop_pending_updates=True,
allowed_updates=("message", "callback_query"),
)
await engine.on_startup(app)
yield
await engine.on_shutdown(app)
app = FastAPI(lifespan=lifespan)from aiogram import Bot, Dispatcher, Router
from aiogram.filters import CommandStart
from aiogram.types import Message
from aiogram_webhook import SimpleEngine, AiohttpWebAdapter
from aiogram_webhook.routing import StaticRouting
from aiohttp import web
router = Router()
@router.message(CommandStart())
async def start(message: Message):
await message.answer("OK")
async def on_startup(bot: Bot, webhook_engine:SimpleEngine) -> None:
await webhook_engine.set_webhook()
dispatcher = Dispatcher()
dispatcher.include_router(router)
dispatcher.startup.register(on_startup)
bot = Bot("BOT_TOKEN")
engine = SimpleEngine( # or other engine
dispatcher,
bot,
web_adapter=AiohttpWebAdapter(),
routing=StaticRouting(url="https://example.com/webhook"),
# security=Security(...)
)
app = web.Application()
engine.register(app)In aiogram-webhook, there are two main engines for integrating Telegram bots via webhook:
Used for serving a single Telegram bot. Suitable for most standard scenarios when you need to integrate only one bot with your application.
- Connects aiogram
DispatcherandBotto the selected web framework (FastAPI, aiohttp, etc.) - Handles webhook requests for a single bot
- Requires explicit dispatcher, bot, web_adapter, and routing (security is optional)
Example:
from aiogram import Bot, Dispatcher
from aiogram_webhook import SimpleEngine, FastApiWebAdapter
from aiogram_webhook.routing import StaticRouting
bot = Bot("BOT_TOKEN")
dispatcher = Dispatcher()
engine = SimpleEngine(
dispatcher,
bot,
web_adapter=FastApiWebAdapter(),
routing=StaticRouting(url="https://example.com/webhook"),
# security=Security(...)
)Allows you to serve multiple Telegram bots in a single application. Useful if you need to dynamically determine which bot the request is for (e.g., by token in the URL).
- Allows serving multiple bots via a single endpoint
- Uses the bot token for request routing
- Requires dispatcher, web_adapter, routing, bot_settings (a dict with bot settings), security (optional)
Example:
from aiogram import Dispatcher, Router
from aiogram.client.default import DefaultBotProperties
from aiogram.types import Message
from aiogram.filters import Command, CommandObject
from aiogram_webhook import TokenEngine, FastApiWebAdapter
from aiogram_webhook.routing import PathRouting
router = Router()
@router.message(Command("addbot"))
async def add_bot_handler(message: Message, command: CommandObject, webhook_engine: TokenEngine):
token = command.args
if not token:
await message.answer("Use: /addbot <TOKEN>")
return
new_bot = await webhook_engine.set_webhook(token)
await message.answer(f"Bot #{new_bot.id} started!")
dispatcher = Dispatcher()
dispatcher.include_router(router)
engine = TokenEngine(
dispatcher,
web_adapter=FastApiWebAdapter(),
routing=PathRouting(url="https://example.com/webhook/{bot_token}"),
bot_settings={"default": DefaultBotProperties(parse_mode="HTML")},
# security=Security(...)
)You can create your own engine by inheriting from the base engine class (BaseEngine). This allows you to implement custom logic for webhook processing, routing, or bot management.
Adapters connect the engine to your web framework.
- Use
FastApiWebAdapter - Register engine in FastAPI lifespan (see Quick Start)
- Use
AiohttpWebAdapter - Just call
engine.register(app)
aiogram-webhook provides several routing strategies to determine webhook URLs and extract bot tokens from requests:
Base class for all routing strategies. Defines the webhook URL template and provides the interface for extracting information from requests.
Used with SimpleEngine for static webhook URLs without token extraction.
- Returns the webhook URL as-is
- No parameter extraction needed
- Example:
https://example.com/webhook
from aiogram_webhook.routing import StaticRouting
routing = StaticRouting(url="https://example.com/webhook")Base class for token-based routing strategies. Used with TokenEngine to serve multiple bots.
- Requires a URL template with a parameter placeholder (e.g.
{bot_token}) - Extracts bot token from incoming requests
- Automatically formats webhook URL using the bot token
Extracts bot token from the URL path parameter.
- Parameter is read from the path segment
- Example:
https://example.com/webhook/123:ABCβ token extracted from path - Default parameter name:
"bot_token"
from aiogram_webhook.routing import PathRouting
# Using default parameter name "bot_token"
routing = PathRouting(url="https://example.com/webhook/{bot_token}")
# Or with custom parameter name
routing = PathRouting(url="https://example.com/webhook/{token}", param="token")Extracts bot token from URL query parameters.
- Parameter is read from the query string
- Example:
https://example.com/webhook?token=123:ABCβ token extracted from query - Default parameter name:
"bot_token"
from aiogram_webhook.routing import QueryRouting
# Using default parameter name "bot_token"
routing = QueryRouting(url="https://example.com/webhook")
# Or with custom parameter name
routing = QueryRouting(url="https://example.com/webhook", param="token")
# Or with other parameters
routing = QueryRouting(url="https://example.com/webhook?other=value")You can implement your own routing by inheriting from BaseRouting or TokenRouting and implementing the webhook_point() method (and extract_token() if using token-based routing).
See routing examples for implementation details.
aiogram-webhook provides a flexible and extensible security system for processing webhook requests. You can use built-in mechanisms, combine them, or implement your own checks.
from aiogram_webhook.security import Security, StaticSecretToken, IPCheck
security = Security(
IPCheck(), # and other checks...
secret_token=StaticSecretToken("YOUR_SECRET_TOKEN")
)- SecretToken β verification of the Telegram secret token (e.g., via the
X-Telegram-Bot-Api-Secret-Tokenheader). - IPCheck β validation of the request source IP address (by default, official Telegram networks are supported, you can add your own addresses/networks).
- Combining checks β you can combine several checks (for example, SecretToken and IPCheck simultaneously).
- Custom checks β the ability to implement your own verification logic (e.g., by headers, parameters, etc.).
from aiogram_webhook.security import Security, StaticSecretToken
security = Security(secret_token=StaticSecretToken("SECRET_TOKEN"))StaticSecretToken is a simple implementation of the SecretToken protocol that checks the provided token against a static value.
You can implement your own class based on the SecretToken protocol. For example, you may want to:
- Store tokens in a database or environment variable
- Use different tokens for different bots
- Rotate tokens dynamically
IPCheck is a security check that validates the client's IP address against allowed networks and addresses. It helps ensure that only requests from trusted sources (such as official Telegram servers or your own networks) are accepted.
Constructor parameters:
*ip_entries: Any number of IP addresses or networks (as strings or ipaddress objects) to allow. You can specify both IPv4 and IPv6 addresses or networks.include_default(bool, default: True): If True, includes the official Telegram IP networks in the allowed list. If False, only your custom addresses/networks will be used.
You can combine as many addresses and networks as needed. The check supports both IPv4 and IPv6.
Features:
- Automatic detection of client IP from direct connection or
X-Forwarded-Forheader (for reverse proxy scenarios) - Works seamlessly with load balancers and reverse proxies
Example:
from aiogram_webhook.security import Security, IPCheck
# Use default Telegram IP networks
security = Security(IPCheck())
# Add custom addresses/networks
security = Security(IPCheck("192.168.1.0/24", "10.0.0.1"))
# Disable default Telegram networks and use only custom ones
security = Security(IPCheck("192.168.1.0/24", include_default=False))You can create your own security check by implementing the SecurityCheck protocol. This allows you to define custom logic for validating incoming requests based on your specific requirements.
See checks examples for more details.
aiogram-webhook β a modular library for professional Telegram bot integration via webhooks with modern Python frameworks.