Telegram bot webhook vs long polling

Long polling needs no public URL and runs on any machine, so it is the best place to start. A webhook needs an open HTTPS address and pays off for bots with heavy traffic.

Updated 5 min read

Learning objectives

After reading this article you will be able to:

  • Understand how getUpdates and setWebhook deliver updates
  • Compare the requirements, ports, latency and complexity of each mode
  • Switch from one mode to the other without errors
On this page

Every Telegram bot has to receive messages somehow. The Bot API offers two ways: the bot asks Telegram whether anything is new (long polling, the getUpdates method), or Telegram notifies the bot with an HTTPS POST (a webhook, the setWebhook method). Both deliver the same Update object; what changes is who starts the conversation.

You use one mode at a time. The choice affects where the bot can run, what must be open on the network and how it behaves under load. Telegram's own documentation says there is "nothing wrong" with using getUpdates, so neither mode is mandatory.

one mode at a timeLong pollingno public URLWebhookpublic HTTPS URLsetWebhookdeleteWebhookgetUpdatesBotgetUpdatesfailsPOSTBot
One mode at a time: with a webhook set, getUpdates fails, and only deleteWebhook brings the bot back to polling.

How does long polling work?#

The bot calls getUpdates and Telegram returns up to 100 pending updates (limit ranges from 1 to 100). With a timeout above zero, Telegram holds the connection open until something new arrives instead of answering empty right away. With timeout set to 0 (the default) it is short polling, which the docs reserve for testing.

To confirm what you already processed, the next call sends offset set to the last update_id plus 1. Libraries do this for you. Because the connection goes from your bot out to Telegram, you need no domain, certificate or open port: it works behind NAT, on a laptop or inside a container.

How does a webhook work?#

You call setWebhook with an HTTPS URL and Telegram sends a POST to it for every update. Requirements, per the official docs:

  • Port 443, 80, 88 or 8443. Other ports do not work.
  • TLS 1.2 or higher. SSLv3, TLS 1.0 and TLS 1.1 are not supported.
  • A valid certificate whose CN or SAN matches the domain, with intermediates in the chain. A self-signed certificate works if you upload the public key in the certificate parameter.
  • IPv4. IPv6 is not supported.
  • A 2XX status in the response. On any other status Telegram retries, then gives up after a reasonable number of attempts.

Useful parameters: max_connections (1 to 100, default 40) sets how many deliveries Telegram makes at once; secret_token (1 to 256 characters, only letters, digits, _ and -) comes back in the X-Telegram-Bot-Api-Secret-Token header, and you should reject requests without it. To understand the certificate side, see how Let's Encrypt works.

What is the practical difference?#

Long polling Webhook
Who starts it The bot (getUpdates) Telegram (POST)
Public HTTPS URL Not needed Required
Ports Outbound only 443, 80, 88 or 8443
Domain and certificate No Yes
Bot offline Updates wait in the queue for up to 24 h Telegram retries, then gives up after a reasonable number of attempts
Several bot instances Only one process can consume the queue Possible, with a load balancer in front
Complexity Low Medium

Telegram is cautious about performance: a webhook avoids repeated requests and polling code, but how much that changes CPU use or response time depends on your bot.

When should you choose long polling?#

  • You are starting out or developing on your own computer.
  • The bot runs somewhere without its own domain or HTTPS.
  • Volume is small or medium and one process handles it.
  • You want the fewest parts that can break.

When should you choose a webhook?#

  • You already run an HTTPS server with a domain, for example an API that also serves the bot.
  • Volume is high and you want several instances behind a load balancer.
  • Your environment should only consume resources when a message arrives.
  • You want the bot and other HTTP routes (dashboard, payments) in the same web process.

Keep Telegram's send limits in mind: about one message per second in a single chat, 20 per minute in groups and roughly 30 per second for bulk sends. A webhook does not change those numbers.

How do you switch from one mode to the other?#

Going from polling to a webhook only requires setting the webhook; the library makes the call. Going back requires removing it, or getUpdates will fail. With curl and the token in an environment variable, the first command shows the current state (an empty url means no webhook) and the second returns to polling, discarding anything pending:

bash
curl "https://api.telegram.org/bot$BOT_TOKEN/getWebhookInfo"

curl "https://api.telegram.org/bot$BOT_TOKEN/deleteWebhook?drop_pending_updates=true"

With the python-telegram-bot 22 API (pip install "python-telegram-bot[webhooks]>=22,<23"), the same handler serves both modes; only the last call changes:

python
import os

from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes


async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text("Hello!")


def main() -> None:
    app = Application.builder().token(os.environ["BOT_TOKEN"]).build()
    app.add_handler(CommandHandler("start", start))

    if os.environ.get("PUBLIC_URL"):
        app.run_webhook(
            listen="0.0.0.0",
            port=int(os.environ.get("PORT", "8080")),
            url_path="telegram",
            webhook_url=f"{os.environ['PUBLIC_URL']}/telegram",
            secret_token=os.environ["WEBHOOK_SECRET"],
        )
    else:
        app.run_polling()


if __name__ == "__main__":
    main()

Without PUBLIC_URL the bot polls; with it, it uses a webhook. If polling complains that a webhook is active, run the deleteWebhook call above. If the bot does not answer at all, see Telegram bot not responding.

How to do this on Square Cloud#

Square Cloud is self-service hosting: you deploy the bot and control everything in the dashboard. You can use python-telegram-bot, aiogram, Telethon, Telegraf or grammY, with long polling that needs no setup or with an HTTPS subdomain for webhooks.

That covers both modes in the code above. For polling, just upload the bot. For a webhook, the bot becomes a web application: set BOT_TOKEN, WEBHOOK_SECRET and PUBLIC_URL (the application's HTTPS subdomain) in its environment variables. The code already listens on 0.0.0.0 on the port in the PORT variable, which the platform sets, so there is nothing to change. In either mode the container stays on, and automatic restart (on by default for dashboard deploys) brings the bot back when the process exits with an error. To keep the bot online, see how to host a Telegram bot 24/7.

All plans are paid and billed in reais. Hobby costs R$12.49 per month, with 1 GB of RAM shared across your applications. The minimum per application is 256 MB for a background application, such as a polling bot, and 512 MB for a web application, such as a webhook bot. See the Telegram bot hosting page.

Bot hosting

Keep your bot online 24/7 with automatic restarts

Learn more

FAQs

Can I use a webhook and polling at the same time on one bot?

No. While a webhook is set, getUpdates does not work. To go back to polling, call deleteWebhook first.

Is a webhook faster than long polling?

Not necessarily. With long polling the connection is already open and the reply arrives as soon as an update exists. Telegram's docs say any gain in CPU use or response time depends on your bot's usage pattern.

How long does Telegram keep updates if my bot is offline?

Until the bot receives them, but never longer than 24 hours. After that they are discarded.

Which ports does a Telegram webhook support?

443, 80, 88 and 8443. The URL must be HTTPS with TLS 1.2 or newer. Other ports do not work.

Next articleDiscord music bot stopped playing YouTube: what changedMusic bots stopped playing YouTube because YouTube blocks automated access and extraction libraries keep breaking. See the causes and the alternatives.