Skip to content

setChatMenuButton

Returns: TrueOfficial docs ↗

Use this method to change the bot's menu button in a private chat, or the default menu button. Returns True on success.

Parameters

chat_idIntegerOptional
Unique identifier for the target private chat. If not specified, default bot's menu button will be changed
menu_buttonMenuButtonOptional
A JSON-serialized object for the bot's new menu button. Defaults to MenuButtonDefault

Returns

On success, True is returned.

GramIO Usage

ts
// Show the "Menu" button that opens the commands list (default Telegram behavior)
await 
bot
.
api
.
setChatMenuButton
({
chat_id
: 123456789,
menu_button
: {
type
: "commands" },
});
ts
// Launch a Web App from the menu button for a specific private chat
await 
bot
.
api
.
setChatMenuButton
({
chat_id
: 123456789,
menu_button
: {
type
: "web_app",
text
: "Open App",
web_app
: {
url
: "https://my-mini-app.example.com" },
}, });
ts
// Change the default menu button for ALL private chats (no chat_id)
await 
bot
.
api
.
setChatMenuButton
({
menu_button
: {
type
: "web_app",
text
: "Launch",
web_app
: {
url
: "https://my-mini-app.example.com" },
}, });
ts
// Reset the menu button to Telegram's default for a specific user
await 
bot
.
api
.
setChatMenuButton
({
chat_id
: 123456789,
menu_button
: {
type
: "default" },
});
ts
// Set Web App button when user starts the bot, then confirm
bot
.
command
("start", async (
ctx
) => {
await
bot
.
api
.
setChatMenuButton
({
chat_id
:
ctx
.
from
?.
id
,
menu_button
: {
type
: "web_app",
text
: "Open Dashboard",
web_app
: {
url
: "https://my-mini-app.example.com" },
}, }); await
ctx
.
send
("Menu button configured! Tap the button below.");
});

Errors

CodeErrorCause
400Bad Request: chat not foundInvalid or inaccessible chat_id — ensure it's a valid private chat ID
400Bad Request: BUTTON_USER_PRIVACY_RESTRICTEDUser has restricted who can show them Web App buttons
400Bad Request: chat type is not supportedchat_id points to a group/channel — this method only works for private chats

Tips & Gotchas

  • Private chats only. chat_id must be a private chat (individual user). Groups and channels are not supported — passing a group or channel ID returns an error.
  • Omit chat_id for the global default. When chat_id is omitted, the button is set as the default for all users who don't have a per-chat override. Per-chat buttons always take priority over the default.
  • Three button types available. "commands" shows the command menu, "web_app" opens a Mini App URL with custom button text, and "default" resets to Telegram's built-in behavior (usually shows "Menu").
  • "web_app" requires text and web_app.url. The text field is the label shown on the button (up to ~512 chars); the URL must be HTTPS and must be an allowed domain for the bot.
  • Use getChatMenuButton to read the current state before overwriting, in case you want to restore it later.
  • Per-user customization pattern. Call setChatMenuButton in a bot.command("start", ...) handler to personalize the button experience for each user based on their state or role.

See Also