Skip to main content
Share
Guides

Telegram Bot Commands: setMyCommands, Scopes, Menu Button and Deep Links

Registering commands is how users discover what your bot does. The exact BotFather format, the naming limits, all seven BotCommandScope types and the order Telegram resolves them in, localized lists, the menu button, /start payloads and how commands behave in groups.

Content & Engineering
Oct 13, 2026
11 min read
Updated Nov 2026Last verified November 2026
telegram bot commandssetmycommandsbotfather setcommandstelegram bot menu buttontelegram bot commands list
TL;DR

Registering commands is how users discover what your bot does. The exact BotFather format, the naming limits, all seven BotCommandScope types and the order Telegram resolves them in, localized lists, the menu button, /start payloads and how commands behave in groups.

Key Takeaways
  • You set a Telegram bot's command list either in @BotFather with /setcommands , sending one command - description pair per line, or from code with the Bot API method setMyCommands .
  • Each command is 1-32 characters of lowercase English letters, digits and underscores, each description is 1-256 characters, and one list holds at most 100 commands.
  • Last verified: November 2026 against the Bot API reference (through Bot API 10.3) and Telegram's bot features guide .
  • The registered list is what Telegram apps show when a user types / and what the menu button next to the message field opens.

Two ways to set Telegram bot commands

You set a Telegram bot's command list either in @BotFather with /setcommands, sending one command - description pair per line, or from code with the Bot API method setMyCommands. Each command is 1-32 characters of lowercase English letters, digits and underscores, each description is 1-256 characters, and one list holds at most 100 commands.

Last verified: November 2026 against the Bot API reference (through Bot API 10.3) and Telegram's bot features guide.

The registered list is what Telegram apps show when a user types / and what the menu button next to the message field opens. It does not create any behavior by itself: your code still has to handle /help when it arrives. Registering commands is about discoverability, and a bot with no registered commands leaves users guessing.

BotFather /setcommandssetMyCommands API
Best forA single static list, set once by handLists in code, per audience, per language, in CI
Scopes (private, groups, admins, one chat)No, sets the default listYes, seven scope types
Per-language listsNoYes, via language_code
Ephemeral flagNoYes, is_ephemeral on each command
ReversibleRe-run with a new listdeleteMyCommands per scope and language

BotFather /setcommands: the exact format

  1. Open @BotFather and send /setcommands (or go through /mybots, pick the bot, then Edit Bot and Edit Commands).
  2. Choose the bot from the list.
  3. Send the whole list as one message, one command per line, command first, then a space, a hyphen, a space and the description.
start - Start the bot and see what it can do
help - How to use this bot
order - Check the status of an order
support - Talk to a person
settings - Language and notification settings
cancel - Cancel the current action

Write the command names without the leading slash, the way Telegram's own tutorial does. Sending /setcommands again replaces the whole list rather than appending to it, so always paste the complete set. The list you set here is the default list, equivalent to setMyCommands with the default scope and no language.

If a line is rejected, the cause is almost always the name: a capital letter, a hyphen, a space or a non-Latin character in the command itself. Descriptions are free text and can be written in any language.

Command naming rules and limits

The limits below come from the BotCommand object and setMyCommands in the Bot API reference. They apply to commands you register; Telegram's features guide notes that commands users type can contain Latin letters, numbers and underscores, but only lowercase names are accepted in the registered list.

FieldRule
command1-32 characters; lowercase English letters, digits and underscores only; no leading / in the API object
description1-256 characters
is_ephemeralOptional boolean; marks a command whose message only the sender and the bot can see
Commands per listAt most 100 per setMyCommands call (one scope plus language combination)
language_codeTwo-letter ISO 639-1 code, or empty for the fallback list

Telegram's guidance is to make commands specific: /newlocation and /newrule rather than a generic /new that then asks a follow-up question. Specific commands are self-documenting in the menu and remove a conversational round trip. Keep names short enough to type on a phone; 32 characters is a ceiling, not a target.

Telegram asks every bot to support three global commands, and its apps add interface shortcuts for them:

  • /start begins the interaction and carries deep-link parameters.
  • /help explains what the bot does and lists its commands.
  • /settings, if applicable, shows the user's settings and how to change them.
Try it yourself
Build your first chatbot free
Free plan, no credit card required. Live on your site in about 10 minutes.
Start building free

setMyCommands: setting commands from code

setMyCommands takes a JSON array of BotCommand objects plus optional scope and language_code. It returns true on success. Sending JSON in the body is cleaner than the URL query string because the list nests:

curl -s https://api.telegram.org/bot<TOKEN>/setMyCommands \
  -H "Content-Type: application/json" \
  -d '{
    "commands": [
      {"command": "start",   "description": "Start the bot"},
      {"command": "help",    "description": "How to use this bot"},
      {"command": "order",   "description": "Check an order"},
      {"command": "support", "description": "Talk to a person"}
    ]
  }'

Run it at deploy time, not on every process start. The list is stored by Telegram per bot, so calling it from each of twenty workers on boot does nothing useful and burns requests. A small script in your release pipeline that sets every scope and language you support keeps the menu in version control alongside the handlers it describes.

The rest of the family:

MethodWhat it does
getMyCommandsReturns the list for a given scope and language as an array of BotCommand; an empty array if none is set
deleteMyCommandsDeletes the list for a given scope and language; affected users then see the next, broader list
setChatMenuButtonChanges what the menu button does, per private chat or as the bot default
getChatMenuButtonReturns the current menu button for a private chat or the default

Remember that deleteMyCommands with no arguments only deletes the default list. If you set lists for groups, admins or specific languages, each needs its own delete call with the same scope and language_code.

BotCommandScope: different menus for different users

Scopes let one bot show a short menu to customers in private chats, a moderation menu to group admins, and a different list in one specific group. The API defines exactly seven scope types:

Scope objecttype valueExtra fieldsCovers
BotCommandScopeDefaultdefaultNoneEveryone, when no narrower list applies
BotCommandScopeAllPrivateChatsall_private_chatsNoneAll one-to-one chats with the bot
BotCommandScopeAllGroupChatsall_group_chatsNoneAll groups and supergroups
BotCommandScopeAllChatAdministratorsall_chat_administratorsNoneAdministrators of all groups and supergroups
BotCommandScopeChatchatchat_idOne specific chat
BotCommandScopeChatAdministratorschat_administratorschat_idAdministrators of one group or supergroup
BotCommandScopeChatMemberchat_memberchat_id, user_idOne member of one group or supergroup

chat_id accepts a numeric ID or a supergroup @username; the reference notes that channel chats and channel direct-message chats are not supported for the chat-based scopes. A moderation menu for admins everywhere looks like this:

curl -s https://api.telegram.org/bot<TOKEN>/setMyCommands \
  -H "Content-Type: application/json" \
  -d '{
    "scope": {"type": "all_chat_administrators"},
    "commands": [
      {"command": "warn",  "description": "Warn the replied-to user"},
      {"command": "mute",  "description": "Mute the replied-to user"},
      {"command": "stats", "description": "Group activity summary"}
    ]
  }'

Which list a user actually sees

Telegram resolves the menu by walking a fixed order and returning the first list that is set. Lists do not merge: if an admin list exists, admins see only that list, not the admin list plus the group list. Repeat shared commands such as /help in every list.

In a private chat with the botIn a group or supergroup
1. chat + language1. chat_member + language
2. chat2. chat_member
3. all_private_chats + language3. chat_administrators + language (admins only)
4. all_private_chats4. chat_administrators (admins only)
5. default + language5. chat + language
6. default6. chat
7. all_chat_administrators + language (admins only)
8. all_chat_administrators (admins only)
9. all_group_chats + language
10. all_group_chats
11. default + language
12. default

Scopes control what is shown, not what is allowed. The features guide is explicit that updates carry no information about the scope a command came from, and may contain commands that do not exist in your bot at all. Anyone can type /mute. Check the sender's rights in your handler, for example with getChatMember, before acting on a privileged command.

Telegram Bot Token Checker
Free tool - no signup, runs in your browser.
Open free tool

Localized command lists with language_code

Pass language_code with a two-letter ISO 639-1 code and the list applies only to users whose Telegram app language matches. Leave it empty and the list becomes the fallback for that scope, used for every language you have not covered. A sensible setup is an English (or primary-market) list with no language_code, plus one call per translated language:

{
  "language_code": "es",
  "commands": [
    {"command": "start", "description": "Iniciar el bot"},
    {"command": "help",  "description": "Cómo usar este bot"},
    {"command": "order", "description": "Consultar un pedido"}
  ]
}

Translate descriptions, not command names. Command names are restricted to lowercase English letters, digits and underscores in every language, and keeping /order identical everywhere means one handler, consistent support documentation, and links that work for everyone. The same applies per scope: language-specific lists sit above the plain list at every level of the resolution order shown above.

Commands in groups: @botname and privacy mode

In a group with several bots, /help is ambiguous. Telegram's convention is the suffixed form /help@your_bot, which the docs list as a command "explicitly meant" for that bot. Your parser should accept both forms and should ignore commands addressed to a different bot.

/order 8812            -> command "order", args "8812"
/order@your_bot 8812   -> same, explicitly addressed to you
/order@other_bot 8812  -> not for you, ignore

Privacy mode decides which of those messages reach you at all. It is on by default, and a bot in privacy mode receives, per the docs:

  • commands explicitly meant for it, such as /command@this_bot;
  • general commands such as /start, if this bot was the last bot to send a message to the group;
  • inline messages sent via the bot, and replies to messages meant for it;
  • plus, regardless of privacy mode, all service messages.

So a bare /help in a busy group with other bots may never arrive. Bots added as administrators receive all messages. Disabling privacy mode with BotFather's /setprivacy also works, but the change only takes effect after the bot is removed and re-added to the group, a step that accounts for many "it works in DMs but not in my group" reports covered in why a Telegram bot is not responding.

Ephemeral commands

Bot API 10.2 (July 2026) added an optional is_ephemeral field to BotCommand. When a command is declared ephemeral, the user's message invoking it is delivered to your bot but stays invisible to other group members and other bots, so someone can run /balance in a public group without broadcasting it. Bots can answer with ephemeral messages visible only to that user. The details and timing rules are in our Bot API 10 breakdown.

A command setup checklist

  1. Handle /start, /help and, if you have settings, /settings. Make /start work with and without a payload.
  2. Name commands with lowercase letters, digits and underscores, 32 characters or fewer, and make each one specific.
  3. Set the default list, then narrower lists only where the audience truly differs. Repeat shared commands in every list, because lists do not merge.
  4. Add language_code lists for translated descriptions, keeping command names identical.
  5. Set lists from a deploy script with setMyCommands, and verify with getMyCommands for each scope.
  6. Enforce permissions in the handler; scopes only hide menu entries.
  7. Parse /cmd@your_bot and ignore commands addressed to other bots.
  8. Decide deliberately between the commands menu button and a Mini App button.

Message length, callback data, polling and request ceilings that commands run into are collected on the Telegram limits page, and any error string a command handler hits is explained in the Bot API error codes guide. If you would rather design the conversation than the command router, Conferbot's Telegram integration builds flows visually on top of the same Bot API.

Share this article:

Was this article helpful?

Ready to build your chatbot?

Join the businesses. Deploy on website, WhatsApp, and 11 more channels in minutes. Free forever plan available.

No credit cardNo coding13+ channels
Start Building Free

Get chatbot insights delivered weekly

Join 5,000+ professionals getting actionable AI chatbot strategies, industry benchmarks, and product updates.

🎯Automate this with a free chatbot

Build and deploy in 10 minutes. No coding needed.

❓FAQ

Telegram Bot Commands FAQ

Everything you need to know about chatbots for telegram bot commands.

🔍
Popular:

Send /setcommands to @BotFather, choose your bot, and send the full list in one message with one command per line in the format "command - description", without the leading slash. Alternatively call the Bot API method setMyCommands with a JSON array of objects containing command and description. Both replace the existing list rather than appending, so always send the complete set.

A registered command must be 1-32 characters long and can contain only lowercase English letters, digits and underscores. Hyphens, spaces, capital letters and non-Latin characters in the command name are rejected. The description is separate, can be 1-256 characters, and can be written in any language, which is where localization belongs.

setMyCommands accepts at most 100 commands per list. Because a list is stored per scope and per language code, a bot can show different sets of up to 100 commands to private chats, groups, administrators or specific chats, and per language. In practice menus with more than a dozen entries are hard to scan on a phone, so most bots keep the visible list short.

BotCommandScope tells setMyCommands which users a command list applies to. There are seven types: default, all_private_chats, all_group_chats, all_chat_administrators, chat, chat_administrators and chat_member. Telegram picks the first list that is set when walking from the narrowest scope to the default, and lists never merge, so shared commands must be repeated in every list.

Check getMyCommands with the same scope and language you set; a list set for one scope is invisible elsewhere. Confirm a narrower list is not shadowing yours, because Telegram shows only the first matching list. Also confirm the menu button has not been switched to a Mini App with setChatMenuButton. Also check that you are testing with the account, chat type and app language the list targets.

Call deleteMyCommands with the scope and language_code of the list you want removed. With no arguments it deletes only the default list. After deletion, affected users see the next broader list in the resolution order, or no list at all. You can also replace the list by sending a new, shorter one with /setcommands or setMyCommands.

Call setChatMenuButton with a menu_button object of type commands, web_app or default. Omit chat_id to change the bot's default button for all private chats, or pass a chat_id to override it for one user. A web_app button needs text and a web_app object with the Mini App URL. getChatMenuButton returns the current setting.

Append ?start=value to the bot link, as in https://t.me/your_bot?start=promo42, and your bot receives the message /start promo42. The value may use A-Z, a-z, 0-9, underscore and hyphen, up to 64 characters; base64url is recommended for binary data. For groups, ?startgroup=value lets the user add the bot to a group and delivers /start@your_bot value.

Privacy mode is on by default, so the bot only receives commands explicitly addressed to it, such as /help@your_bot, general commands if it was the last bot to post, and replies to its messages. Make the bot an administrator, or disable privacy with /setprivacy in BotFather and then remove and re-add the bot, because the setting only applies after re-adding.

No. Scopes only control which commands appear in a user's menu. Telegram's documentation notes that updates contain no information about scope and may include commands your bot never registered. Anyone can type an admin command by hand, so your handler must check the sender's rights, for example with getChatMember, before executing a privileged action.

About the Author

Content & Engineering

The Conferbot team writes about building, deploying, and improving AI chatbots.

View all articles
Skip the blank canvas
Start from one of 250+ free chatbot templates for lead generation, support, e-commerce, and 20+ industries - customize and launch in minutes.
Browse free templates

Related Articles

From the reference shelf

Fact-checked reference pages and free tools for the platform this article covers.

Omnichannel Platform

One Chatbot,
Every Channel

Your chatbot works seamlessly across WhatsApp, Messenger, Slack, and 6 more platforms. Build once, deploy everywhere.

View All Channels
Conferbot
online
Hi! How can I help you today?
I need pricing info
Conferbot
Active now
Welcome! What are you looking for?
Book a demo
Sure! Pick a time slot:
#support
Conferbot
New ticket from Sarah: "Can't access dashboard"
Auto-resolved. Password reset link sent.