Telegram Bots

Securing Your Telegram Bot Token and Admin Commands

Protect your Telegram bot from takeover and abuse — token handling, revoking leaks, verifying admins by ID, validating callbacks, webhook secrets and safe input.

On this page
  1. Protecting the token
  2. Verifying admins correctly
  3. Validate everything from updates
  4. Secure your webhook
  5. Limit abuse
  6. Protect your users’ data
  7. A security checklist
  8. Summary

A Telegram bot token grants complete control of your bot: reading every message it receives, sending messages as it, and changing its settings. Admin commands grant control over whatever your bot manages — groups, users, data. This article covers how to protect both.

Protecting the token

Where tokens leak

The same few mistakes cause almost every leak:

  • The token is pasted into source code and the repository is made public.
  • It’s removed in a later commit but remains in git history.
  • It appears in a screenshot, a shared snippet or a support request.
  • Debug logging prints the configuration or the full request URL — Bot API URLs contain the token (https://api.telegram.org/bot<token>/sendMessage).

That last one is easy to miss. If you log outgoing request URLs, or an error message includes one, your token is in your logs.

Keep it in environment variables

Read the token from the environment:

import os
BOT_TOKEN = os.environ["BOT_TOKEN"]
const bot = new Bot(process.env.BOT_TOKEN);

Locally, keep it in a git-ignored .env file. In production, set it in your host’s panel — on Kerit Cloud, environment variables are stored encrypted and never printed in logs, and each bot runs in its own isolated container. Using .env files in Node.js and Python shows the setup.

Revoke a leaked token immediately

If a token might have leaked, open @BotFather, choose your bot and use /revoke (or API Token → Revoke current token). The old token stops working at once and BotFather issues a new one. Update your environment variable, restart the bot, and only then worry about cleaning up git history.

Protect the account that owns the bot

Your bots are controlled through BotFather from your personal Telegram account. If someone takes over that account, they take over every bot. Enable two-step verification in Telegram’s privacy settings, review active sessions regularly, and be wary of anyone asking you to log in somewhere “to verify your bot”.

Verifying admins correctly

Check user IDs, not usernames

A very common pattern is:

if message.from_user.username == "myname":   # DON'T

Usernames can be changed at any time — and once you change yours, someone else can claim it and inherit your admin powers. Always compare numeric user IDs, which never change:

ADMIN_IDS = {int(x) for x in os.environ.get("ADMIN_IDS", "").split(",") if x}

def is_admin(user_id: int) -> bool:
    return user_id in ADMIN_IDS

Find your ID by logging message.from_user.id when you message the bot.

Group admins: ask Telegram

For commands meant for group administrators, don’t maintain your own list — ask Telegram whether the user is an admin of that chat:

member = await bot.get_chat_member(chat_id, user_id)
if member.status not in ("administrator", "creator"):
    return await message.reply("Only group admins can do that.")

Cache the result briefly (a minute or two) if the command is used often, but re-check regularly — admins get demoted.

Watch for anonymous admins

In groups, admins can post anonymously on behalf of the group. Their messages arrive with sender_chat set to the group and a generic from_user. Decide deliberately whether your bot trusts anonymous admin actions, and handle that case explicitly rather than letting it fall through.

Validate everything from updates

Callback data can be forged

Inline keyboard buttons carry callback_data that your bot set — but don’t assume it arrives unchanged. Modified clients can send any callback data they like. Treat it as user input:

  • Parse it strictly and reject anything unexpected.
  • Re-check permissions when the button is pressed, not only when it was shown. A “Delete post 42” button must verify that the presser is allowed to delete post 42.
  • Don’t put secrets or trust decisions in callback data.

Escape user text

If your bot uses HTML or MarkdownV2 parse mode, escape any user-supplied text before including it in a message. Otherwise a user’s <b> or * breaks your formatting — or causes “can’t parse entities” errors that make the command fail. In Python, html.escape(); in grammY and Telegraf, their formatting helpers.

Never evaluate user input

Owner-only /eval or /shell commands are a common feature in hobby bots and a common way bots get compromised. If you must have one, restrict it to your user ID in code, keep it out of group chats, and consider removing it from production builds entirely.

Secure your webhook

If you use webhooks, register a secret_token with setWebhook and reject any request whose X-Telegram-Bot-Api-Secret-Token header doesn’t match. Without it, anyone who finds your URL can send your bot fake updates — including fake messages “from” an admin. The full setup is in setting up a Telegram webhook over HTTPS.

Limit abuse

  • Rate-limit per user. A middleware that throttles each user protects your bot from floods and your account from Telegram’s limits.
  • Cap input sizes. Reject or truncate very long texts and large files before processing them.
  • Give your bot only the group rights it needs. A bot that only reads commands doesn’t need to ban users or pin messages. If its token ever leaks, limited rights mean limited damage.
  • Keep privacy mode on in groups unless the bot genuinely needs every message.

Protect your users’ data

Bots often store user IDs, names, messages and settings. Store only what you need, keep database credentials in environment variables, restrict database access to the bot, and delete data you no longer use. If your users are in regions with data-protection laws, collecting less makes compliance simpler. See keeping database credentials secure.

A security checklist

  • [ ] Token in environment variables, never in code or logs
  • [ ] Outgoing request URLs not logged
  • [ ] Two-step verification on the owning Telegram account
  • [ ] Admins identified by numeric user ID
  • [ ] Group admin rights checked with getChatMember
  • [ ] Callback data parsed strictly and permissions re-checked
  • [ ] User text escaped for your parse mode
  • [ ] Webhook secret token set and verified
  • [ ] Per-user rate limiting and input caps
  • [ ] Minimal bot rights in groups

Summary

Keep the token in environment variables and out of logs, revoke it through BotFather the moment it might have leaked, and protect the Telegram account that owns your bots. Identify admins by user ID, check group admin status with Telegram, treat callback data and message text as untrusted input, and secure webhooks with a secret token. Those habits stop the overwhelming majority of bot takeovers and abuse.