How to Host a Telegram Bot: Polling vs Webhooks, and Where to Run It
Telegram bots receive messages in one of two ways: long polling (your bot asks Telegram) or webhooks (Telegram calls your URL). How each works, which hosting fits each — a VPS, serverless functions, a container platform — with setup steps, token safety and the common mistakes.
A Telegram bot is a program that receives messages from Telegram and replies. Before choosing where to host it, you need to decide how it gets messages — because that decides what kind of hosting fits.
Two ways to receive updates
Long polling
Your bot repeatedly asks Telegram, "any new messages?" (getUpdates). Each request stays open until something arrives or a timeout passes, then the bot asks again.
- ✅ Simple, works anywhere — even your laptop, with no public URL.
- ❌ The program must run all the time.
Webhooks
You give Telegram an HTTPS URL. When a message arrives, Telegram sends it to your URL. (What is a webhook?, Webhooks vs polling)
- ✅ Nothing runs while idle; scales well; fits serverless.
- ❌ Needs a public HTTPS address with a valid certificate.
You can't use both at once — setting a webhook disables getUpdates.
Which hosting fits which
| Hosting | Polling | Webhook |
|---|---|---|
| VPS / always-on server | ✅ | ✅ (with HTTPS) |
| Serverless functions (Cloudflare Workers, Vercel, Lambda) | ❌ | ✅ |
| Container platform worker | ✅ | ✅ |
| Free host that sleeps when idle | ❌ (bot goes offline) | ⚠ slow first reply |
Keep the token safe
Create your bot with @BotFather to get its token. Treat it like a password:
# .env — and add .env to .gitignore
TELEGRAM_TOKEN=123456:ABC...
If it leaks, revoke it with BotFather (/revoke) and update your app. (Environment variables explained)
Option 1: polling on a server
The simplest reliable setup. With python-telegram-bot:
import os
from telegram.ext import ApplicationBuilder, CommandHandler
async def start(update, context):
await update.message.reply_text("Hello!")
app = ApplicationBuilder().token(os.environ["TELEGRAM_TOKEN"]).build()
app.add_handler(CommandHandler("start", start))
app.run_polling()
Run it as a systemd service with Restart=always so it survives crashes and reboots — the same setup as a Discord bot or any long-running Python script.
Option 2: webhook on a server
Your bot runs a small web server, behind a reverse proxy with HTTPS:
bot.example.com {
reverse_proxy 127.0.0.1:8443
}
Then tell Telegram where to send updates, with a secret token so you can verify requests really come from Telegram:
curl "https://api.telegram.org/bot$TELEGRAM_TOKEN/setWebhook" \
-d "url=https://bot.example.com/telegram" \
-d "secret_token=$WEBHOOK_SECRET"
Telegram then sends the header X-Telegram-Bot-Api-Secret-Token with each update — check it and reject anything else. (What is Caddy?)
Option 3: webhook on serverless
A function receives the update, handles it, replies. Cheap and zero maintenance for simple bots. Limits to know: function time limits (long tasks need a queue), cold starts, and no in-memory state between requests — store state in a database. (What is serverless?)
Common mistakes
- Webhook set, then trying to poll (or the reverse) — check with
getWebhookInfo; remove a webhook withdeleteWebhook. - Two copies running with polling — you get
Conflict: terminated by other getUpdates request. Stop the old one (often still running on your laptop). - Self-signed or expired certificate on the webhook URL.
- Slow handlers — reply quickly and move long work to a background job, or Telegram retries and you process messages twice. (Background jobs)
- Bot's data in memory — gone on restart. Use a database.
Debugging
curl "https://api.telegram.org/bot$TELEGRAM_TOKEN/getWebhookInfo"
shows the current webhook, pending updates and the last error Telegram saw.
EasySpawn gives your bot an always-on server with a public HTTPS address — polling or webhook both work — plus a database for its state and automatic restarts. See how it works or join the waitlist.
Related: How to Host a Discord Bot 24/7 · Webhooks vs Polling · How to Run a Python Script 24/7 · What Is a Webhook?
Keep reading
Subdomain vs Subdirectory: blog.example.com or example.com/blog?
Should your blog, docs or app live on a subdomain (app.example.com) or a subdirectory (example.com/app)? The technical differences, what it means for SEO, cookies and hosting, and sensible defaults for a small product.
Static vs Dynamic Websites: What's the Difference?
A static site is the same files for everyone; a dynamic site builds pages per request. What each means, where single-page apps and server rendering fit, why it matters for hosting, speed, SEO, and cost — and how to tell which one your AI tool built.