Guide

Telegram bots: webhooks or long polling?

A Telegram bot can fetch its messages, or have Telegram deliver them. Both work; one of them needs a lot more from your server. Here is how to choose.

← All guides2 min readUpdated

How long polling works

With long polling, your bot asks Telegram for new updates with getUpdates, and Telegram holds the request open until something arrives or a timeout passes, then answers. The bot handles what came back and asks again straight away.

It is often described as wasteful, which is a misunderstanding of the "long" part. The bot is not asking many times a second; it keeps one request open and gets an answer the moment there is anything to say. Messages arrive just as quickly as with a webhook.

Everything goes outward from your bot to Telegram, so it works anywhere a program can reach the internet: your laptop, a server with no public address, behind any firewall.

How webhooks work

With a webhook, you give Telegram a URL once, with setWebhook, and from then on Telegram sends every update to that URL as an HTTPS request. Your bot is a small web server that waits to be called.

That brings requirements. The URL must be HTTPS, with a valid certificate (or a self-signed one you upload to Telegram). It must be on one of four ports: 443, 80, 88 or 8443. And the server must be reachable from the internet at that address.

In return, the bot does nothing until there is work, which suits platforms that start a program per request and bill by the second, and it scales across several machines behind one address.

Which to choose

For a bot that runs all the time as one process — which is most bots — use long polling. It needs no domain, no certificate and no open port, it is what the libraries do by default, and it is just as responsive.

Choose webhooks when the bot runs on a serverless platform that only starts code in response to requests, or when it is large enough to spread across several machines.

You cannot use both at once. While a webhook is set, getUpdates fails with 409 Conflict; deleteWebhook switches a bot back to polling.

Polling in code

Each of the main libraries starts long polling with a single call.

grammY

const { Bot } = require('grammy');

const bot = new Bot(process.env.TELEGRAM_TOKEN);
bot.on('message:text', (ctx) => ctx.reply(ctx.message.text));

bot.start(); // long polling

python-telegram-bot

import os
from telegram.ext import ApplicationBuilder, MessageHandler, filters

async def echo(update, context):
    await update.message.reply_text(update.message.text)

app = ApplicationBuilder().token(os.environ["TELEGRAM_TOKEN"]).build()
app.add_handler(MessageHandler(filters.TEXT, echo))
app.run_polling()

aiogram

# Inside an async main(), after registering handlers on dp:
await dp.start_polling(bot)

On our hosting

Use long polling. Your server gets a public address and a port, shown in your panel, but not a domain or an HTTPS certificate, and the port it is given is rarely one of the four Telegram accepts. Polling needs none of that and works the moment the bot starts.

Because a polling bot runs continuously, it needs somewhere that stays on — which is what our free servers are for. They do not sleep, and restart the bot automatically if it crashes.

FAQ

Questions

Is polling slower than a webhook?

Not noticeably. Telegram answers a long-poll request the moment an update arrives, so the delay is a single round trip either way.

Can two copies of my bot poll at once?

No. Telegram lets one connection fetch a bot's updates at a time, and a second copy produces 409 Conflict errors in both. Run exactly one, and use a separate bot from @BotFather for testing.