Создать чат бота в Telegram на Python: пошаговый гайд

ИнструментыИгорь Мельник11 мин чтения
Создать чат бота в Telegram на Python: пошаговый гайд

Если задача звучит как «создать чат бота», а бот должен принимать заявки, отвечать по правилам и жить на сервере без вас, конструктор упрётся в потолок, а код на Python нет. Ниже весь путь: токен у BotFather, библиотека, первый хендлер, кнопки, анкета на состояниях, вызов внешней модели, переход с long polling на вебхук, лимиты Bot API и выкладка на сервер. Версии и ограничения сверены с официальной документацией 21 августа 2026 года.

Что закрывает бот на Python и где проходит граница

Бот в Telegram это клиент Bot API: всё, что он умеет, описано методами API. Текущая версия Bot API 10.2 от 14 июля 2026 года, и она задаёт рамки проекта ещё до первой строки кода. Границы, о которые бьётся первый рабочий бот:

  • Текст одного сообщения в методе sendMessage: от 1 до 4096 символов после разбора разметки. Длинный ответ придётся резать на части самому.
  • Подпись к фото и другим медиа: 0-1024 символа. Всё остальное уходит отдельным сообщением.
  • Отправка файла через multipart: до 50 МБ, фото до 10 МБ. По HTTP-ссылке Telegram заберёт до 20 МБ и до 5 МБ для фото.
  • Скачивание файла ботом через getFile: не более 20 МБ, ссылка живёт минимум час.
  • Удалить сообщение методом deleteMessage можно, только если оно отправлено меньше 48 часов назад.

Эти цифры определяют интерфейс: длинные ответы разбиваются на экраны, тяжёлые документы отдаются ссылкой на хранилище, а «отменить отправленное вчера» технически невозможно.

Токен у BotFather: что вы получаете и как его хранить

Бот создаётся не в коде, а в диалоге с @BotFather. Команда /newbot запрашивает отображаемое имя и username, который обязан заканчиваться на bot, после чего выдаёт токен. Это единственный фактор аутентификации: токен подставляется прямо в URL запроса вида api.telegram.org/bot<token>/methodName. Отсюда три правила:

  • Токен не хранится в файле с кодом. Переменная окружения или .env, который добавлен в .gitignore до первого коммита.
  • Утёкший токен отзывается там же, командой /revoke в BotFather. Старый перестаёт работать сразу.
  • Список команд бота задаётся не в коде интерфейса, а методом setMyCommands или командой /setcommands: не более 100 команд, каждая от 1 до 32 символов, только строчные латинские буквы, цифры и подчёркивание.

Окружение и выбор библиотеки: aiogram, pyTelegramBotAPI, python-telegram-bot

Актуальная стабильная версия языка на момент подготовки материала Python 3.14.7 от 5 августа 2026 года. Все три живые библиотеки требуют минимум Python 3.10, так что версия из системного репозитория пятилетней давности не подойдёт.

Библиотека Версия и дата Требования Модель работы
aiogram 3.30.0, 17 июля 2026 Python 3.10-3.14 Асинхронная, роутеры, встроенный FSM
pyTelegramBotAPI (telebot) 4.36.1, 13 августа 2026 Python 3.10+ Синхронная, есть async-ветка
python-telegram-bot 22.8, 12 июня 2026 Python 3.10+ Асинхронная, ConversationHandler

Порядок подготовки одинаковый для любой из трёх: python -m venv venv, активация окружения, установка пакета через pip, фиксация зависимостей в requirements.txt. Последний пункт не формальность: без него бот, поднятый на сервере через полгода, соберётся с другой минорной версией и упадёт на импорте. Дальше примеры описаны на aiogram: у него строгая структура проекта, а асинхронность понадобится в тот же день, когда бот пойдёт во внешние API.

Минимальный каркас бота на aiogram

Рабочий каркас это четыре объекта и один цикл.

  1. Bot, которому передан токен из переменной окружения. Он умеет только вызывать методы API.
  2. Dispatcher, который принимает объекты Update и раздаёт их дальше.
  3. Router, куда регистрируются хендлеры. Роутеры вкладываются друг в друга, поэтому логика режется по файлам: команды, анкета, админка.
  4. Хендлер, обычная асинхронная функция с декоратором фильтра, например по команде start.

Запуск в разработке делается вызовом start_polling у диспетчера внутри asyncio.run. Проверка живости бота отдельным методом getMe: если он вернул объект с username, токен корректен и сеть до api.telegram.org есть. Это первое, что стоит выполнить при любой ошибке запуска, чтобы отделить проблему кода от проблемы окружения.

Кнопки, команды и callback-запросы

Клавиатур в Bot API две. ReplyKeyboardMarkup подменяет системную клавиатуру и отправляет обычный текст: бот получает строку и не отличает её от набранной руками. InlineKeyboardMarkup живёт под конкретным сообщением и присылает объект CallbackQuery.

Технические ограничения инлайн-кнопок:

  • Поле callback_data вмещает от 1 до 64 байт. В кириллице это примерно 32 символа, поэтому в кнопку кладут короткий идентификатор, а не название товара.
  • На каждый CallbackQuery обязателен ответ методом answerCallbackQuery. Без него у пользователя висит индикатор загрузки на кнопке, пока клиент не сбросит его сам.
  • Всплывающее уведомление у ответа на callback короткое, при необходимости показывается как alert поверх экрана.

Если ответ готовится дольше секунды, до отправки вызывается sendChatAction. Статус набора текста держится 5 секунд или меньше и сбрасывается, как только бот пришлёт сообщение, поэтому при долгой операции вызов повторяют.

Анкета через FSM: состояния и хранилище

Бот не помнит контекст сам: каждый апдейт приходит отдельно. Чтобы собрать имя, телефон и услугу тремя сообщениями, нужна машина состояний. В aiogram она встроена: класс на базе StatesGroup описывает шаги, хендлер фильтруется по состоянию, промежуточные данные лежат в FSMContext.

Ключевой выбор здесь не синтаксис, а хранилище состояний. MemoryStorage держит всё в оперативной памяти процесса: перезапуск бота, и половина пользователей зависла на шаге «введите телефон» без возможности продолжить. Внешнее хранилище вроде Redis переживает рестарт и обязательно, если процесс запускается больше чем в одном экземпляре.

Что закладывается в анкету сразу, чтобы не переделывать:

  • Валидация на каждом шаге: телефон проверяется регулярным выражением.
  • Кнопка отмены, доступная в любом состоянии, и обработчик, чистящий контекст.
  • Запрос номера отдельной кнопкой запроса контакта: так номер приходит от клиента Telegram, а не набирается вручную с опечатками.

Искусственный интеллект в чат-боте: вызов модели из хендлера

Когда в сценарии появляется искусственный интеллект, чат перестаёт быть детерминированным: ответ приходит от внешнего HTTP API за непредсказуемое время. С точки зрения кода бота это обычный асинхронный запрос, и вся сложность в таймаутах.

Библиотека aiohttp, на которой работает aiogram, по умолчанию даёт общий таймаут 300 секунд на всю операцию. Для бота это неприемлемо: пользователь уйдёт из чата на второй минуте, а хендлер продолжит удерживать соединение. Практика простая.

  • Свой ClientTimeout на каждый запрос к модели, разумный потолок несколько десятков секунд.
  • Перед запросом sendChatAction, чтобы в чате был виден статус набора, и повтор вызова каждые 5 секунд при долгом ответе.
  • Ветка на исключение по таймауту с человеческим текстом и повторной попыткой, а не молчание бота.
  • Ответ модели режется под лимит sendMessage в 4096 символов до отправки, иначе API вернёт ошибку на длинном ответе.
  • Клиентская сессия создаётся один раз на жизнь процесса, а не в каждом хендлере.

Выбор самой модели, промпт роли, база знаний и эскалация на оператора это отдельная тема: подробный разбор в материале о том, как создать чат-бота на нейросети. Здесь важно только то, что со стороны Python это ещё один вызов внешнего сервиса, который обязан быть обёрнут в таймаут.

Long polling или вебхук: как бот получает апдейты

Способов доставки апдейтов ровно два, и переключение между ними это одна строка в коде плюс настройки инфраструктуры.

Long polling через getUpdates: процесс сам опрашивает Telegram. Параметр limit принимает значения от 1 до 100, по умолчанию 100. Параметр timeout по умолчанию 0, то есть короткий опрос, который документация прямо рекомендует использовать только для тестов. В продакшене ставится положительный timeout, иначе процесс молотит запросы вхолостую.

Вебхук через setWebhook: Telegram сам присылает POST на ваш адрес. Требования жёсткие.

  • Только HTTPS. Поддерживаются порты 443, 80, 88 и 8443, других нет.
  • Параметр max_connections задаёт число одновременных соединений от 1 до 100, по умолчанию 40.
  • Параметр secret_token от 1 до 256 символов из набора A-Z, a-z, 0-9, подчёркивание и дефис. Telegram добавит его в заголовок X-Telegram-Bot-Api-Secret-Token, и ваш обработчик обязан этот заголовок проверять. Без проверки endpoint принимает апдейты от кого угодно.
  • Параметр drop_pending_updates сбрасывает накопленную очередь при переключении, иначе после простоя бот разом ответит на все старые сообщения.
  • Состояние доставки смотрится методом getWebhookInfo: он возвращает last_error_message и last_error_date. Это первое место, куда идут при жалобе «бот молчит».

Правило выбора: разработка и внутренний бот на десятки пользователей это long polling, публичный бот с уведомлениями и нагрузкой это вебхук за уже имеющимся HTTPS-доменом.

Лимиты Bot API и ошибка 429

Рассылка это то место, где первый бот получает бан на отправку. Официальные ориентиры из FAQ Telegram:

  • В один чат не чаще одного сообщения в секунду. Короткие всплески допускаются, но на длинной дистанции лимит соблюдается.
  • В одну группу не более 20 сообщений в минуту.
  • Массовая рассылка около 30 сообщений в секунду суммарно.

Превышение возвращает ошибку 429, а в объекте ResponseParameters приходит поле retry_after с числом секунд ожидания. Обработчик обязан читать это поле и засыпать ровно на указанное время, а не повторять запрос немедленно.

Платные рассылки поднимают потолок до 1000 сообщений в секунду: каждое сообщение сверх бесплатных 30 в секунду стоит 0,1 Telegram Stars. Порог входа отсекает почти всех: нужно не менее 100 000 Stars на балансе и не менее 100 000 активных пользователей в месяц. Для обычного проекта вывод такой: рассылка на 10 000 подписчиков при 30 в секунду займёт около 6 минут и делается очередью, а не циклом for.

Бот перерос вечерний проект

Токен, хендлер и кнопки собираются за вечер. Очередь рассылки с учётом retry_after, вебхук с проверкой секретного заголовка, внешнее хранилище состояний и мониторинг падений это уже недели работы. Мы разрабатываем и сопровождаем Telegram-ботов под задачу: от анкеты с выгрузкой в вашу систему до сценариев с вызовом моделей.

Обсудить задачу

Выкладка на сервер: systemd, Docker и логи

Бот, запущенный командой в терминале, умирает вместе с SSH-сессией. Рабочих схем две.

Первая, systemd-юнит на VPS. Директива Restart=always поднимает процесс после любого завершения, RestartSec по умолчанию 100 мс. Деталь, о которую спотыкаются: перезапуск ограничен рейт-лимитом, по умолчанию 5 попыток за 10 секунд (DefaultStartLimitBurst равен 5, DefaultStartLimitIntervalSec равен 10 с). Бот, падающий на старте из-за неверного токена, через полсекунды окажется в состоянии failed и не поднимется, пока не выполните systemctl reset-failed. Поэтому RestartSec выставляют в несколько секунд.

Вторая схема, контейнер с политикой restart unless-stopped: зависимости зафиксированы образом, Redis и база поднимаются рядом одним файлом compose.

Что настраивается до первого пользователя:

  • Логи через модуль logging с уровнем INFO в journald или файл. Print это не логи.
  • Секреты в переменных окружения юнита или в env-файле с правами 600.
  • Один экземпляр процесса. Два запущенных polling-процесса с одним токеном дают ошибку 409 Conflict: getUpdates разрешён только одному потребителю.

Чек-лист запуска и ошибки, на которых спотыкается первый бот

  1. Получить токен у @BotFather, сразу задать команды через setMyCommands.
  2. Поставить Python не ниже 3.10, создать venv, зафиксировать requirements.txt.
  3. Вынести токен в переменную окружения и добавить .env в .gitignore.
  4. Собрать каркас: Bot, Dispatcher, Router, хендлер команды start, проверка через getMe.
  5. Добавить инлайн-кнопки с коротким callback_data и обязательным answerCallbackQuery.
  6. Сделать анкету на FSM с валидацией и внешним хранилищем состояний.
  7. Обернуть каждый внешний запрос своим таймаутом.
  8. Реализовать обработку 429 с чтением retry_after и очередь для рассылок.
  9. Развернуть на сервере с автоперезапуском и логами, RestartSec выставить вручную.
  10. Перевести на вебхук с проверкой secret_token, когда появится домен и нагрузка.

Ошибки, которые встречаются чаще прочих: токен в коде и утечка через публичный репозиторий; две копии бота и постоянный 409; синхронный блокирующий вызов внутри асинхронного хендлера, который останавливает весь бот; отправка ответа длиннее 4096 символов без нарезки; отсутствие ответа на callback и вечный индикатор на кнопке; попытка удалить сообщение старше 48 часов.

Частые вопросы

Какая версия Python нужна для бота в 2026 году

Не ниже 3.10: этого требуют все три живые библиотеки. aiogram 3.30.0 объявляет поддержку диапазона от 3.10 до 3.14 включительно, pyTelegramBotAPI 4.36.1 и python-telegram-bot 22.8 требуют 3.10 и выше. Актуальная стабильная версия языка 3.14.7 от 5 августа 2026 года.

Сколько сообщений в секунду можно рассылать

По умолчанию около 30 сообщений в секунду суммарно, не чаще одного в секунду в один чат и не более 20 в минуту в одну группу. При превышении API возвращает 429 с полем retry_after. Потолок 1000 сообщений в секунду доступен только через платные рассылки: 0,1 Stars за каждое сообщение сверх 30 в секунду и порог в 100 000 Stars на балансе.

Можно ли писать бота на телефоне

Технически да: официальные сборки Termux распространяются через GitHub и F-Droid, внутри ставится Python и pip. Для постоянной работы это не годится: телефон уходит в сон, процесс убивается системой.

Обязателен ли домен и HTTPS

Для long polling нет, для вебхука да: setWebhook принимает только HTTPS-адреса и работает по портам 443, 80, 88 и 8443. Пока бота используют десятки человек, long polling с положительным параметром timeout закрывает задачу полностью.

Что делать, если бот перестал отвечать

Порядок проверки занимает три минуты. Вызов getMe отвечает на вопрос, жив ли токен и есть ли сеть. Для вебхука getWebhookInfo показывает last_error_message и last_error_date с причиной отказа доставки. Дальше смотрят логи процесса: 409 Conflict означает вторую запущенную копию, 429 означает упор в лимит рассылки.

Поделиться:

About Author: Игорь Мельник

nu_editor_melnik@neurounit.ai

Редактор Neurounit. Пишет про автоматизацию, разработку и внедрение AI в процессы.

Neurounit

Запустить рост с AI

Оставьте заявку или напишите в мессенджер