Skip to content

How to Host a Telegram Bot for Free with Webhooks (2026)

Host a Telegram bot for free with webhooks: why they beat polling, a complete bot in Node.js and Python, a secret-token check and a one-command deploy.

Published
Reading time
4 min
On this page

Key takeaways

  • Use webhooks, not polling: Telegram sends each update to your HTTPS URL, so your bot only works when there's a message.
  • Because updates arrive as web requests, a webhook bot can run on DockHosting's Free plan: a sleeping app wakes on the next update.
  • Protect the endpoint with secret_token: Telegram sends it in the X-Telegram-Bot-Api-Secret-Token header.

Telegram bots are among the easiest bots to host, if you use webhooks. Instead of your bot constantly asking Telegram "anything new?", Telegram pushes each message to an HTTPS URL you control. That means no always-running loop, and it means the bot can run on a free plan.

Webhooks vs polling

Long polling (getUpdates)Webhook (setWebhook)
How it worksYour bot asks Telegram for updates in a loopTelegram POSTs updates to your URL
Needs a public HTTPS URLNoYes
Needs to run 24/7YesNo (it can wake on request)
Good forLocal developmentProduction

Every app on DockHosting gets an HTTPS URL like https://mybot.dockhosting.cloud, so the HTTPS requirement is already covered.

1. Create the bot

Message @BotFather on Telegram, send /newbot and follow the prompts. You'll get a token like 123456:ABC-DEF….

2a. Node.js webhook bot

No bot library is needed: the Bot API is plain HTTPS and JSON.

js
// index.js
import express from "express";
 
const { BOT_TOKEN, WEBHOOK_SECRET, PORT = 3000 } = process.env;
const api = (method, body) =>
  fetch(`https://api.telegram.org/bot${BOT_TOKEN}/${method}`, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(body),
  });
 
const app = express();
app.use(express.json());
 
app.post("/telegram", async (req, res) => {
  // Reject anything that isn't from Telegram.
  if (req.get("X-Telegram-Bot-Api-Secret-Token") !== WEBHOOK_SECRET) return res.sendStatus(401);
  const msg = req.body.message;
  if (msg?.text) await api("sendMessage", { chat_id: msg.chat.id, text: `You said: ${msg.text}` });
  res.sendStatus(200);
});
 
app.get("/", (_, res) => res.send("ok"));
app.listen(PORT);
json
{ "type": "module", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^5" } }

2b. Python webhook bot (FastAPI)

python
# main.py
import os
import httpx
from fastapi import FastAPI, Header, HTTPException, Request
 
TOKEN = os.environ["BOT_TOKEN"]
SECRET = os.environ["WEBHOOK_SECRET"]
app = FastAPI()
 
@app.post("/telegram")
async def telegram(request: Request, x_telegram_bot_api_secret_token: str = Header(None)):
    if x_telegram_bot_api_secret_token != SECRET:
        raise HTTPException(status_code=401)
    update = await request.json()
    msg = update.get("message") or {}
    if "text" in msg:
        async with httpx.AsyncClient() as client:
            await client.post(f"https://api.telegram.org/bot{TOKEN}/sendMessage",
                              json={"chat_id": msg["chat"]["id"], "text": f"You said: {msg['text']}"})
    return {"ok": True}

requirements.txt: fastapi, uvicorn[standard], httpx. FastAPI projects are detected and run with Uvicorn for you. More in the FastAPI deploy guide.

3. Deploy

bash
curl -fsSL https://cli.dockhosting.dev/install.sh | sh   # Windows: irm https://cli.dockhosting.dev/install.ps1 | iex
dock login
dock deploy

In the project's environment variables, set BOT_TOKEN and a long random WEBHOOK_SECRET (letters, digits, _ and -), then run dock restart.

4. Point Telegram at your URL

Run this once from your terminal, using your app's address:

bash
curl "https://api.telegram.org/bot$BOT_TOKEN/setWebhook" \
  -d "url=https://mybot.dockhosting.cloud/telegram" \
  -d "secret_token=$WEBHOOK_SECRET"

Check it with getWebhookInfo, then message your bot. dock logs shows each request as it arrives.

Free plan vs always on

On the Free plan, the app sleeps after 1 hour without requests. The next Telegram update wakes it, so the reply comes a few seconds later than usual. Telegram also retries updates that fail. For a bot people use all day, Hobby ($4/month) is always on and replies instantly.

Need a long-running bot that keeps a socket open instead? That's how Discord bots work: see hosting a Discord bot 24/7.

Frequently asked questions

Can I host a Telegram bot for free?

Yes, with webhooks. Telegram delivers each update as an HTTPS request, and on DockHosting's Free plan a sleeping app wakes on the next request, so the first reply after a quiet hour can take a few seconds. For instant replies all the time, Hobby ($4/month) is always on.

Webhook or long polling: which should I use?

Polling keeps a process asking Telegram for updates, so it must run all the time. Webhooks let Telegram push updates to your URL, which needs HTTPS but no always-running loop. For hosted bots, webhooks are simpler and cheaper.

Does Telegram need HTTPS for webhooks?

Yes. Every DockHosting app gets HTTPS automatically on its .dockhosting.cloud address, so the URL works as a webhook right away.

  • Telegram bot
  • Webhooks
  • Node.js
  • Python
  • Tutorial

Written by Doughmi ILYAS

Doughmi builds DockHosting, the developer-first platform behind dock deploy: the build system, the managed databases and the dashboard. On this blog: guides to shipping apps without running servers, written with the commands the platform actually ships.

Summarize with

Share

All posts

Create an account, run dock deploy, and get a live HTTPS URL in minutes.