Вебхук для Telegram-бота: настройка setWebhook, проверка и удаление
Вебхук Телеграм-бота — это HTTPS-адрес вашего сервера, на который Telegram сам отправляет POST-запрос с каждым новым апдейтом. Включается он одним вызовом setWebhook, проверяется через getWebhookInfo, а удаляется методом deleteWebhook. Ниже — требования к серверу, готовые команды curl, обработчики с проверкой secret_token на Python и Node.js и разбор типичных ошибок, включая n8n на localhost.
Вебхук или getUpdates: что выбрать
getUpdates (long polling) | Вебхук | |
|---|---|---|
| Кто инициирует | Бот сам опрашивает Telegram | Telegram присылает апдейты на ваш сервер |
| Что нужно | Любая машина с интернетом, даже за NAT | Публичный HTTPS-адрес и сертификат |
| Когда удобен | Разработка, небольшие боты, нет домена | Продакшен, serverless, нагрузка с пиками |
Способы взаимоисключающие: пока вебхук установлен, getUpdates не работает. В обоих случаях Telegram хранит недоставленные апдейты не дольше 24 часов.
Требования к серверу для вебхука
- Только HTTPS с TLS 1.2 или новее — на любом порту. Обычный HTTP облачный Bot API не принимает, такое разрешено только на локальном Bot API сервере.
- Порты 443, 80, 88 или 8443. Другие не работают. Если порт не 443, укажите его в URL:
https://bot.example.com:8443/telegram/webhook. - Сертификат, у которого CN или SAN совпадает с доменом, с полной цепочкой промежуточных сертификатов. Бесплатный Let's Encrypt подходит. Самоподписанный тоже можно, но его нужно загрузить в
setWebhook. - IPv4. IPv6 для вебхуков пока не поддерживается.
- Без редиректов: ответ 301 или 302 Telegram не выполнит.
- Если фильтруете трафик по IP, пропускайте подсети
149.154.160.0/20и91.108.4.0/22— и сверяйтесь с официальным гайдом по вебхукам, диапазоны могут меняться.
Как установить вебхук через setWebhook
| Параметр | Зачем нужен |
|---|---|
url | HTTPS-адрес обработчика. Пустая строка удаляет вебхук |
secret_token | 1–256 символов A-Z, a-z, 0-9, _, -; приходит в заголовке X-Telegram-Bot-Api-Secret-Token |
allowed_updates | Какие типы апдейтов присылать, например ["message", "callback_query"] |
drop_pending_updates | true — выбросить накопившиеся апдейты |
max_connections | Одновременных соединений к серверу: 1–100, по умолчанию 40 |
certificate | Публичный ключ самоподписанного сертификата (только файлом, multipart) |
ip_address | Фиксированный IP вместо адреса из DNS |
export BOT_TOKEN="123456789:AAEexampleTokenReplaceWithYours"
export WEBHOOK_SECRET="$(openssl rand -hex 32)" # сохраните — он нужен обработчику
curl -s "https://api.telegram.org/bot$BOT_TOKEN/setWebhook" \
--data-urlencode "url=https://bot.example.com/telegram/webhook" \
-d "secret_token=$WEBHOOK_SECRET" \
--data-urlencode 'allowed_updates=["message","callback_query"]' \
-d drop_pending_updates=true \
-d max_connections=40
{"ok": true, "result": true, "description": "Webhook was set"}
Учтите: если allowed_updates не передать, сохранится прежний список. Пустой список означает все типы, кроме chat_member, message_reaction и message_reaction_count. Попробовать без терминала можно в Bot API Tester на методе setWebhook.
С самоподписанным сертификатом в CN можно указать IP-адрес сервера, а публичный ключ передать файлом:
openssl req -newkey rsa:2048 -sha256 -nodes -keyout private.key -x509 -days 365 \
-out public.pem -subj "/CN=203.0.113.10"
curl -s "https://api.telegram.org/bot$BOT_TOKEN/setWebhook" \
-F "url=https://203.0.113.10:8443/telegram/webhook" \
-F "certificate=@public.pem" \
-F "secret_token=$WEBHOOK_SECRET"
Проверка вебхука: getWebhookInfo
curl -s "https://api.telegram.org/bot$BOT_TOKEN/getWebhookInfo"
{
"ok": true,
"result": {
"url": "https://bot.example.com/telegram/webhook",
"has_custom_certificate": false,
"pending_update_count": 12,
"last_error_date": 1793275800,
"last_error_message": "Wrong response from the webhook: 502 Bad Gateway",
"max_connections": 40,
"allowed_updates": ["message", "callback_query"]
}
}
urlпустой — вебхук не установлен, бот работает черезgetUpdates;pending_update_countрастёт — Telegram не может доставить апдейты, они копятся в очереди;last_error_messageиlast_error_date— последняя ошибка доставки: код ответа вашего сервера, отказ в соединении, таймаут или проблема с SSL;has_custom_certificate—true, если загружен свой сертификат.
Обработчик вебхука с проверкой secret_token
Адрес вебхука публичный, поэтому любой может отправить на него поддельный апдейт. Заголовок X-Telegram-Bot-Api-Secret-Token отсекает такие запросы: сравнивайте его с секретом за постоянное время и отвечайте 403 на чужие запросы.
Python, FastAPI (pip install fastapi uvicorn):
import hmac
import os
from fastapi import FastAPI, Header, HTTPException, Request
WEBHOOK_SECRET = os.environ["WEBHOOK_SECRET"]
app = FastAPI()
@app.post("/telegram/webhook")
async def telegram_webhook(
request: Request,
x_telegram_bot_api_secret_token: str | None = Header(default=None),
):
received = (x_telegram_bot_api_secret_token or "").encode()
if not hmac.compare_digest(received, WEBHOOK_SECRET.encode()):
raise HTTPException(status_code=403)
update = await request.json()
# положите апдейт в очередь и сразу верните 200
print("update", update["update_id"])
return {"ok": True}
Node.js, Express (npm i express):
import crypto from 'node:crypto';
import express from 'express';
const expected = Buffer.from(process.env.WEBHOOK_SECRET);
const app = express();
app.use(express.json());
app.post('/telegram/webhook', (req, res) => {
const received = Buffer.from(req.get('X-Telegram-Bot-Api-Secret-Token') ?? '');
if (received.length !== expected.length || !crypto.timingSafeEqual(received, expected)) {
return res.sendStatus(403);
}
res.sendStatus(200); // сначала ответ Telegram
handleUpdate(req.body).catch(console.error); // потом обработка
});
async function handleUpdate(update) {
console.log('update', update.update_id);
}
app.listen(8000); // TLS терминирует nginx или Caddy перед приложением
Отвечайте 2xx быстро
- Любой ответ, кроме 2xx, Telegram считает неудачей и повторяет запрос, а апдейты тем временем копятся в
pending_update_count. - Отвечайте 200 сразу, а запросы к базе, внешним API и нейросетям выполняйте в фоне или через очередь.
- Неинтересные боту апдейты тоже подтверждайте ответом 200, иначе они будут приходить снова.
- Храните обработанные
update_id: повторная доставка возможна, и дубли лучше отсекать.
Бонус: в ответе на вебхук можно сразу вызвать метод Bot API. Верните JSON с полем method и параметрами — Telegram выполнит запрос, но узнать его результат вы не сможете:
{"method": "sendMessage", "chat_id": 123456789, "text": "Принято!"}
Как удалить вебхук телеграм-бота
Чтобы вернуться к getUpdates, вызовите deleteWebhook. Параметр drop_pending_updates=true заодно выбросит накопившиеся апдейты — удобно, если бот долго лежал и не должен отвечать на старые сообщения:
curl -s "https://api.telegram.org/bot$BOT_TOKEN/deleteWebhook?drop_pending_updates=true"
Без этого параметра очередь сохранится, и getUpdates отдаст её целиком. Тот же эффект, что и у deleteWebhook, даёт setWebhook с пустым url.
Частые ошибки вебхука
Bad Request: bad webhook: An HTTPS URL must be provided for webhook — в url передан адрес с http:// или без схемы. Нужен именно https:// и публичный домен или IP.
409 Conflict при вызове getUpdates — вебхук установлен, и long polling заблокирован. Если вебхук поставил другой сервис (например, n8n), а вам нужен polling, вызовите deleteWebhook. Если же нужен вебхук, остановите скрипт, который вызывает getUpdates.
n8n на localhost. Telegram-триггер в n8n регистрирует вебхук через setWebhook, а адрес вида http://localhost:5678 не подходит дважды: это не HTTPS, и Telegram не может достучаться до вашего компьютера. Нужен публичный HTTPS-адрес: n8n на сервере с доменом за nginx или Caddy с сертификатом либо туннель вроде cloudflared или ngrok. Публичный адрес нужно передать самой n8n (обычно через переменную окружения WEBHOOK_URL), чтобы она регистрировала у Telegram именно его.
Вебхук установлен, но апдейты не приходят. Смотрите last_error_message в getWebhookInfo. Типичные причины: неподдерживаемый порт, неполная цепочка сертификатов, редирект, обработчик падает с 5xx или файрвол не пускает подсети Telegram. Проверить TLS с внешней машины поможет curl -v https://bot.example.com/telegram/webhook.
Вебхук принимает апдейты, а отправка ответов работает как обычно — через sendMessage, подробности в гайде как отправить сообщение через бота. Если бот только создаётся, начните с инструкции по созданию бота, а при проблемах с токеном загляните в гайд токен бота Telegram. Про ограничения на число соединений и хранение апдейтов — в обзоре лимиты Telegram Bot API.
Частые вопросы
Как удалить вебхук Телеграм-бота?
Вызовите https://api.telegram.org/bot<token>/deleteWebhook. С параметром drop_pending_updates=true заодно удалятся накопившиеся апдейты. После этого снова работает getUpdates.
Можно ли использовать вебхук и getUpdates одновременно?
Нет, это взаимоисключающие способы. Пока вебхук установлен, getUpdates возвращает 409 Conflict.
Какие порты поддерживает вебхук Telegram?
Только 443, 80, 88 и 8443, причём HTTPS обязателен на любом из них. Порт, отличный от 443, указывается прямо в URL: https://example.com:8443/webhook.
Нужен ли платный SSL-сертификат для вебхука?
Нет. Подойдёт бесплатный сертификат, например Let's Encrypt, или самоподписанный — его нужно загрузить в параметре certificate при вызове setWebhook.
Как проверить, что запрос на вебхук пришёл от Telegram?
Передайте secret_token в setWebhook: Telegram будет присылать его в заголовке X-Telegram-Bot-Api-Secret-Token каждого запроса. Сравнивайте заголовок с ожидаемым значением и отклоняйте запросы без него.
Почему Telegram присылает один и тот же апдейт повторно?
Ваш сервер ответил не 2xx или не ответил вовремя, и Telegram повторил доставку. Отвечайте 200 сразу, тяжёлую обработку выносите в фон, а дубли отсекайте по update_id.
Читайте также
Как создать бота в Телеграм: от @BotFather до первого сообщения
Как создать бота в Телеграм: регистрация в @BotFather, токен, проверка через getMe, первое сообщение на curl и Python, команды и описание бота.
Что нового в Telegram Bot API 10.0–10.3: rich-сообщения, эфемерные сообщения и гостевой режим
Что нового в Telegram Bot API 10.0–10.3: rich-сообщения, эфемерные сообщения, гостевой режим, заявки на вступление — с примерами и чек-листом миграции.
Лимиты Telegram Bot API: сообщения в секунду, ошибка 429 и размеры файлов
Все лимиты Telegram Bot API в одном месте: сообщения в секунду, ошибка 429 и retry_after, платные рассылки, размеры файлов, длина текста и подписи.
Как отправить сообщение через бота Telegram: sendMessage, разметка и кнопки
Как отправить сообщение через бота Telegram: sendMessage на curl, Python и JavaScript, parse_mode HTML и MarkdownV2, кнопки и ошибки 400, 403, 429.
Токен бота Telegram: как получить, где найти, как проверить и отозвать
Как получить токен бота Телеграм в @BotFather, где взять токен уже созданного бота, как проверить его через getMe и что делать, если токен утёк.
Как узнать chat id в Telegram: пользователь, группа, канал и тема форума
Как узнать chat id в Telegram через getUpdates: личный чат, группа, супергруппа, канал и тема форума. Форматы id с -100 и что делать с пустым result.
Тестирование Telegram Mini App: от браузера до отладки на телефоне
Тестирование Telegram Mini App по шагам: mock-режим в браузере, HTTPS-туннель для localhost, тестовая среда, DevTools на телефоне и проверка initData.