Telegram Bot Hosting: Polling vs Webhook, and What Each One Needs

·5 min read·Updated
telegrambotspythonnodejshttpshow-to

Telegram bot hosting comes down to one early decision: long polling or webhooks. With polling your bot calls getUpdates in a loop — outbound connections only, no port, no domain, no certificate, and it runs anywhere that will keep a process alive. With webhooks Telegram calls you, which means you need a public HTTPS URL with a valid certificate on port 443, 80, 88, or 8443. You can't use both at once. On a container platform either works; the practical difference is how much infrastructure each one asks you to have.

The two modes side by side

Long polling (getUpdates) Webhook (setWebhook)
Direction Your bot calls Telegram Telegram calls your bot
Inbound port None Required
HTTPS + valid certificate Not needed Required
Allowed public ports n/a 443, 80, 88, 8443 only
Runs on serverless No — needs a live process Yes
Setup Run the process Deploy, then register the URL

Both constraints come straight from the Bot API: setWebhook takes an HTTPS URL, only those four ports are supported, and a self-signed certificate has to be uploaded via the certificate parameter (Telegram Bot API).

They're also mutually exclusive — while a webhook is set, getUpdates won't return anything. Switching back means calling deleteWebhook first. If your bot "stopped receiving messages" right after you tried webhooks, that's almost always why.

Polling: nothing to configure

For most bots this is the right default. Your process opens an outbound connection to Telegram and waits. Nothing connects in, so there's nothing to expose.

Zip your project and drop it into the Runny AI Agent, and it deploys as a worker with no ports at all.

The Runny AI Agent zip upload step in the JustRunMy.App panel, used to deploy a Telegram bot

The agent classifies bots as workers and maps no ports for them, which is exactly what a polling bot wants. It also asks you for the secrets it can't find rather than expecting them in your code — so your BOT_TOKEN gets set as an environment variable at deploy time instead of living in the repo. It's the same path a Discord bot takes.

The one thing polling genuinely requires is a process that stays running. That rules out serverless hosts entirely — there's no request to wake up on, so there's nothing to bill and nothing to run. A container platform is the natural fit, and this is a workload that costs very little: a polling bot is idle almost all the time.

Webhooks: what you actually need

Webhook mode is worth it when you want lower latency and no constant polling loop — a bot answering payments or interactive queries, or one you expect to get busy.

The requirement people trip on is the certificate. Telegram won't deliver to a plain HTTP endpoint, and a self-signed certificate means uploading it alongside setWebhook. What you want is a real certificate on a real hostname, and that's what an HTTPS port binding gives you: add one for whatever port your bot listens on, and the app gets a subdomain with a certificate issued and renewed automatically. Public traffic arrives on 443, which is on Telegram's allowed list.

No certificate to buy, upload, or rotate — HTTPS is one of the things included free on every app.

Read your own URL from the environment

You have to tell Telegram where to deliver, and hard-coding the URL is how staging bots end up pointing at production. Every app is given a DF_URLS environment variable containing its public HTTPS URLs, semicolon-separated, so the bot can register itself at startup:

import os
from telegram.ext import ApplicationBuilder

base_url = os.environ["DF_URLS"].split(";")[0]   # https://<your-app-host>
token = os.environ["BOT_TOKEN"]

app = ApplicationBuilder().token(token).build()
app.run_webhook(
    listen="0.0.0.0",
    port=8080,
    webhook_url=f"{base_url}/{token}",
)

Two details worth copying:

  • Listen on 0.0.0.0, not 127.0.0.1. A container bound to loopback is unreachable from outside it, and this is the most common reason a webhook bot deploys cleanly and then receives nothing.
  • Put a secret in the path, as above with the token, or use secret_token so you can verify that requests really came from Telegram. Your webhook URL is public; anyone who guesses it can post fake updates.

Which should you pick?

  • Polling if your bot is small, moderately busy, or you just want it running today. No ports, no URL, no registration step, and one less thing to break.
  • Webhook if you want updates pushed instantly and no polling loop, and you're comfortable owning a public endpoint and a registration step.

You can start with polling and move to webhooks later — it's a code change plus a port binding, not a migration. Just remember deleteWebhook when you switch back.

Keeping it running

Two things to know regardless of mode:

  • Crashes restart automatically. The platform supervises the process, so an unhandled exception doesn't leave your bot dead. The flip side: a bot that crash-loops still reports as running, so read the logs rather than trusting a green status.
  • Either approach runs uninterrupted. There is no session limit and no idle policy, so a polling bot and a webhook bot both simply keep running. A polling bot's actual resource use is tiny, so the cost of continuous operation is small.

FAQ

Do I need a domain to host a Telegram bot?

Only for webhooks. Polling bots make outbound calls to Telegram and need no domain, no port, and no certificate.

What ports does a Telegram webhook support?

443, 80, 88, and 8443 — nothing else. Public HTTPS traffic arrives on 443, so a standard HTTPS binding satisfies this.

Can I use polling and webhooks at the same time?

No. While a webhook is registered, getUpdates returns nothing. Call deleteWebhook before switching back to polling.

Do I need to buy an SSL certificate?

No. An HTTPS port binding gets a certificate issued and renewed automatically, so there's no self-signed certificate to upload with setWebhook.

Why does my webhook bot deploy fine but never receive messages?

Usually one of three things: the bot is listening on 127.0.0.1 instead of 0.0.0.0, the webhook URL was never registered, or a previous webhook is still set. Check getWebhookInfo.

Can I run a polling bot on serverless?

No. Polling needs a process that stays alive between messages; serverless platforms only run code in response to a request. Use a container, or switch to webhooks.

Wrapping up

Polling and webhooks aren't better and worse, they're a trade between "nothing to configure" and "nothing to poll." Most bots should start with polling, because the infrastructure requirement is a process that keeps running. That means keeping credit on the balance so the process stays up.