Telegram доставляет обновления боту двумя способами: long polling (бот сам опрашивает сервер) и webhook (Telegram шлёт POST на ваш URL). В статье — как это устроено и как переключиться с одного на другое.
Long polling
Бот в цикле вызывает getUpdates: получил обновления — обработал — запросил следующие с offset. Плюсы: не нужен домен с SSL и белый IP, удобно на разработке и на простом VPS. Минусы: небольшая задержка, бот должен быть постоянно запущен.
В aiogram long polling включается по умолчанию при dp.start_polling(bot). Ниже — пример «ручного» цикла на requests, чтобы понять механику (в проде лучше использовать aiogram):
import requests
BOT_TOKEN = "..."
def get_updates(offset=None):
url = f"https://api.telegram.org/bot{BOT_TOKEN}/getUpdates"
r = requests.get(url, params={"timeout": 30, "offset": offset}, timeout=35)
return r.json().get("result", [])
offset = None
while True:
updates = get_updates(offset)
for u in updates:
offset = u["update_id"] + 1
if "message" in u:
chat_id = u["message"]["chat"]["id"]
requests.get(f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage",
params={"chat_id": chat_id, "text": "Получил: " + u["message"].get("text", "")})
Webhook
Вы указываете HTTPS-URL; Telegram при каждом событии (сообщение, callback) отправляет туда POST с телом Update. Плюсы: быстрая доставка, не нужно держать длинный запрос. Минусы: нужен домен с SSL и доступный порт 443 (или прокси, например nginx).
Установка webhook и приём обновлений (aiohttp + aiogram): при старте приложения вызывается on_startup — ставится webhook; при остановке — on_shutdown, webhook удаляется. Обработчики регистрируются в dp как обычно.
from aiohttp import web
from aiogram import Bot, Dispatcher
from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application
WEBHOOK_PATH = "/webhook"
WEBHOOK_URL = "https://yourdomain.com" + WEBHOOK_PATH
async def on_startup(bot: Bot):
await bot.set_webhook(WEBHOOK_URL)
async def on_shutdown(bot: Bot):
await bot.delete_webhook()
bot = Bot(token="...")
dp = Dispatcher()
# ... регистрация handlers (dp.message, dp.callback_query и т.д.) ...
app = web.Application()
webhook_requests = SimpleRequestHandler(dispatcher=dp, bot=bot)
webhook_requests.register(app, path=WEBHOOK_PATH)
setup_application(app, dp, bot=bot)
if __name__ == "__main__":
app.on_startup.append(lambda app: on_startup(bot))
app.on_shutdown.append(lambda app: on_shutdown(bot))
web.run_app(app, host="0.0.0.0", port=8080) # 443 с SSL или за nginx
В проде часто поднимают приложение на порту 8080, а nginx на 443 принимает HTTPS и проксирует запросы на http://127.0.0.1:8080/webhook. Тогда в WEBHOOK_URL указываете https://yourdomain.com/webhook. SSL для nginx — например Certbot (Let's Encrypt).
Переход с long poll на webhook
- Убедитесь, что webhook не установлен: getWebhookInfo — поле
urlдолжно быть пустым (или удалите через deleteWebhook). - Поднимите HTTPS-сервер с путём для webhook и зарегистрируйте URL: setWebhook(url="https://yourdomain.com/webhook").
- Запустите приложение. Дальше Telegram будет слать обновления только на webhook; long polling при активном webhook не используется.
Что выбрать
Для разработки и тестов удобнее long polling. Для продакшена с большой нагрузкой и минимальной задержкой — webhook с SSL за nginx.
Итоги
Long polling проще в настройке и не требует домена с SSL. Webhook даёт быструю доставку и подходит для продакшена. Выбор зависит от этапа проекта и инфраструктуры.