Webhook или long polling для Telegram-бота: что выбрать
Основы3 минРедакция Innovialabs
Коротко
Long polling проще: бот сам забирает апдейты и работает без домена и SSL, что удобно для разработки и небольших ботов; webhook требует HTTPS-адреса, но лучше подходит для продакшена, масштабирования и serverless.
Коротко: в чём разница
Telegram доставляет боту события (апдейты) двумя способами, и одновременно работает только один из них.
- Long polling — бот сам спрашивает Telegram методом
getUpdates: «есть что-нибудь новое?». Запрос висит открытым, пока не появится событие или не истечёт таймаут, затем бот сразу отправляет следующий. - Webhook — вы один раз сообщаете Telegram свой HTTPS-адрес через
setWebhook, и дальше Telegram сам присылает каждый апдейт POST-запросом.
Проще говоря: при polling бот звонит сам, при webhook — ждёт звонка.
Сравнение
| Long polling | Webhook | |
|---|---|---|
| Настройка | Запустил скрипт — работает | Нужен домен, HTTPS, настройка setWebhook |
| Хостинг | Любая машина с выходом в интернет, даже за NAT | Публичный адрес, доступный из интернета |
| SSL-сертификат | Не нужен | Обязателен (подойдёт и самоподписанный, если загрузить его в Telegram) |
| Порты | Без ограничений | Только 443, 80, 88 или 8443 |
| Задержка | Практически мгновенно | Практически мгновенно |
| Постоянный процесс | Нужен, бот всё время держит соединение | Не обязателен, подходит serverless |
| Несколько копий бота | Нельзя: второй getUpdates даёт ошибку 409 | Можно за балансировщиком |
| Отладка локально | Просто | Нужен туннель или тестовый сервер |
По скорости доставки разницы на практике почти нет: при long polling ответ приходит, как только появляется событие.
Как работает надёжность
Long polling. Если бот упал, апдейты копятся на стороне Telegram и будут получены после перезапуска. Хранятся они ограниченное время, так что долгий простой означает потерю событий. Важно правильно передавать offset, иначе апдейты будут приходить повторно.
Webhook. Если ваш сервер ответил ошибкой или не ответил, Telegram повторяет отправку, но после нескольких неудачных попыток сдаётся. Состояние видно в getWebhookInfo: там есть число ожидающих апдейтов и текст последней ошибки.
Для webhook есть два правила:
- отвечайте быстро — сразу возвращайте 200, а тяжёлую работу ставьте в очередь;
- проверяйте источник — передайте
secret_tokenвsetWebhook, и Telegram будет присылать его в заголовкеX-Telegram-Bot-Api-Secret-Token. Запросы без него отклоняйте.
Как настроить webhook
curl -X POST "https://api.telegram.org/bot<TOKEN>/setWebhook" \
-d "url=https://example.com/telegram/webhook" \
-d "secret_token=long_random_string" \
-d "drop_pending_updates=true"
Проверить состояние:
curl "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"
Чтобы вернуться к polling, вызовите deleteWebhook: пока webhook установлен, getUpdates возвращает ошибку.
Когда что выбирать
Long polling подходит, если:
- вы разрабатываете и тестируете бота локально;
- бот небольшой, работает в одном экземпляре;
- сервер без публичного адреса или домена;
- нужен максимально простой запуск.
Webhook подходит, если:
- бот в продакшене и у вас уже есть домен с HTTPS;
- нужно запускать несколько копий бота под нагрузкой;
- бот работает на serverless-платформе или вместе с веб-приложением;
- не хочется держать постоянно работающий процесс.
Частый рабочий вариант: локально — polling, на сервере — webhook. Библиотеки вроде aiogram поддерживают оба режима, и переключение обычно сводится к нескольким строкам.
Частые ошибки
- Запустить две копии бота с polling — они будут «воровать» апдейты друг у друга и получать ошибку 409.
- Выполнять долгую обработку до ответа на webhook — Telegram посчитает это сбоем и пришлёт апдейт ещё раз.
- Забыть про
secret_tokenи принимать запросы от кого угодно. - После переезда сервера не обновить адрес webhook.