In this categoryIntegrations · 69
Chat Apps & Bots
Docs, Sheets & Email
IntegrationsIntermediate

How to switch a Telegram bot from polling to webhooks

Move a bot off long polling and onto a webhook URL so Telegram pushes updates to your server.

9 minIntermediate

Polling is great for local development: your bot repeatedly asks Telegram for new messages. In production, webhooks are better. Telegram pushes each update to a public HTTPS URL the instant it arrives, which is faster and cheaper. This guide migrates a bot from one to the other.

What you need

  • A working bot and token
  • A public HTTPS endpoint (a deployed server or a tunnel like ngrok)
  • A valid TLS certificate (Telegram requires HTTPS)

Step 1: Understand the trade-off

AspectPollingWebhook
SetupZero configNeeds a public HTTPS URL
LatencyUp to a few secondsNear instant
Best forLocal devProduction
ServerCan run anywhereMust be reachable from internet

Step 2: Build an HTTP endpoint

Telegram POSTs each update as JSON to your URL. Here is a minimal Express handler that reads the message and replies through sendMessage.

server.mjs
import express from "express";

const app = express();
app.use(express.json());
const token = process.env.TELEGRAM_BOT_TOKEN;

app.post("/webhook", async (req, res) => {
  const msg = req.body.message;
  if (msg?.text) {
    await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        chat_id: msg.chat.id,
        text: `You said: ${msg.text}`,
      }),
    });
  }
  res.sendStatus(200);
});

app.listen(3000, () => console.log("Listening on :3000"));
Always return 200 fast
Telegram retries any update your endpoint does not acknowledge with a 2xx status. Respond quickly and do slow work in the background, or you will get duplicate updates.

Step 3: Register the webhook

Tell Telegram where to send updates with setWebhook. Adding a secret token header lets you verify that incoming requests really come from Telegram.

zsh - setWebhook
$curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/setWebhook" \
$ -d url="https://api.example.com/webhook" \
$ -d secret_token="my-shared-secret"
{"ok":true,"result":true,"description":"Webhook was set"}
$
Verify the request header
POST /webhook
X-Telegram-Bot-Api-Secret-Token: my-shared-secret
Content-Type: application/json
----------------------------------
if (header !== "my-shared-secret") return 403
Reject any POST that lacks the matching secret header.

Step 4: Confirm and roll back if needed

Check the active webhook with getWebhookInfo. To go back to polling later, call deleteWebhook first, otherwise the two methods conflict.

curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/getWebhookInfo"
# to revert:
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/deleteWebhook"

Result

Telegram now delivers updates straight to your server with almost no delay, and the secret header keeps the endpoint safe from spoofed requests.

Watch related tutorials

Free weekly email

New guides in your inbox

Fresh step-by-step how-to guides as we publish them. One email a week, no more.

Tags
#telegram#webhook#polling#bot#deployment