Создание интерактивного бота с кнопками

Иван Корнев·14.04.2026·5 мин

Чтобы создать Telegram-бота и добавить кнопки, нужно зарегистрировать его через @BotFather, получить токен и написать код на выбранном языке (чаще всего Python), где для отправки сообщений используется параметр reply_markup. Существует два типа кнопок: Reply (отправляют текст в чат) и Inline (работают внутри сообщения через callback или ссылки). Весь процесс занимает от 15 минут до часа в зависимости от сложности логики.

Подготовка и регистрация в BotFather

Первый шаг — создание самого бота. Это делается исключительно через официального представителя Telegram — аккаунт @BotFather.

  1. Найдите в поиске Telegram пользователя @BotFather и запустите диалог.
  2. Отправьте команду /newbot.
  3. Бот попросит ввести имя (Name) — это то, что будут видеть пользователи (например, «Мой Магазин»).
  4. Затем потребуется ввести юзернейм (Username). Он должен быть уникальным, латиницей и обязательно заканчиваться на bot (например, my_shop_bot).
  5. Если имя свободно, BotFather пришлет длинный строковый ключ — токен.

Никогда не публикуйте токен в открытом доступе (на GitHub, в чатах, на форумах). Токен дает полный доступ к управлению ботом. Храните его в переменных окружения или защищенных конфигурационных файлах.

После получения токена бот технически создан, но пока он «пустой» и не реагирует на сообщения. Для оживления нужна программа-сервер.

Типы клавиатур: когда и какие использовать

Telegram предлагает два принципиально разных механизма взаимодействия через кнопки. Выбор зависит от задачи.

Reply-клавиатура (Ответная)

Кнопки отображаются вместо обычной клавиатуры смартфона. При нажатии в чат отправляется текстовое сообщение с названием кнопки.

  • Для чего подходит: Простые меню («Контакты», «О нас»), замена ручного ввода, опросы, где ответ должен остаться в истории переписки.
  • Особенность: Пользователь может легко переключиться на обычную клавиатуру, если нажмет крестик. Кнопки «прилипают» к полю ввода, пока вы явно не уберете их.

Inline-клавиатура (Встроенная)

Кнопки прикреплены непосредственно к сообщению бота. Они выглядят аккуратнее и работают «под капотом».

  • Для чего подходит: Навигация по меню, пагинация (страницы 1, 2, 3...), подтверждение действий («Купить», «Удалить»), переходы по ссылкам без спама в чате.
  • Особенность: При нажатии сообщение не дублируется в чат. Бот получает скрытый сигнал (callback_data) и может отредактировать исходное сообщение или ответить новым. Также поддерживаются прямые ссылки (url).

Для современных сервисных ботов (магазины, поддержка, сервисы) почти всегда лучше использовать Inline-кнопки. Они создают более профессиональный интерфейс и не засоряют историю чата техническими сообщениями.

Реализация на Python с библиотекой Aiogram

Самый популярный стек для разработки — язык Python и асинхронная библиотека aiogram (актуальная версия 3.x). Она обеспечивает высокую скорость работы и простоту кода.

Установка зависимостей

В терминале выполните команду:

pip install aiogram

Пример кода с Inline-кнопками

Ниже представлен готовый шаблон бота, который приветствует пользователя и показывает меню с двумя типами действий: открытие сайта и внутренняя навигация.

import asyncio
from aiogram import Bot, Dispatcher, F, Router
from aiogram.types import Message, CallbackQuery
from aiogram.utils.keyboard import InlineKeyboardBuilder
from aiogram.fsm.storage.memory import MemoryStorage

# Вставьте сюда ваш токен от BotFather
TOKEN = "YOUR_BOT_TOKEN"

bot = Bot(token=TOKEN)
dp = Dispatcher(storage=MemoryStorage())
router = Router()

# Создаем конструктор клавиатуры
def get_main_keyboard():
    builder = InlineKeyboardBuilder()
    # Кнопка с переходом на сайт
    builder.button(text="🌐 Наш сайт", url="https://example.com")
    # Кнопка с обратным вызовом (внутренняя логика)
    builder.button(text="📦 Каталог", callback_data="catalog_open")
    # Выстраиваем кнопки по одной в ряд
    builder.adjust(1) 
    return builder.as_markup()

@router.message(F.text == "/start")
async def cmd_start(message: Message):
    await message.answer(
        "Привет! Выберите действие:",
        reply_markup=get_main_keyboard()
    )

@router.callback_query(F.data == "catalog_open")
async def process_catalog(callback: CallbackQuery):
    # Отвечаем на нажатие, чтобы убрать индикатор загрузки
    await callback.answer("Загружаю каталог...") 
    # Редактируем сообщение или отправляем новое
    await callback.message.edit_text("Здесь будет список товаров.")

# Подключаем роутер к диспетчеру
dp.include_router(router)

async def main():
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())

Разбор ключевых моментов

  1. InlineKeyboardBuilder: Удобный инструмент для сборки кнопок. Метод adjust(1) выстраивает их в один столбец. Можно передать adjust(2, 2, 1) для сложной сетки.
  2. callback_data: Строка, которую бот получит при нажатии. Максимальная длина — 64 байта. В ней часто кодируют ID товара или название действия.
  3. callback.answer(): Обязательный метод. Если его не вызвать, у пользователя на телефоне будет бесконечно крутиться значок загрузки рядом с кнопкой.

Обработка нажатий и логика меню

Главное отличие обработки Inline-кнопок от обычных команд — использование хендлера callback_query.

Когда пользователь нажимает кнопку:

  1. Бот получает объект CallbackQuery.
  2. Вы проверяете поле data (то, что вы зашили в callback_data).
  3. Выполняете действие: меняете текст сообщения (edit_text), удаляете кнопки, отправляете фото или формируете ответное сообщение.

Лайфхак для навигации: Чтобы сделать кнопку «Назад», просто передайте в callback_data специальное значение (например, back_to_main). В обработчике проверьте это значение и вызовите функцию генерации главного меню, обновив текущее сообщение.

Если вы используете Reply-кнопки, логика проще: бот получает обычное текстовое сообщение. Вам нужно лишь сравнить текст сообщения с ожидаемым названием кнопки через условие if message.text == "Каталог":.

Частые ошибки разработчиков

Даже опытные разработчики иногда допускают типовые промахи при работе с интерфейсом ботов.

ОшибкаПоследствиеКак исправить
Отсутствие answer() на callbackУ пользователя висит «вечная загрузка» (часики) у кнопки.Всегда вызывайте await callback.answer() в начале обработчика.
Хардкод токена в кодеУтечка доступа при публикации кода на GitHub.Используйте .env файлы и библиотеку python-dotenv.
Путаница типов кнопокПопытка получить callback_data от Reply-кнопки (её там нет).Помните: Reply шлет текст в чат, Inline шлет скрытый запрос.
Длинный callback_dataКнопка не создается или работает некорректно.Лимит данных — 64 байта. Используйте сокращения или ID.
Неуникальный юзернеймBotFather не создает бота.Username должен быть свободен во всем Telegram и оканчиваться на bot.

FAQ

Можно ли добавить картинку к кнопке? Нет, в стандартном API Telegram нельзя разместить иконку прямо на кнопке. Кнопка содержит только текст и эмодзи. Однако вы можете отправить картинку сообщением, а под ней разместить Inline-клавиатуру.

Как сделать кнопку, которая просит номер телефона? Это возможно только через Reply-клавиатуру. Нужно передать специальный параметр request_contact=True. Inline-кнопки не умеют запрашивать личные данные пользователя напрямую.

Бот не видит нажатия на кнопки, что делать? Проверьте, правильно ли вы подключили роутер с хендлером callback_query к диспетчеру (dp.include_router). Также убедитесь, что строка в callback_data при создании кнопки и в условии фильтра (F.data == ...) совпадает до символа.

Можно ли редактировать сообщение с кнопками? Да, это основная фишка Inline-режима. Метод edit_message_text позволяет изменить текст и набор кнопок в уже отправленном сообщении, создавая эффект перехода по экранам без новой переписки.