Как написать Telegram-бота на Python с pyTelegramBotAPI: от токена до сервера

Пишем Telegram-бота на Python с нуля: получаем токен у @BotFather, ставим pyTelegramBotAPI и запускаем эхо-бота.

Потом добавляем команды, кнопки и курс доллара от ЦБ, разбираем ошибки, из-за которых бот не отвечает, и переносим его на сервер. Весь код можно скопировать целиком.

Статью написал:
Ваня Буявец, продюсер, основатель Checkroi
Ваня Буявец
Основатель Checkroi, продюсер, эксперт в выборе онлайн-курсов
Все 3017 статей автора Подписаться на Телеграм-канал
Одобрено экспертом:
Наташа Буявец, основатель Checkroi, эксперт по онлайн-курсам
Наташа Буявец
Основательница Checkroi, продюсер Youtube-каналов, эксперт по онлайн-курсам
Все 3671 экспертное мнение Подписаться на Телеграм-канал
Обложка: Как написать Telegram-бота на Python с pyTelegramBotAPI: от токена до сервера

Чтобы написать Telegram-бота на Python, нужны три вещи: токен от @BotFather, библиотека pyTelegramBotAPI и файл bot.py на полтора десятка строк. Токен выдаёт сам Telegram за пару минут, библиотека ставится одной командой pip install pyTelegramBotAPI, а запускается бот командой python bot.py в терминале. Пока скрипт работает, бот отвечает в чате.

Ниже весь путь по шагам: от регистрации до кнопок, запроса во внешний API и запуска на сервере. Код рассчитан на Python 3.11 и новее и pyTelegramBotAPI 4.37.1. Если нужен бот без программирования, вам в соседнюю инструкцию по BotFather и настройке команд.

Что понадобится до начала

Рой пишет код Telegram-бота на ноутбуке

Шаг 1: получите токен у BotFather

Токен служит паролем: по нему ваш скрипт управляет ботом. Его выдаёт официальный бот Telegram @BotFather.

  1. Найдите в поиске Telegram @BotFather, проверьте написание имени до буквы и начните с ним чат.
  2. Отправьте команду /newbot.
  3. Введите имя бота. Его увидят в шапке чата, писать можно по-русски: «Курс и погода».
  4. Введите username, то есть адрес вида @kurs_pogoda_bot. Правила из документации Telegram: от 5 до 32 символов, только латиница, цифры и подчёркивание, в конце обязательно bot. Поменять username потом нельзя, имя можно.
  5. BotFather пришлёт токен вида 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw. Скопируйте его целиком, вместе с цифрами до двоеточия.

Токен никому не показывайте и не выкладывайте в открытый репозиторий: с ним любой может писать от имени вашего бота. Если токен утёк, отправьте BotFather команду /token: как сказано в справке по BotFather, она выпускает новый токен, его нужно вписать в .env.

Сайты документации Telegram из России открываются не всегда, поэтому главные правила мы переписали сюда.

Канал основателя Checkroi Вани Буявца3 700 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединиться

Шаг 2: создайте проект и установите библиотеку

Сделайте папку проекта и виртуальное окружение в ней. Окружение нужно, чтобы библиотеки бота не смешивались с другими проектами.

# macOS и Linux
mkdir tgbot && cd tgbot
python3 -m venv .venv
source .venv/bin/activate

# Windows (PowerShell)
mkdir tgbot; cd tgbot
python -m venv .venv
.venv\Scripts\Activate.ps1

# дальше одинаково
pip install pyTelegramBotAPI python-dotenv requests

Рядом с будущим bot.py создайте файл .env и положите туда токен:

BOT_TOKEN=110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw

Так токен не попадёт в код. Если будете хранить проект в Git, допишите строку .env в файл .gitignore.

Какую библиотеку выбрать

Библиотек для Telegram на Python три популярных. Для первого бота мы взяли самую простую по синтаксису:

Библиотека Как пишется код Кому подойдёт
pyTelegramBotAPI Обычные функции, есть и асинхронный вариант AsyncTeleBot Первый бот, учебные и небольшие проекты
aiogram Полностью асинхронный, на asyncio, Python 3.10+ Ботам с большой нагрузкой и сложными сценариями
python-telegram-bot Асинхронный интерфейс, Python 3.10+ Тем, кому нужны готовые сокращения и обёртки поверх Bot API

Асинхронность нужна, когда бот обслуживает много людей одновременно и не ждёт ответа на каждый запрос. Боту на десятки пользователей она ни к чему, а читать такой код новичку тяжелее.

Шаг 3: напишите эхо-бота

Рой радуется первому ответу своего бота

Эхо-бот повторяет всё, что ему пишут. На нём видно, как устроен любой бот: получил сообщение → выбрал обработчик → ответил. Создайте bot.py:

import os

import telebot
from dotenv import load_dotenv

load_dotenv()
bot = telebot.TeleBot(os.getenv("BOT_TOKEN"))


@bot.message_handler(commands=["start"])
def start(message):
    bot.send_message(message.chat.id, "Привет! Напишите что-нибудь, и я повторю")


@bot.message_handler(content_types=["text"])
def echo(message):
    bot.send_message(message.chat.id, message.text)


print("Бот запущен")
bot.infinity_polling()

Что здесь происходит:

  • load_dotenv() читает файл .env, а os.getenv("BOT_TOKEN") достаёт из него токен.
  • @bot.message_handler(...) называется декоратором. Он говорит библиотеке, какие сообщения отдавать функции под ним. Обработчики при этом остаются обычными функциями Python, объявленными через def. Первый ловит команду /start, второй любой текст.
  • message.chat.id хранит номер чата, куда отправлять ответ.
  • bot.infinity_polling() раз за разом спрашивает у Telegram, нет ли новых сообщений. По описанию в библиотеке, это опрос в бесконечном цикле с обработкой исключений, чтобы бот не останавливался из-за сбоя.

Запустите скрипт из папки проекта командой python bot.py. В терминале появится «Бот запущен», а в Telegram бот начнёт отвечать:

Вы:  /start
Бот: Привет! Напишите что-нибудь, и я повторю
Вы:  Привет, бот
Бот: Привет, бот

Остановить бота можно сочетанием Ctrl+C в терминале. Пока скрипт не запущен, бот не отвечает.

CheckroiCheckroiПодборка курсов по Python466 курсов • 48 школСравните цены, школы, программу и найдите выгодные предложения по обучениюСравнить→

Шаг 4: добавьте команды, кнопки и внешний API

Дальше расширяем того же бота. Приветствие теперь обращается к человеку по имени: его подставляет f-строка f"Привет, {message.from_user.first_name}!". Полный код в конце раздела, его можно скопировать целиком.

Меню команд

Чтобы при вводе «/» пользователь видел подсказки, список команд нужно зарегистрировать. Это делается командой /setcommands у BotFather или одной строкой из кода:

from telebot import types

bot.set_my_commands([
    types.BotCommand("start", "Начать"),
    types.BotCommand("help", "Подсказка"),
    types.BotCommand("site", "Ссылка на сайт"),
])

Telegram хранит список у себя, текущий отдаёт метод getMyCommands (документация Telegram из России открывается не всегда). Поэтому вызывать set_my_commands при каждом запуске не нужно, хватит одного раза после изменения списка.

Кнопки под полем ввода

ReplyKeyboardMarkup заменяет клавиатуру телефона набором кнопок. Нажатие кнопки отправляет её текст как обычное сообщение, поэтому ловится оно фильтром по тексту: func=lambda m: m.text == "Помощь".

Кнопки под сообщением

InlineKeyboardMarkup прикрепляет кнопки к конкретному сообщению. Кнопка бывает ссылкой (url=) или отправляет боту скрытые данные (callback_data=), их ловит callback_query_handler.

В обработчике нажатия обязательно вызывайте bot.answer_callback_query(call.id). По описанию CallbackQuery в Bot API, пока бот этого не сделал, приложение показывает на кнопке индикатор загрузки (страница документации из России открывается не всегда).

Запрос во внешний API: курс доллара

Бот умеет не только отвечать заготовками. Для примера возьмём официальный курс Банка России: ЦБ отдаёт его в формате XML по адресу cbr.ru/scripts/XML_daily.asp, ключ не нужен.

Библиотека requests скачивает ответ, а модуль xml.etree из стандартной поставки Python находит в нём доллар. Как вообще устроены такие запросы, мы разбирали в статье про API простыми словами.

Полный код бота

import os
import xml.etree.ElementTree as ET
from datetime import datetime

import requests
import telebot
from dotenv import load_dotenv
from telebot import types

load_dotenv()
bot = telebot.TeleBot(os.getenv("BOT_TOKEN"))


@bot.message_handler(commands=["start"])
def start(message):
    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    keyboard.add("Курс доллара", "Помощь")
    bot.send_message(
        message.chat.id,
        f"Привет, {message.from_user.first_name}! Я бот-попугай: повторю всё, что напишете.",
        reply_markup=keyboard,
    )


@bot.message_handler(commands=["help"])
@bot.message_handler(func=lambda m: m.text == "Помощь")
def help_command(message):
    bot.send_message(message.chat.id, "Команды: /start — начать, /help — подсказка, /site — ссылка на сайт")


@bot.message_handler(func=lambda m: m.text == "Курс доллара")
def usd_rate(message):
    try:
        response = requests.get("https://www.cbr.ru/scripts/XML_daily.asp", timeout=10)
        root = ET.fromstring(response.content)
        value = root.find("Valute[CharCode='USD']/Value").text
        text = f"Курс ЦБ на {root.get('Date')}: 1 $ = {value} ₽"
    except (requests.RequestException, ET.ParseError, AttributeError):
        text = "Сайт ЦБ сейчас не ответил, попробуйте через минуту"
    bot.send_message(message.chat.id, text)


@bot.message_handler(commands=["site"])
def site(message):
    markup = types.InlineKeyboardMarkup()
    markup.add(types.InlineKeyboardButton("Открыть сайт", url="https://checkroi.ru/"))
    markup.add(types.InlineKeyboardButton("Показать время", callback_data="time"))
    bot.send_message(message.chat.id, "Выберите действие:", reply_markup=markup)


@bot.callback_query_handler(func=lambda call: call.data == "time")
def show_time(call):
    bot.answer_callback_query(call.id)
    bot.send_message(call.message.chat.id, datetime.now().strftime("Сейчас %H:%M"))


@bot.message_handler(content_types=["text"])
def echo(message):
    bot.send_message(message.chat.id, message.text)


if __name__ == "__main__":
    print("Бот запущен")
    bot.infinity_polling()

Так бот ответил нам 21 октября 2026 года:

Вы:  /start
Бот: Привет, Аня! Я бот-попугай: повторю всё, что напишете.
     [Курс доллара] [Помощь]
Вы:  Курс доллара
Бот: Курс ЦБ на 21.10.2026: 1 $ = 82,8879 ₽
Вы:  /site
Бот: Выберите действие:
     [Открыть сайт]
     [Показать время]
     (нажатие «Показать время») → Сейчас 20:16

Порядок обработчиков важен. Библиотека проверяет их сверху вниз и отдаёт сообщение первому подходящему. Эхо-обработчик ловит любой текст, поэтому он стоит последним.

Блок try/except в usd_rate нужен на случай, если сайт ЦБ не ответил за 10 секунд: тогда бот пришлёт понятную фразу и продолжит работать.

CheckroiCheckroiПодборка курсов для Python-разработчиков83 курса • 32 школыСравните цены, школы, программу и найдите выгодные предложения по обучениюСравнить→

Почему бот не отвечает: ошибки по симптомам

Ниже ошибки, из-за которых первый бот обычно не запускается или не отвечает, с тем текстом, что пишет терминал.

Что видите Причина Что сделать
ModuleNotFoundError: No module named 'telebot' Библиотека установлена в другой Python, чаще всего не активировано окружение Активируйте .venv и поставьте библиотеку заново: python -m pip install pyTelegramBotAPI
TypeError: 'NoneType' object is not iterable на строке с TeleBot Токен не прочитался: нет файла .env или скрипт запущен из другой папки Запускайте из папки проекта, проверьте имя переменной BOT_TOKEN
ValueError: Token must contain a colon Скопирована только часть токена Скопируйте токен у BotFather заново, вместе с цифрами до двоеточия
Error code: 401. Description: Unauthorized Токен неверный: опечатка, лишний символ или токен от другого бота Возьмите актуальный токен в BotFather
ConnectTimeout или «Connection timed out» Компьютер или сервер не может связаться с api.telegram.org Проверьте связь командой ниже, код тут ни при чём
На /start бот отвечает «/start» Эхо-обработчик стоит выше остальных и забирает все сообщения Перенесите его в конец файла
В группе бот не видит обычные сообщения Режим приватности: по умолчанию бот в группе получает только команды и ответы себе Сделайте бота админом группы или выключите режим через /setprivacy у BotFather, после чего добавьте бота в группу заново
Бот работал, а после экспериментов перестал получать сообщения Для бота включён вебхук, а при нём опрос getUpdates не работает Вызовите bot.remove_webhook() перед infinity_polling()

Про режим приватности и вебхуки подробно написано в разделе Privacy Mode и в описании getUpdates. Оба раздела из России открываются не всегда, главное из них уже в таблице.

Проверить связь с Telegram

В феврале 2026 года Роскомнадзор объявил о замедлении Telegram в России, и с части машин api.telegram.org не отвечает. Проверьте это с того компьютера, где запускаете бота:

curl -sS -m 10 -o /dev/null -w '%{http_code}\n' https://api.telegram.org/

Ответ 302 значит, что связь есть и искать ошибку нужно в коде. curl: (28) Connection timed out значит, что эта машина до Telegram не достаёт и бот на ней работать не будет.

Ваня БуявецКанал основателя Checkroi Вани БуявцаЗабирайте промпты и обучение по нейросетям в моём Телеграм-каналеБольше 3 700 человек уже применяют Claude Code, ChatGPT и другие нейросети в работе, учёбе, бизнесе и жизниПерейти в канал

Как оставить бота работать без вашего компьютера

Маленький сервер, на котором бот работает круглосуточно

Бот живёт, пока работает скрипт. Закрыли ноутбук, и бот перестал отвечать. Сообщения при этом не теряются сразу: по разделу Getting updates в Bot API Telegram хранит их не дольше 24 часов (сайт документации из России открывается не всегда). Если запустите бота за это время, он их получит.

Чтобы бот отвечал круглосуточно, его переносят на сервер с Linux. Код туда удобно возить через Git, а файл .env с токеном создать прямо на сервере. Дальше скрипт оформляют как службу systemd, тогда он сам перезапустится после сбоя или перезагрузки.

  1. Заведите на сервере отдельного пользователя bot, скопируйте проект в /home/bot/tgbot, создайте там окружение и поставьте библиотеки, как в шаге 2.
  2. Создайте файл /etc/systemd/system/tgbot.service:
    [Unit]
    Description=Telegram bot
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    User=bot
    WorkingDirectory=/home/bot/tgbot
    ExecStart=/home/bot/tgbot/.venv/bin/python bot.py
    Restart=always
    RestartSec=5
    
    [Install]
    WantedBy=multi-user.target
  3. Включите службу и посмотрите журнал:
    sudo systemctl daemon-reload
    sudo systemctl enable --now tgbot
    journalctl -u tgbot -f

Перед переносом прогоните на сервере проверку связи из предыдущего раздела.

У способа, которым мы получаем сообщения, есть альтернатива, вебхук. При нём Telegram сам присылает каждое сообщение на ваш сервер, и для этого нужен публичный HTTPS-адрес. Для первого бота опроса через infinity_polling() хватает.

Где освоить Python, чтобы бот вырос

Эхо-бот с кнопками собирается за вечер. Следующий уровень сложнее: база данных для пользователей, оплата, подключение нейросети (например, GigaChat API на Python), тесты и деплой. Здесь уже не обойтись копированием примеров, нужен уверенный Python.

Если боты вам интересны как работа, почитайте, кто такой разработчик чат-ботов и как стать Python-разработчиком с нуля, а программы именно по ботам собраны на странице курсов для разработчиков Telegram-ботов. А курсы, где Python учат системно, есть в каталоге:

КурсШколаСтоимость со скидкойВ рассрочкуДлитель­ностьОбзор курса от Checkroi
Профессия «Python-разработчик»
Перейти на сайт курса
SkillboxSkillbox157 335 ₽5987 ₽/мес.10 месяцевОбзор курса
Fullstack-разработчик на Python
Перейти на сайт курса
НетологияНетология145 100 ₽7125 ₽/мес.21 месяцОбзор курса
ДО Профессия Python-разработчик
Перейти на сайт курса
GeekBrainsGeekBrains149 001 ₽3167 ₽/мес.10 месяцевОбзор курса
Автоматизированное тестирование на Python
Перейти на сайт курса
SkillboxSkillbox122 226 ₽4108 ₽/мес.9 месяцевОбзор курса
Программирование на Python ПРО
Перейти на сайт курса
SkillboxSkillbox119 600 ₽ - 17 месяцевОбзор курса

Больше программ — в полном каталоге курсов по Python

Часто задаваемые вопросы

Можно ли сделать Telegram-бота без программирования?

Да. Простого бота с кнопками и автоответами можно собрать в конструкторе или настроить прямо в BotFather, об этом наша инструкция по созданию бота в Телеграме. Python нужен, когда бот должен считать, ходить во внешние API или хранить данные пользователей.

Какую библиотеку Python выбрать для первого бота?

Для первого бота удобна pyTelegramBotAPI: код пишется обычными функциями, и эхо-бот занимает полтора десятка строк. Для нагруженных ботов чаще берут асинхронный aiogram.

Как получить токен Telegram-бота?

Напишите @BotFather команду /newbot, введите имя и username, который заканчивается на bot. В ответ придёт токен вида 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw. Если токен утёк, команда /token выпустит новый.

Будет ли бот работать, если выключить компьютер?

Нет, бот отвечает, только пока запущен скрипт. Сообщения, пришедшие за это время, Telegram хранит не дольше 24 часов. Чтобы бот работал круглосуточно, его запускают на сервере как службу systemd.

Почему бот не отвечает на сообщения?

Чаще всего скрипт не запущен, токен скопирован не целиком или эхо-обработчик стоит в файле выше остальных и перехватывает команды. Если в терминале ошибка ConnectTimeout, машина не может связаться с api.telegram.org.

Читайте Checkroi первым в Google
Добавьте Checkroi в избранные источники — и наши разборы курсов и обзоры школ будут показываться выше в вашей выдаче Google.
Оставить комментарий
0 комментариев
Форма комментария

Оставьте комментарий

Напишите, что думаете. Нам важно ваше мнение!