Telegram Bot Security Best Practices
A bot token is a password that anyone can use from anywhere, with no second factor and no login alert. Most Telegram bot incidents start there. Here is what to lock down, in the order it usually goes wrong.
1. Treat the token as a live credential
Whoever holds your bot token controls the bot completely. They can read incoming messages, send messages as you, and change your webhook so your own server stops receiving updates. There is no password prompt and no device approval in the way.
Where tokens leak
- Committed to a repository. The most common route by far, and public repos are scanned continuously by bots that are not yours.
- Pasted into a support chat or an issue tracker. Once it is in a ticket it is in a search index somewhere.
- Hardcoded in a mobile or front-end build. Anything shipped to a client device is public.
- Left in logs. If you log the full API URL, the token is in the URL.
What to do instead
- Keep the token in an environment variable or a secrets manager, never in source.
- Add
.envto.gitignorebefore the first commit, not after. - Redact the token in log output.
- Use separate tokens for development and production so a leaked test token cannot touch real users.
If a token leaks, revoke it
Open BotFather, run /revoke, and pick the bot. The old token stops working immediately and you get a new one. Rotating it costs a few minutes of downtime. Leaving it costs the bot. Rewriting git history does not help, because the token was already scraped.
2. Harden the webhook
If your bot uses a webhook, that URL is an open endpoint on the internet. Anyone who finds it can post fake updates that look exactly like real Telegram traffic.
- Set a secret token. The
setWebhookmethod accepts asecret_tokenparameter. Telegram then sends it back in theX-Telegram-Bot-Api-Secret-Tokenheader on every request. Reject anything that does not match. - Use HTTPS with a valid certificate. Telegram requires it, and it stops the payload being readable in transit.
- Use an unguessable path. A random segment in the URL is not real security on its own, but it removes you from opportunistic scanning.
- Limit what you receive. The
allowed_updatesparameter lets you subscribe only to the update types you handle. Less surface, less parsing. - Return quickly. Acknowledge the request, then do the work asynchronously. Slow webhook handlers are a denial of service waiting to happen.
3. Never trust the content of an update
Everything inside an update was typed by a user. The display name, the message text, the callback data on a button press. All of it is attacker-controlled input.
- Validate callback data server side. A button that carries
order_id=123can be replayed withorder_id=124. Check that the pressing user owns the record. - Escape user text before echoing it. If you send messages in HTML or Markdown mode and paste a display name straight in, a crafted name can break your formatting or inject a link.
- Parameterise database queries. Chat input reaching a query string is the same injection risk as a web form.
- Cap the sizes you accept. Set limits on text length and file size before you process anything.
4. Lock down admin commands
Almost every bot grows an admin command. Broadcast, refund, export users. This is where a working bot becomes an incident.
- Check an allowlist of user IDs on the server, held in configuration. Never infer admin status from a username, which can be changed and reused.
- Do not hide, verify. An undocumented command is discovered the moment someone tries it. Obscurity is not the control.
- Confirm destructive actions with a second step, and include what is about to happen in the confirmation text.
- Log admin actions with the user ID and timestamp so you can answer "who sent that broadcast" later.
5. Turn on privacy mode in groups
By default a bot added to a group only receives messages that are commands, replies to its own messages, or mentions of it. That default is called privacy mode and it exists for good reason.
You can disable it with /setprivacy in BotFather so the bot sees every message in the group. Only do that if a feature genuinely needs it. Once it is off, your server is storing other people's conversations, and you now own that liability.
6. Rate limit yourself and your users
Telegram applies its own limits, and hitting them gets you throttled or temporarily blocked. Broad guidance from Telegram is roughly 30 messages per second across different chats, and about 20 messages per minute into the same group. Treat those as ceilings to stay well under, not targets.
- Queue outgoing messages rather than sending in a tight loop.
- Honour the retry-after value when the API returns a 429 instead of retrying immediately.
- Throttle per user as well. One person spamming a command should not be able to drive your costs or exhaust your quota.
- Put a cooldown on anything expensive, such as calls to a paid AI model or an image generation step.
7. Collect less user data
The safest record is the one you never stored. Bots accumulate chat IDs, names, phone numbers and message content by default, and most of it is never used.
- Store the chat ID and what you actually need. Skip the rest.
- Do not log full message bodies unless you have a concrete reason and a retention limit.
- Set a retention period and delete on schedule.
- Encrypt sensitive fields at rest and restrict who can query the database.
- Support deletion requests. Under GDPR and similar laws a user can ask you to remove their data, and you need a way to do it.
- Say what you collect in a privacy policy that the bot can link to.
Note that phone numbers only reach you if the user taps a contact request button. Asking for one you do not need is both a conversion cost and a liability.
8. Verify Web App and Login Widget data
If your bot opens a Telegram Web App or you use the Login Widget on a website, the user data arrives with a hash. Verify that hash on your server using your bot token before you trust a single field. Skipping this check means anyone can claim to be any user by editing the request.
9. Keep an eye on the boring things
- Update dependencies. Most real compromises come through a library, not through Telegram.
- Restrict who can deploy and who can read production secrets.
- Watch for unusual patterns: a spike in a single command, messages from one user in a tight loop, requests that fail the secret token check.
- Have a plan for the bad day. Revoke the token, stop the webhook, restore from backup. Write it down before you need it.
The checklist
- Token lives in environment variables, not in git, and is redacted in logs.
- You know how to run
/revokein BotFather. - Webhook uses HTTPS and a secret token that you verify on every request.
allowed_updatesis set to only what you handle.- Callback data is authorised server side, not trusted as sent.
- User text is escaped before it is echoed back in a formatted message.
- Admin commands check an ID allowlist and are logged.
- Privacy mode is on unless a feature truly requires it off.
- Outgoing messages are queued and 429 responses are respected.
- You store the minimum, delete on a schedule, and can honour a deletion request.
- Web App and Login Widget payloads are hash-verified.
Skip the parts that go wrong
With TeleMinute your token is stored server side, the webhook is managed for you, and there is no server of your own to leave exposed. You write the conversation, we run the infrastructure.
Start Building TodayKeep reading
- BotFather guide, including how to revoke and rotate a token
- Telegram bot best practices, the wider checklist
- Telegram bot UX best practices, for the design side
Frequently asked questions
What happens if my Telegram bot token leaks?
Whoever holds it controls the bot completely. They can read incoming messages, send messages as you, and change your webhook so your own server stops receiving updates. There is no password prompt in the way.
How do I revoke a Telegram bot token?
Open BotFather, send the revoke command and pick the bot. The old token stops working immediately and you get a new one. Rewriting git history does not help, because a leaked token is scraped within minutes.
Does my bot see every message in a group?
Only if you disable privacy mode. By default a bot in a group receives commands, replies to its own messages and direct mentions. Turning privacy mode off means your server stores other people conversations.
Do I need a secret token on my webhook?
Yes. Without one, anyone who finds your webhook URL can post fake updates that look exactly like real Telegram traffic. Set the secret when you register the webhook and reject requests whose header does not match.