How to Create a Telegram Bot: Step by Step with BotFather and Python
Here is how to create a Telegram bot in a few minutes: open @BotFather, send /newbot, choose a name and a username that ends in bot, and copy the token BotFather gives you. That token is all your code needs to talk to the Telegram Bot API. This guide takes you from BotFather to a first message sent with curl and Python, then turns it into a tiny echo bot.
What you need
- A Telegram account in any app: phone, desktop or web.
- A terminal with
curl, or Python 3 with therequestspackage (pip install requests). - No server yet. During development your bot can fetch updates with
getUpdatesfrom any computer, even behind NAT. A public HTTPS server only matters once you switch to a webhook.
Step 1: create a Telegram bot with @BotFather
@BotFather is Telegram's own bot for creating and managing bots. This step needs no code:
- Open t.me/BotFather and press Start. Use this link rather than search, so you don't end up in a look-alike account.
- Send
/newbot. - Enter a name, for example
Weather Alerts. It is shown in chats and contacts, and you can change it later with/setname. - Enter a username, for example
weather_alerts_bot: 5–32 characters, only Latin letters, digits and underscores, ending inbot(tetris_botandTetrisBotboth work). Usernames are not case sensitive and, unlike the name, can't be changed later. - BotFather confirms with a link to your bot, such as
t.me/weather_alerts_bot, and the token.
If the username is taken or breaks the rules, BotFather simply asks for another one. Prefer buttons to commands? The @BotFather Mini App offers the same functions in a graphical interface.
Step 2: copy the token and keep it secret
The token looks like 123456789:AAEexampleTokenReplaceWithYours. Anyone who has it can control your bot: read its incoming messages, send messages in its name and change its settings. Keep it out of screenshots, public repositories and front-end code, and load it from an environment variable in real projects. If you lose the token or it leaks, see how to find, check and revoke a Telegram bot token.
Step 3: check the token with getMe
Every Bot API call has the form https://api.telegram.org/bot<token>/METHOD_NAME, with the word bot right before the token and no slash in between. getMe takes no parameters and is the quickest way to test a token:
curl "https://api.telegram.org/bot123456789:AAEexampleTokenReplaceWithYours/getMe"
A valid token returns your bot's User object (shortened):
{
"ok": true,
"result": {
"id": 123456789,
"is_bot": true,
"first_name": "Weather Alerts",
"username": "weather_alerts_bot",
"can_join_groups": true,
"can_read_all_group_messages": false,
"supports_inline_queries": false
}
}
can_read_all_group_messages: false means privacy mode is on, which is the default. 401 Unauthorized means the token is wrong or revoked; 404 Not Found usually means a broken URL, typically a missing bot prefix. No terminal at hand? Open getMe in the Bot API Tester, paste the token and press Execute; the token stays in your browser.
Step 4: send /start and find your chat id
Bots can't start conversations, so message your bot first: open t.me/weather_alerts_bot (with your own username), press Start, which sends /start, and type any text. Then fetch the waiting updates:
curl "https://api.telegram.org/bot123456789:AAEexampleTokenReplaceWithYours/getUpdates"
{
"ok": true,
"result": [
{
"update_id": 870123456,
"message": {
"message_id": 1,
"from": {"id": 123456789, "is_bot": false, "first_name": "Alex"},
"chat": {"id": 123456789, "first_name": "Alex", "type": "private"},
"date": 1793266200,
"text": "/start"
}
}
]
}
The number in message.chat.id is the chat id you need for sending messages; in a private chat it equals your user id. An empty result means there is nothing new: send another message and repeat the call. Group, channel and topic ids work differently, see how to get a Telegram chat id.
Step 5: send your first message with curl and Python
Call sendMessage with its two required parameters, chat_id and text:
curl -X POST "https://api.telegram.org/bot123456789:AAEexampleTokenReplaceWithYours/sendMessage" \
-H "Content-Type: application/json" \
-d '{"chat_id": 123456789, "text": "Hello from my new bot!"}'
The same in Python with requests:
import requests
TOKEN = "123456789:AAEexampleTokenReplaceWithYours"
API = f"https://api.telegram.org/bot{TOKEN}"
resp = requests.post(f"{API}/sendMessage",
json={"chat_id": 123456789, "text": "Hello from Python!"},
timeout=10).json()
if resp["ok"]:
print("Sent message", resp["result"]["message_id"])
else:
print("Error", resp["error_code"], resp["description"])
The message appears in your chat with the bot right away. Formatting, buttons and error handling are covered in how to send messages with the Bot API.
Step 6: a minimal Telegram bot in Python
A bot is just a loop: receive updates, react to them. This echo bot uses long polling (with timeout=30 each request waits up to 30 seconds for new updates) and confirms processed updates with offset:
import requests
TOKEN = "123456789:AAEexampleTokenReplaceWithYours"
API = f"https://api.telegram.org/bot{TOKEN}"
offset = None
while True:
data = requests.get(f"{API}/getUpdates",
params={"offset": offset, "timeout": 30}, timeout=40).json()
if not data["ok"]:
raise SystemExit(f'{data["error_code"]}: {data["description"]}')
for update in data["result"]:
offset = update["update_id"] + 1 # confirm this update
message = update.get("message")
if message and "text" in message:
requests.post(f"{API}/sendMessage", json={
"chat_id": message["chat"]["id"],
"text": f"You said: {message['text']}",
}, timeout=10)
Save it as echo_bot.py, run python echo_bot.py, write to your bot and stop the script with Ctrl+C. Only one process can poll a token at a time: a second one fails with 409 Conflict.
Optional: description, about text and commands
/setdescription: the text under "What can this bot do?" that users see in an empty chat with the bot (up to 512 characters)./setabouttext: the short bio on the bot's profile (up to 120 characters)./setuserpic: the profile picture./setcommands: the command list users see when they type/. Send one command per line in the formstart - Start the bot.
Commands can also be set from code with setMyCommands, which is handy in deploy scripts: up to 100 commands, each 1–32 characters of lowercase letters, digits and underscores, with a 1–256 character description.
curl -X POST "https://api.telegram.org/bot123456789:AAEexampleTokenReplaceWithYours/setMyCommands" \
-H "Content-Type: application/json" \
-d '{"commands": [
{"command": "start", "description": "Start the bot"},
{"command": "help", "description": "How to use this bot"}
]}'
Planning to use the bot in groups? /setjoingroups controls whether it can be added to groups at all, and /setprivacy toggles privacy mode, in which the bot receives only commands meant for it, replies to its messages and service messages.
Next steps: webhooks, libraries and Mini Apps
- Polling or webhook.
getUpdatesis perfect for development. In production many bots switch to a webhook, where Telegram POSTs each update to your HTTPS endpoint; the two methods are mutually exclusive. See how to set up a Telegram bot webhook. - Libraries. For anything bigger than an echo bot, use a library that handles updates, routing and errors: python-telegram-bot, aiogram or pyTelegramBotAPI for Python; grammY or Telegraf for Node.js; telebot or go-telegram-bot-api for Go.
- Mini Apps. A bot can open a full web interface inside Telegram. Register one with
/newappand follow how to test a Telegram Mini App.
Troubleshooting a new bot
| Problem | Cause | Fix |
|---|---|---|
| BotFather rejects the username | Already taken, wrong length, invalid characters or no bot at the end | Try a variation, for example with an extra word before _bot |
401 Unauthorized | Wrong, incomplete or revoked token | Copy it again from /mybots → your bot → API Token |
404 Not Found | Broken URL: missing bot prefix or a typo in the method name | Use https://api.telegram.org/bot<token>/getMe |
getUpdates returns "result": [] | No new updates; updates are kept for 24 hours only | Send the bot a new message and call it again |
409 Conflict | A webhook is set, or another process is already polling | Call deleteWebhook or stop the other instance |
400 Bad Request: chat not found | Wrong chat_id, or the user never started the bot | Press Start in the bot chat and re-check the id |
403 Forbidden: bot was blocked by the user | The user blocked the bot | Only the user can unblock it; don't retry |
Frequently asked questions
Is it free to create a Telegram bot?
Yes. Creating a bot with @BotFather and calling the Bot API cost nothing; you only pay for wherever you host your code. A few optional features, such as paid broadcasts, are paid in Telegram Stars.
Can I create a Telegram bot without coding?
You can register a bot in @BotFather without code, but it does nothing until a program processes its updates. If you don't want to write that program, automation tools such as n8n can drive the bot with its token.
What are the rules for a Telegram bot username?
It must be 5–32 characters long, use only Latin letters, digits and underscores, and end in bot, like tetris_bot or TetrisBot. Usernames are not case sensitive and can't be changed later.
Which programming language is best for a Telegram bot?
Any language that can make HTTPS requests. Python (python-telegram-bot, aiogram, pyTelegramBotAPI) and Node.js (grammY, Telegraf) have the most popular libraries; for Go there are telebot and go-telegram-bot-api.
Why doesn't my new Telegram bot reply?
A bot created in @BotFather has no logic of its own: it answers only while your code receives updates and calls sendMessage. Check that your script is running, the token passes getMe and no webhook blocks getUpdates.
How do I delete a Telegram bot?
Send /deletebot to @BotFather and choose the bot. This deletes it and frees its username; it can't be undone.
Related guides
Telegram Bot API 10.0–10.3: Rich Messages, Ephemeral Messages, Guest Mode and More
What's new in Telegram Bot API 10.0–10.3: guest mode, rich messages, streamed drafts, ephemeral messages, join request queries, with JSON examples.
Telegram Bot API Limits: Rate Limits, 429 Errors, File Sizes and Message Length
Telegram Bot API rate limits explained: 30 msg/s, 1 msg/s per chat, 20/min in groups, handling 429 retry_after, plus file size and message length limits.
How to Send a Message with the Telegram Bot API (sendMessage)
Telegram Bot API send message guide: sendMessage with curl, Python and JavaScript, HTML and MarkdownV2 formatting, inline buttons and error fixes.
Telegram Bot Token: How to Get It, Find It Again, Check It and Keep It Safe
Telegram bot token guide: get one from @BotFather, find the token of an existing bot, check it with getMe, revoke a leaked token and store it safely.
How to Set Up a Telegram Bot Webhook: setWebhook, Secret Token and Troubleshooting
Set up a Telegram bot webhook: setWebhook URL requirements, secret_token header check, getWebhookInfo debugging, deleteWebhook and fixes for n8n.
How to Get a Telegram Chat ID for a User, Group, Channel or Topic
How to get a Telegram chat ID for a user, group, supergroup, channel or forum topic with getUpdates, plus fixes for an empty result and 409 Conflict.
How to Test a Telegram Mini App: From Browser Mock to Real Telegram
Test a Telegram Mini App step by step: browser mock mode, localhost via HTTPS tunnel, test environment, DevTools per platform, initData validation.