Webhook vs Polling¶
Рекомендация MAX
Получение обновлений с помощью Long Polling ограничено по скорости и сроку хранения событий — этот способ не подходит для production-окружения. Рекомендуется на всех этапах работы использовать Webhook.
Polling¶
Параметры:
bot— экземпляр ботаskip_updates— пропускать старые события (по умолчаниюFalse)
Плюсы:
- Простая настройка
- Не требует публичного URL
- Подходит для разработки
Минусы:
- Постоянное подключение к API
- Не подходит для production (ограничения по скорости и хранению событий)
Остановка polling¶
stop_polling() — единственный корректный способ остановиться: он прерывает
висящий запрос get_updates, дожидается цикла, инлайн-обработчиков и фоновых
задач (use_create_task=True), а затем закрывает изоляцию событий.
Дожидается он именно выхода из цикла, а не задачи, которая вызвала
start_polling(). Если await dp.start_polling(bot) стоит внутри более крупной
корутины, та задача после остановки продолжает работу как обычно — и
stop_polling() из обработчика её не ждёт (иначе получилось бы кольцо, когда
продолжение задачи ждёт останавливающий обработчик).
task.cancel()на задачеstart_pollingзаменой не является: фоновые задачи не будут дожданы, изоляция не будет закрыта. После отмены вызовитеawait dp.shutdown(), а перед новым запуском дождитесь самой отменённой задачи.- Повторный
start_pollingна ещё живом цикле поднимаетRuntimeError— сначала остановите текущий. А если цикл уже вышел, но уборка за ним ещё идёт (отложенный дренаж после инлайн-остановки — см. ниже — илиshutdown()внешнегоstop_polling()), новый запуск не отклоняется, а дожидается её окончания: иначе прошлая уборка закрыла бы изоляцию уже нового цикла. Поэтому идиомаwhile True: await dp.start_polling(bot)переживает остановку снаружи. - Обработчик может остановить polling сам (
await dp.stop_polling()внутри хендлера). Поведение зависит от того, как обработчик выполняется:- Инлайн-обработчик (
use_create_task=False, обработчик выполняется прямо в задаче polling) — вызов только выставляет флаги, цикл завершится сразу после возврата из обработчика; дренаж фоновых задач и закрытие изоляции произойдут автоматически сразу после выхода из цикла. - Фоновый обработчик (
use_create_task=True) — самstop_polling()блокируется до выхода из цикла polling, но остальные фоновые задачи, ещё не завершившиеся к этому моменту, дожидаться не будет, а изоляция событий закрыта не будет — они доработают сами. Чтобы дождаться их явно, вызовитеawait dp.shutdown()снаружи обработчиков.
- Инлайн-обработчик (
- Регистрация хендлеров, роутеров, middleware и фильтров после старта работает:
индекс обработчиков перестраивается автоматически перед следующим событием.
После остановки диспетчер снова считается неподготовленным, поэтому
зарегистрированный в этот момент
@dp.on_started()штатно сработает при следующемstart_polling(). Предупреждение об опоздавшем@dp.on_started()печатается только в двух случаях: подготовка уже завершена или колбэк регистрируют изнутри самогоon_started. Регистрация в окне подготовки — до того, как диспетчер прочитал колбэк (например из-под долгогоcheck_me), — не опаздывает: колбэк будет вызван в этом же запуске.
Ограничения Long Polling (с 11.05.2026)
На стороне API MAX действуют следующие ограничения на использование Long Polling:
- Максимальное количество запросов — 2 RPS (запроса в секунду).
- Таймаут запроса — 30 секунд.
- Максимальный размер батча — 100 событий.
- TTL событий — 24 часа (события старше этого периода удаляются).
Для корректной работы чат-бота рекомендуется перейти на схему с Webhook.
Webhook¶
async def main():
webhook_url = "https://ваш-домен.рф/webhook" # <-- укажите свой
await bot.subscribe_webhook(url=webhook_url)
await dp.handle_webhook(bot, host="0.0.0.0", port=8080, path="/webhook")
Параметры:
bot— экземпляр ботаhost— хост сервера (по умолчанию'0.0.0.0')port— порт сервера (по умолчанию8080)path— URL-путь для маршрута вебхука (по умолчанию'/')secret— секрет для проверки заголовкаX-Max-Bot-Api-Secret**kwargs— дополнительные параметры для запуска веб-сервера
Плюсы:
- Эффективнее для больших нагрузок
- События приходят мгновенно
- Меньше нагрузка на API
Минусы:
- Требует публичный URL
- Нужна настройка сервера
Остановка вебхука¶
await dp.shutdown() дожидается фоновых задач (use_create_task=True) и
закрывает изоляцию событий. Вызывать его нужно после остановки приёма запросов —
shutdown-хуки интеграций (maxapi.webhook) делают это сами.
Вызов dp.shutdown() изнутри обработчика дренаж и закрытие изоляции
пропускает (с предупреждением в логе) — в том числе при use_create_task=False,
когда обработчик выполняется прямо в задаче HTTP-запроса. Иначе получилось бы
кольцо: остальные обработчики того же пользователя ждут блокировку изоляции,
которую держит сам вызывающий. Оставшиеся задачи доработают сами; чтобы
дождаться их, вызовите await dp.shutdown() снаружи обработчиков.
Требования безопасности (с 25.05.2026)
Для повышения безопасности прекращается поддержка получения вебхуков по HTTP,
а также самоподписных сертификатов. Используйте HTTPS и сертификаты,
выданные доверенным центром сертификации. Подробнее о требованиях
безопасности — в описании POST /subscriptions
(метод subscribe_webhook).
Важно
Если у бота есть подписки на Webhook, start_polling предупредит об этом в логах.
Удалите подписки через await bot.delete_webhook().