The short answer: BotFather issues the token
To get a Telegram bot token, open a chat with @BotFather, send /newbot, give the bot a display name, then a username that ends in "bot". BotFather replies immediately with the token, a string shaped like 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw. That string is the bot's only credential: whoever holds it controls the bot.
Last verified: November 2026 against Telegram's BotFather documentation and the Bot API reference.
The full sequence, start to finish:
- In any Telegram app, search for
@BotFatherand open the account with the blue verification check. t.me/BotFather opens it directly. Impersonator accounts with similar names exist, and they collect tokens. - Tap Start (or send
/start) to see the command list. - Send
/newbot. - When asked for a name, send the display name users will see in chats, for example
Acme Support. - When asked for a username, send a unique handle ending in
bot, for exampleacme_support_bot. - BotFather confirms with a message containing your bot's
t.melink and the HTTP API token. Copy the token into a secret store right away, not into a notes app or a chat with a colleague.
Telegram also ships a BotFather Mini App with the same functions in a graphical interface. The commands below work in both, and the docs describe the chat commands as the reference.
Display name vs username: the one choice you cannot undo
BotFather asks for two identifiers that look interchangeable and are not. The display name is cosmetic and editable. The username is permanent.
| Display name | Username | |
|---|---|---|
| Where it shows | Chat header, contact details, notifications | Search, @mentions, t.me/<username> links |
| Rules | Free text; setMyName accepts 0-64 characters | 5-32 characters, Latin letters, digits and underscores, case-insensitive, must end in bot |
| Example | Acme Support | acme_support_bot or AcmeSupportBot |
| Change later? | Yes: /setname or the setMyName method | No. Telegram's docs say the username cannot be changed after creation |
Two rejections come up constantly at this step. The username is taken: usernames are global across Telegram, so short generic names are long gone, and adding your brand plus a function (acme_orders_bot) usually works. It does not end in "bot": the suffix is mandatory, in any case (tetris_bot and TetrisBot are both valid, per the docs).
Because the username lives in every link you print, every QR code and every /command@username in a group, treat it like a domain name. If you need a test bot, create a second bot with a second username rather than renaming the production one later, which you cannot do anyway.
What the token is made of, and the "bot" prefix
A token has two halves separated by a colon:
110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw
|_______| |__________________________________|
numeric secret part
bot IDThe part before the colon is numeric and identifies the bot; you will see the same number as the id field when you call getMe, which makes it a handy way to tell two bots' tokens apart without exposing the secret. The part after the colon is the secret. People sometimes call the whole string a "Telegram bot API key"; there is no separate API key, API secret or client ID for the Bot API. This token is all of it.
Every Bot API call puts the token in the URL path, prefixed with the literal word bot:
https://api.telegram.org/bot<TOKEN>/METHOD_NAME
https://api.telegram.org/bot110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw/getMeThe docs call this out explicitly ("remember to prefix the word 'bot' to your token"), and it is still the most common copy-paste error. The two failure signatures are distinct:
| Response | Usual cause |
|---|---|
{"ok":false,"error_code":404,"description":"Not Found"} | The bot prefix is missing, the method name is misspelled, or the URL has an extra slash. See 404 Not Found. |
{"ok":false,"error_code":401,"description":"Unauthorized"} | The token is wrong, truncated, has whitespace or quotes in it, or was regenerated. See 401 Unauthorized. |
Libraries such as python-telegram-bot, aiogram, grammY and Telegraf add the prefix for you, so pass them the bare token. Passing bot123:ABC to a library produces botbot123:ABC in the URL and a 401 or 404 that looks baffling until you log the request path.
Finding the token for a bot you already created
Lost the original message? You do not need to create a new bot. BotFather keeps the token available to the bot's owner:
- Send
/mybotsto @BotFather. - Tap the bot in the list.
- Tap API Token. BotFather shows the current token.
Only the Telegram account that owns the bot can do this. If the bot was created by a former employee or an agency, the owner must either send you the token or use BotFather's ownership transfer (/mybots, select the bot, transfer ownership). Telegram's docs note two constraints: the recipient must have interacted with the bot at least once, and the transfer is permanent and hands over full control, including deleting the bot.
Transfer is the right fix for an orphaned business bot. Asking the old owner to paste the token in Slack leaves a live credential in a chat log forever and leaves them able to regenerate it at any time, which silently breaks your integration.
Test the token with getMe before writing any code
getMe is documented as "a simple method for testing your bot's authentication token". It needs no parameters:
curl -s https://api.telegram.org/bot<TOKEN>/getMeA valid token returns the bot's own profile:
{
"ok": true,
"result": {
"id": 110201543,
"is_bot": true,
"first_name": "Acme Support",
"username": "acme_support_bot",
"can_join_groups": true,
"can_read_all_group_messages": false,
"supports_inline_queries": false
}
}Three fields here are only returned by getMe and answer questions people usually debug the hard way:
can_read_all_group_messagesistrueonly if privacy mode is disabled. If it isfalse, your bot will not see ordinary group chatter, which is the default and usually correct.can_join_groupsreflects the/setjoingroupstoggle. If it isfalse, nobody can add the bot to a group.supports_inline_queriesreflects/setinline.
Check that username is the bot you expect. Teams with a staging bot and a production bot regularly ship the wrong token, and both pass getMe. If you would rather not use a terminal, the Telegram bot token checker runs getMe and getWebhookInfo from your browser and explains the result.
How to revoke a Telegram bot token and issue a new one
If a token leaks, regenerate it. Telegram's docs name the command: "If your existing token is compromised or you lost it for some reason, use the /token command to generate a new one." BotFather asks which bot, then replies with a fresh token. In the /mybots menu, the API Token screen offers the same action as a button. Older tutorials refer to a /revoke command; Telegram's documentation says the live command list in BotFather (type / in the chat) is the authoritative reference, so use whichever your client shows.
What happens next matters more than the command:
- The old token stops authenticating. Every process still using it starts receiving
401 Unauthorized. There is no grace period to plan around, so have the new value ready to deploy before you regenerate. - The bot keeps its identity. Same username, same numeric ID, same chats and subscribers. Only the secret half of the token changes.
- Update every consumer. Production, workers, cron jobs, CI secrets, any third-party platform the token was pasted into. A single forgotten worker using the old token will log 401s that are easy to mistake for an outage.
- Re-check delivery. After deploying, call
getWebhookInfoand confirm theurlandpending_update_countlook right, or run the Telegram webhook checker.
Regenerate on a schedule only if you have automated the rollout. Regenerating by hand "for hygiene" is a reliable way to take a working bot offline at 5 p.m. on a Friday.
One special case: if you build a manager bot with Bot Management Mode, the Bot API exposes getManagedBotToken to fetch a managed bot's token and replaceManagedBotToken to revoke it and generate a new one, so rotation can be automated without BotFather.
Storing the token so it never ends up somewhere public
Telegram's own tutorial says to "treat it like a password" and suggests a settings file or environment variables rather than source code. In practice that means:
| Environment | Where the token should live |
|---|---|
| Local development | A .env file listed in .gitignore, loaded at startup |
| Containers / PaaS | The platform's secret or environment variable store, injected at runtime |
| Cloud production | A secrets manager (AWS Secrets Manager, GCP Secret Manager, Vault), read at boot |
| CI | Encrypted CI secrets, masked in logs |
| Browser, mobile app, Mini App front end | Nowhere. Anything shipped to a client can be extracted |
The token sits in the URL path of every API call, which creates a leak path people miss: request logs. HTTP client debug logging, reverse proxy access logs, APM tools and error trackers that capture outbound URLs will all record /bot<TOKEN>/sendMessage unless you redact it. Grep your log pipeline for api.telegram.org/bot once and add a scrubbing rule.
Two related secrets are worth setting up at the same time:
- Webhook secret.
setWebhookaccepts asecret_token(1-256 characters,A-Z,a-z,0-9,_and-). Telegram then sends it in theX-Telegram-Bot-Api-Secret-Tokenheader on every update, so your endpoint can reject requests that did not come from your webhook. Do not reuse the bot token for this value. - A separate test bot. The docs recommend testing on a different bot account with its own token, so development traffic never touches production users or credentials.
Before trusting any third-party bot platform or browser tool with a production token, check what it does with it: whether calls go straight from your browser to Telegram, or whether the token is stored server-side. When in doubt, test with a throwaway bot.
What never to do with a bot token
A Telegram bot token is not scoped. There are no read-only tokens and no per-method permissions: the holder can send messages as your bot to every user who started it, read every update, change the webhook to their own server, and edit the bot's commands and profile. That makes the list of mistakes short and absolute:
- Do not paste it in public. GitHub issues, Stack Overflow questions, Discord help channels, screen recordings and screenshots of BotFather all leak tokens. Replace it with
<TOKEN>before sharing anything. - Do not commit it. Removing the line in a later commit does not remove it from history. If a token was ever committed to a shared repo, regenerate it.
- Do not embed it in client code. A website that calls
api.telegram.orgfrom JavaScript, or a mobile app with the token in its bundle, hands the bot to anyone who opens developer tools. - Do not share one token across environments. One token, one deployment. Two processes polling the same token produce the 409 conflict, and a dev laptop running the production token will steal its updates.
- Do not send it to contractors. Add them to the code, not the credential, or transfer ownership deliberately.
If you suspect a leak, the response is the same every time: run /token, deploy the new value, call getWebhookInfo to confirm the webhook still points to your server and not someone else's, and review getMyCommands in case the bot's menu was changed.
Next step: choose getUpdates or setWebhook
With a working token, the bot still receives nothing until you pick one of the two update delivery methods. They are mutually exclusive: the docs state you cannot receive updates with getUpdates while an outgoing webhook is set.
| getUpdates (long polling) | setWebhook | |
|---|---|---|
| How it works | Your process asks Telegram for new updates in a loop | Telegram POSTs each update to your HTTPS URL |
| Needs a public URL | No | Yes, HTTPS on port 443, 80, 88 or 8443 |
| Best for | Local development, single-instance bots, firewalled hosts | Production, serverless, horizontally scaled backends |
| Main failure mode | Two pollers on one token (409 conflict) | Endpoint errors or TLS problems that pile up undelivered updates |
| Switch with | deleteWebhook before polling | setWebhook with url; empty string removes it |
A minimal first test with polling needs nothing but the token:
curl -s "https://api.telegram.org/bot<TOKEN>/getUpdates?timeout=30"Send your bot a message from your phone and the update appears in the response, including chat.id, which you need for sendMessage. From there:
- Generate shareable
t.melinks with a start payload using the Telegram link generator. - Check message sizes, polling and webhook ceilings on the Telegram limits page before you design around them.
- If the bot connects but stays silent, work through why a Telegram bot is not responding, which starts from
getWebhookInfo. - Look up any error string you hit in the Telegram Bot API error codes guide.
If you would rather not run the webhook server at all, a hosted platform can take the token and handle delivery for you; Conferbot's Telegram integration works that way, with the conversation built in a visual editor. Either way, the token you just created is the only thing that ties the bot to you, so the storage rules above apply regardless of who runs the code.
Was this article helpful?
Build and deploy in 10 minutes. No coding needed.
How to Get a Telegram Bot Token from BotFather (and Keep It Safe) FAQ
Everything you need to know about chatbots for how to get a telegram bot token from botfather (and keep it safe).
About the Author
The Conferbot team writes about building, deploying, and improving AI chatbots.
View all articlesRelated Articles
From the reference shelf
Fact-checked reference pages and free tools for the platform this article covers.