← back to blog

Configure a Telegram Bot on a Server (Token, Webhook, Proxy)

telegram bot hosting proxy 2026

Configure a Telegram Bot on a Server (Token, Webhook, Proxy)

This is the bot-hosting guide we wish people had handed us years ago: the real commands, the real failure modes, and an honest line about where a datacenter IP will quietly sabotage you. We run managed Telegram hosting in Singapore on dedicated hardware, so we have set up more bots and proxies than we would like to admit. None of this is theoretical.

The plan is to take you from nothing to a bot that survives reboots, talks to Telegram over TLS, and keeps running through an IP block. We will also be clear about the one thing a bot does not fix, which is account hosting. Those are different problems with different answers.

what you will end up with

By the end you will have a Linux server running a Telegram bot that you control through a token, reachable either by long-polling or by an HTTPS webhook. It will run under systemd so it restarts on crash and comes back after a reboot. If your server IP is blocked or throttled by Telegram, you will know how to route the bot’s outbound traffic through a proxy. And you will understand the boundary between a bot, which lives on host telegram bot on server infrastructure like this, and a real Telegram account, which has very different hosting needs.

A bot is not an account. A bot is a program with a token that the Bot API hands you. It cannot read arbitrary chats, it cannot scrape, and it does not own a phone number. That is a feature. It also means the bot lives or dies on your server’s network reachability and your code, not on a SIM.

before you start

You need a few boring things in place first. Skip these and you will waste an afternoon debugging the wrong layer.

1. A Linux server you actually control. A small VPS is fine for a bot. One core and 1 GB of RAM runs most bots comfortably. You need root or sudo, a recent Ubuntu or Debian, and outbound HTTPS to api.telegram.org on port 443.

2. A domain name, if you want a webhook. Webhooks require HTTPS with a valid certificate, which means a real domain, not a bare IP. Long-polling needs no domain, so if you are just starting, you can skip this and add it later.

3. A runtime. Python with python-telegram-bot or aiogram, or Node with telegraf, are the common choices. The examples below are language-agnostic at the HTTP level so they apply whichever you pick.

4. A clear head about IPs. Telegram’s Bot API is generally tolerant of datacenter IPs, far more than the regular client login is. But “generally” is not “always”, and shared VPS ranges do get rate-limited or blocked. Keep that in the back of your mind. We come back to it in the proxy section and again at the end. If you want the background on why Telegram cares about network reputation at all, our note on the official Bot API pairs well with our explainer on what a mobile IP is and why Telegram cares.

the step-by-step

get a token from BotFather

Everything starts with a token. Open Telegram, find @BotFather, and create a bot.

1. Send /newbot. BotFather asks for a display name and a username. The username must end in bot, for example acme_alerts_bot.

2. Save the token. BotFather replies with a string like 123456789:AAExampleTokenStringFromBotFather. That token is the whole identity of your bot. Anyone who has it controls the bot. Treat it like a password.

3. Keep it out of your code. Put it in an environment variable or a secrets file, never hardcoded in a repo. On the server:

# store the token where only your service user can read it
sudo install -m 600 /dev/null /etc/acme-bot.env
echo 'BOT_TOKEN=123456789:AAExampleTokenStringFromBotFather' | sudo tee /etc/acme-bot.env >/dev/null

# quick sanity check that the token works
curl -s "https://api.telegram.org/bot${BOT_TOKEN}/getMe" | python3 -m json.tool

If getMe returns your bot’s username and "ok": true, the token is live and your server can reach Telegram. If it hangs or times out, your outbound network is the problem, not the token. Half of all “my bot is broken” reports are actually a blocked outbound path.

choose long-polling vs webhook

There are two ways your bot learns about new messages. Pick one. They are mutually exclusive at any moment.

Long-polling means your bot calls getUpdates in a loop and Telegram answers when something arrives. It needs no inbound ports, no domain, no certificate. It works behind NAT, behind a firewall, on a laptop. It is the right default for getting started and for low-traffic bots.

Webhook means Telegram pushes updates to an HTTPS URL you expose. It scales better, has lower latency, and uses fewer resources because there is no polling loop. It requires a public domain, a valid TLS certificate, and an open port (443, 80, 88, or 8443). It is the right call for production bots with real traffic.

If you are unsure, start with long-polling. Switching to a webhook later is a single API call. A good mental model for the trade-offs across transports is our piece on MTProto vs SOCKS5 vs cloud phone for Telegram, which covers the same “push vs pull, who reaches whom” thinking at the network layer.

set the webhook with TLS

If you chose webhook, you need a real certificate. Use a reverse proxy in front of your bot. The pattern is: Telegram talks HTTPS to nginx or Caddy, which forwards plain HTTP to your bot on localhost.

1. Get a certificate. With Caddy this is automatic. With nginx, use Certbot to issue a Let’s Encrypt cert for bot.example.com.

2. Point a path at your bot. Have the reverse proxy forward, say, https://bot.example.com/tg/<secret-path> to http://127.0.0.1:8080. Using a long random secret path is a cheap way to stop strangers poking your endpoint.

3. Register the webhook with Telegram.

# tell Telegram where to push updates, and set a secret header
curl -s "https://api.telegram.org/bot${BOT_TOKEN}/setWebhook" \
  -d "url=https://bot.example.com/tg/$(cat /etc/acme-bot.secret)" \
  -d "secret_token=$(cat /etc/acme-bot.hdr)" \
  -d "max_connections=40" \
  -d "drop_pending_updates=true" | python3 -m json.tool

# confirm it stuck
curl -s "https://api.telegram.org/bot${BOT_TOKEN}/getWebhookInfo" | python3 -m json.tool

The secret_token is important. Telegram sends it back in the X-Telegram-Bot-Api-Secret-Token header on every request, and your bot should reject any request that lacks it. That stops anyone who guesses your URL from injecting fake updates.

Check getWebhookInfo whenever something feels off. The last_error_message field is the single most useful diagnostic Telegram gives you. A TLS error there means your cert chain is incomplete. A connection timeout means your firewall is dropping inbound 443.

run under systemd

A bot you start by hand in an SSH session dies when you log out. Do not do that past the first five minutes. Use systemd so the bot restarts on crash and comes back after a reboot.

# /etc/systemd/system/acme-bot.service
[Unit]
After=network-online.target
Wants=network-online.target
[Service]
User=acmebot
EnvironmentFile=/etc/acme-bot.env
WorkingDirectory=/opt/acme-bot
ExecStart=/opt/acme-bot/venv/bin/python /opt/acme-bot/bot.py
Restart=always
RestartSec=5
NoNewPrivileges=true
ProtectSystem=strict
[Install]
WantedBy=multi-user.target

Then sudo systemctl daemon-reload, sudo systemctl enable --now acme-bot.service, and watch logs with journalctl -u acme-bot.service -f.

Restart=always with a five-second backoff handles transient crashes and network blips. Run a dedicated unprivileged user, not root, and lock down what the service can touch. A bot token plus root is a bad combination if your code ever gets exploited.

route the bot through a proxy

Sometimes your server IP is the problem. Maybe the whole VPS range got rate-limited, maybe a previous tenant abused it, maybe Telegram is throttling that subnet. The Bot API supports an HTTPS or SOCKS5 proxy for outbound calls, and most bot libraries expose a proxy setting.

1. For libraries, set the proxy in the client. python-telegram-bot, aiogram, and telegraf all accept a proxy URL on the HTTP client. Point it at your proxy and the bot’s calls to api.telegram.org go through it.

2. For raw curl and quick tests, use the proxy flags.

# route a Bot API call through a SOCKS5 proxy
curl -s --proxy socks5h://user:[email protected]:1080 \
  "https://api.telegram.org/bot${BOT_TOKEN}/getMe" | python3 -m json.tool

Use socks5h rather than socks5 so DNS resolves through the proxy too, which avoids leaking lookups and dodges DNS-level blocks. For the difference between proxy types and when each one helps, read what is an MTProto proxy explained. Note that MTProto proxies are for Telegram client connections, not the Bot API. For a bot you want a plain HTTPS or SOCKS5 proxy on the outbound HTTP client.

A proxy fixes a blocked or throttled IP. It does not fix bad code, an invalid token, or a webhook with a broken cert. Diagnose the layer first, then reach for the proxy.

keep it alive

A bot that runs is not the same as a bot you can trust. Add the boring reliability pieces.

1. Health checks. Have the bot expose a /healthz endpoint or write a heartbeat file, and watch it. systemd’s Restart=always covers crashes, but a hung process that never crashes will sit there doing nothing.

2. Backoff on errors. When Telegram returns 429, respect the retry_after value. Hammering the API after a rate-limit just extends the penalty.

3. Log to journald and rotate. Keep enough history to debug, not so much you fill the disk.

4. Watch getWebhookInfo or your polling loop. A silent webhook with a rising pending_update_count means Telegram is queueing updates it cannot deliver. Catch that early.

what can go wrong

A short field guide to the failures we see most.

Webhook and polling at the same time. If you set a webhook, getUpdates will refuse to work, and vice versa. Pick one. To go back to polling, call deleteWebhook.

Self-signed or incomplete certificate. Telegram will not push to a webhook with a cert it cannot verify. Use a real CA. Make sure the full chain is served, not just the leaf cert. getWebhookInfo will tell you in last_error_message.

Firewall drops inbound 443. A correct webhook with a closed port looks identical to a broken bot. Confirm the port is open from outside, not just from the server itself.

Token in a public repo. If you ever commit a token, assume it is compromised and revoke it with BotFather’s /revoke immediately. A leaked token lets anyone send messages as your bot.

Blocked or throttled server IP. This is the subtle one. The Bot API is more forgiving than the client login, but datacenter ranges still get rate-limited or blocked. Symptoms are timeouts on getMe or persistent 429s that are not tied to your traffic. The fix is the proxy section above, or moving to better-reputation egress.

Confusing a bot with an account. People try to make a bot do things only a user account can do, like reading every message in a group it does not administer, or logging in with a phone number. That is not what the Bot API is for. If your goal needs a real account, you are in a different chapter entirely, which is the next section.

how this looks on managed hosting

Everything above is a bot, and a bot is the easy case: a token and a server. The hard case is hosting a real Telegram account, the kind with a phone number, contacts, and a presence that Telegram’s anti-abuse system scrutinizes. That is what we built telegramvault.org for.

A bot rides on the Bot API and tolerates datacenter IPs reasonably well. A user account does not. Log a real account in from a datacenter IP, especially a shared VPS range, and you raise your odds of a limit or a ban, because that traffic looks nothing like a phone on a carrier network. We go deep on the why in why Telegram bans accounts and how Telegram’s spam algorithm actually works.

That is the gap our managed hosting fills, and only for accounts, not bots. We run a dedicated Samsung cloud-phone fleet in Singapore, each account on a real device behind a real Singapore mobile IP from SingTel, M1, StarHub, or Vivifi. The number stays yours: it is a BYO-number model where you keep ownership of the number and receive your own OTP. We do not sell accounts and we do not send bulk messages. We host the account you already own on hardware that looks like what Telegram expects to see.

If you want the device-side picture, what is a cloud phone and how it works and Telegram device limits and cloud-phone hosting cover it. If your real worry is the IP, the Singapore mobile IP advantage for Telegram and what is a dedicated mobile IP are the ones to read. For the carrier-NAT side of why mobile IPs behave differently, see carrier-grade NAT and Telegram. And if you are weighing this against rolling your own box, telegramvault vs a VPS with telegram-cli is the honest comparison.

One more boundary: if you literally want a bot on a cloud phone for a specific reason, that niche case is covered in how to run a Telegram bot on a cloud phone. For most bots, the plain Linux server above is correct and cheaper. Use a cloud phone for accounts, a server for bots. The mobile-IP infrastructure is the same hardware we run at Singapore Mobile Proxy and cloudf.one.

final word

Hosting a Telegram bot on a server is a solved problem and you can do it yourself: get a token from BotFather, decide between long-polling and a webhook, put TLS in front of the webhook, run the thing under systemd, and keep a proxy in your back pocket for the day your server IP gets throttled. Nothing in this guide needs us. That is the point. A bot is yours to run.

Where it changes is when you stop talking about bots and start talking about real accounts. Accounts on datacenter IPs get burned, and no amount of clever systemd config changes that. That is the part we host: your number, your OTP, on a dedicated Singapore cloud phone behind a real mobile IP. If that is the actual problem you are trying to solve, come see how managed Telegram hosting works and use code TGYT for a discount when you start. If you just needed a bot running, you already have everything you need above.

Get new guides and videos first — join the Telegram channel.

need infra for this today?