Inline vs Reply Keyboard in Telegram Bots: When to Use Each
Basics4 minInnovialabs editorial team
In short
A reply keyboard replaces the phone keyboard and sends text as the user, so use it for a persistent main menu; inline buttons are attached to a message and silently pass callback data, so use them for actions on that message.
The key difference
Telegram bots have two kinds of buttons, and they behave in fundamentally different ways.
- A reply keyboard (
ReplyKeyboardMarkup) appears in place of the phone keyboard. Tapping a button sends its text to the chat as the user, as if they had typed it. - An inline keyboard (
InlineKeyboardMarkup) is attached to a specific bot message. Tapping it writes nothing to the chat: the bot receives a callback query with hiddencallback_dataand can update that same message.
The simple rule: reply keyboards for persistent navigation, inline keyboards for actions in the context of a message.
Reply keyboard: options and limits
Useful options:
resize_keyboardfits button height to content; without it buttons are oversized.one_time_keyboardhides the keyboard after a tap,is_persistentkeeps it visible.input_field_placeholdershows a hint in the input field.- Special buttons can request the user's contact, location or open a Mini App.
- Send
ReplyKeyboardRemoveto remove the keyboard.
Downsides: every tap adds a duplicate-looking message to the chat, and the bot receives plain text it has to match against strings. Rename a button or add a translation and old handlers break.
Inline keyboard: options and limits
Inline button types include:
callback_datato pass data to the bot (up to 64 bytes);urlto open a link;web_appto open a Mini App;switch_inline_queryto start the bot's inline mode in another chat;payfor a payment button on an invoice;copy_textto copy text to the clipboard.
The main rule: for every callback query the bot must call answerCallbackQuery, otherwise the user sees a loading indicator on the button. That call can also show a short notification or an alert.
An inline keyboard in aiogram 3:
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
kb = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Details", callback_data="item:42:info")],
[InlineKeyboardButton(text="Add to cart", callback_data="item:42:add")],
])
The 64-byte limit means callback_data should hold a short identifier, not a JSON payload. The bot loads everything else from its database.
Commands and the menu button
Two more navigation elements sit outside keyboards:
- Commands (
/start,/help,/catalog) are set via BotFather or thesetMyCommandsmethod. The list can differ by language and chat type. - The menu button to the left of the input field. With
setChatMenuButtonit either shows the command list or opens a Mini App.
For most bots a good combination is commands to enter main sections and inline buttons to work inside a section.
UX rules for clean navigation
- Edit, don't multiply. When moving through an inline menu, update the current message with
editMessageTextinstead of sending a new one. - Two or three buttons per row at most. Long labels get cut off on phones.
- Always provide a way out: "Back" and "Main menu" buttons.
- Don't mix without reason a large reply keyboard and inline buttons on one screen; users won't know where to tap.
- Confirm actions with a brief
answerCallbackQuerynotification instead of a separate message. - Handle old messages. Users may tap a week-old button; the bot should respond gracefully that the action has expired.
Which one to use
| Task | Best option |
|---|---|
| Main menu that is always at hand | reply keyboard or menu button |
| Asking for phone number or location | reply button with a special type |
| Catalog, pagination, filters | inline buttons |
| "Yes / No" confirmation | inline buttons |
| Opening a website or Mini App | inline url or web_app button |