Чтобы бот заговорил, нужны три вещи: код бота, установленный Python 3 и токен от @BotFather. Токен кладут в переменную окружения, а не в код. Дальше python3 main.py — и бот отвечает в твоём Telegram. Ниже по шагам: где взять токен, как выставить переменную на трёх системах, минимальный бот на стандартной библиотеке и что делать, когда бот молчит.
Что нужно перед стартом
- Python 3.8 или новее. Проверь:
python3 --version(в Windows —python --version). - Папка с файлами бота. Если писал бота на Koddo, забери его кнопкой «скачать проект» в меню редактора — архив соберётся из твоего кода и выданных модулей.
- Аккаунт в Telegram — с него ты и заведёшь бота.
- Сеть, из которой доступен
api.telegram.org. Весь обмен идёт по HTTPS на этот домен.
Сторонние библиотеки не нужны. aiogram и python-telegram-bot дают удобства, но первый запуск обходится модулем urllib из стандартной поставки. Если позже решишь поставить одну из них — сначала заведи виртуальное окружение, чтобы зависимости бота не смешивались с другими проектами на компьютере.
Как получить токен у @BotFather
Токен выдаёт сам Telegram, в чате, за минуту.
- Найди в поиске Telegram
@BotFather— у настоящего синяя галочка верификации. - Отправь
/newbot. - Введи имя бота — его видят люди в заголовке чата. Кириллица можно, пробелы можно:
Ритм. - Введи username — только латиница, цифры и подчёркивания, обязательно заканчивается на
bot:ritm_habit_bot. Если занят, BotFather попросит другой. - В ответ придёт строка вида
8123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw— это токен.
Токен — пароль от бота. У кого он есть, тот и управляет ботом: читает переписку, отправляет сообщения от его имени. Не коммить его в git, не отправляй в чаты, не оставляй в скриншотах. Если утёк — команда /revoke у BotFather выдаст новый, а старый перестанет работать сразу.
Куда положить токен
В переменную окружения. Строка TOKEN = "8123456789:AAH..." прямо в коде переживёт первый же git push и останется в истории репозитория навсегда.
Linux и macOS, bash или zsh:
export TELEGRAM_BOT_TOKEN="8123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw"
python3 main.py
Переменная живёт до закрытия терминала. Чтобы не набирать каждый раз, положи строку export ... в конец ~/.zshrc или ~/.bashrc — она подхватится в новых окнах.
Windows, PowerShell:
$env:TELEGRAM_BOT_TOKEN = "8123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw"
python main.py
Насовсем — setx TELEGRAM_BOT_TOKEN "8123456789:AAH...", но применится это только к новым окнам, текущее останется без переменной.
Windows, cmd:
set TELEGRAM_BOT_TOKEN=8123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw
python main.py
Кавычки в cmd не ставь: они попадут внутрь значения, и Telegram ответит 401 Unauthorized на токен с кавычкой на конце.
Python читает переменную так:
import os
TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
Как запустить бота
Открой терминал в папке с файлами бота и запусти точку входа:
python3 main.py
Дальше консоль замолкает и висит — так и должно быть. Процесс держит long polling: он спрашивает Telegram про новые сообщения и ждёт ответа до тридцати секунд. Открой своего бота в Telegram (BotFather дал ссылку t.me/<username>), нажми «Запустить» — и первое сообщение уйдёт в твой запущенный код.
Остановить — Ctrl+C в том же терминале.
Минимальный бот на чистом Python
Проверить всю цепочку — токен, сеть, разбор апдейтов — можно двадцатью пятью строками на стандартной библиотеке. Это рабочий эхо-бот: он повторяет всё, что ему пишут.
import json
import os
import urllib.request
TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
API = f"https://api.telegram.org/bot{TOKEN}/"
def call(method, payload):
request = urllib.request.Request(
API + method,
data=json.dumps(payload).encode("utf-8"),
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(request, timeout=65) as response:
return json.loads(response.read().decode("utf-8"))
offset = 0
print("Бот слушает Telegram. Ctrl+C — выход.")
while True:
for update in call("getUpdates", {"offset": offset, "timeout": 30})["result"]:
offset = update["update_id"] + 1
message = update.get("message")
if not message or "text" not in message:
continue
call("sendMessage", {
"chat_id": message["chat"]["id"],
"text": f"Эхо: {message['text']}",
})
Три места, которые стоит понять до того, как строить что-то сложнее.
offset — курсор в очереди апдейтов. Telegram хранит их до суток и отдаёт снова и снова, пока ты не подтвердишь получение: подтверждение — это следующий запрос с offset, равным update_id + 1. Забыл прибавить единицу — бот бесконечно отвечает на одно и то же сообщение.
timeout в запросе — 30 секунд, таймаут сокета — 65. Второй обязан быть больше первого. Поставишь наоборот — соединение оборвётся раньше, чем Telegram успеет ответить, и бот будет падать на ровном месте.
update.get("message") — апдейт не обязан быть сообщением. Отредактированное сообщение, нажатие кнопки, вход участника в группу — всё это приходит в том же потоке с другими ключами. Код, который сразу лезет в update["message"], упадёт на первом же редактировании чужого сообщения.
Почему бот не отвечает
KeyError: ‘TELEGRAM_BOT_TOKEN’
Переменной окружения нет в том терминале, где запущен Python. Частая причина — токен выставили в одном окне, а запускают в другом; в Windows после setx ещё и нужно открыть новое окно. Проверь: echo $TELEGRAM_BOT_TOKEN (PowerShell: echo $env:TELEGRAM_BOT_TOKEN).
401 Unauthorized
Telegram не узнал токен. Смотри на значение целиком: лишние кавычки, пробел в начале, обрезанный при копировании хвост, старый токен после /revoke. Токен состоит из числового id бота, двоеточия и примерно 35 символов после него.
409 Conflict
Telegram отвечает описанием вида «terminated by other getUpdates request». Один и тот же бот опрашивает Telegram из двух мест сразу — например, забытый процесс в соседнем терминале или копия на сервере. Убей лишний процесс. Вторая причина — у бота настроен вебхук: тогда getUpdates работать не будет, пока не снимешь его методом deleteWebhook.
getUpdates возвращает пустой список
Бот запущен, ошибок нет, но result пуст. Значит, сообщений для него правда нет: ты пишешь другому боту (проверь username), либо сообщения уже забрал другой процесс, либо ты ещё не нажал «Запустить» в чате.
Бот не видит сообщения в группе
Так и задумано. По умолчанию у бота включён privacy mode: в группах он получает только команды со слешем, ответы на свои сообщения и служебные события. Обычную болтовню он не видит. Выключается у BotFather: /setprivacy → выбрать бота → Disable. После этого бота нужно удалить из группы и добавить заново, иначе настройка не применится.
urlopen висит или падает на сети
Если из твоей сети api.telegram.org недоступен, поможет прокси. urllib берёт его из окружения сам — отдельный код не нужен:
export https_proxy=http://127.0.0.1:8080
python3 main.py
Как оставить бота работать
Закрыл терминал — процесс убит, бот офлайн. Ноутбук ушёл в сон — то же самое. Варианты по возрастанию надёжности:
На своей машине, на время. nohup python3 main.py & отвяжет процесс от терминала и сложит вывод в nohup.out. Удобнее — tmux или screen: сессия переживёт закрытие окна, и в неё можно вернуться.
На сервере, насовсем. Юнит systemd поднимет бота при старте машины и перезапустит после падения:
[Unit]
Description=Telegram bot
After=network-online.target
[Service]
WorkingDirectory=/opt/ritm
Environment=TELEGRAM_BOT_TOKEN=8123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw
ExecStart=/usr/bin/python3 main.py
Restart=always
[Install]
WantedBy=multi-user.target
Положи файл в /etc/systemd/system/ritm.service и включи: sudo systemctl enable --now ritm. Логи — journalctl -u ritm -f. Файл юнита читается всеми пользователями системы, так что токен лучше вынести в отдельный файл с правами 600 и подключить его через EnvironmentFile=.
Частые вопросы
Нужен ли сервер, чтобы бот работал
Для проверки — нет, домашнего компьютера хватит. Но бот живёт ровно столько, сколько работает процесс: пока ноутбук не заснул и терминал открыт. Как только бот нужен круглосуточно — бери самую дешёвую VPS и systemd-юнит из предыдущего раздела.
Нужен ли aiogram или python-telegram-bot
Для первого бота — нет. Bot API — это обычный HTTPS с JSON, и urllib его закрывает. Библиотеки окупаются позже, когда появляются машина состояний диалога, очереди, вебхуки и десятки хендлеров.
Можно ли положить токен в файл рядом с кодом
Можно, если файл не попадёт в git: добавь его в .gitignore до первого коммита. Правило простое — токен не должен оказаться в истории репозитория, а как ты его туда не пустишь, переменной окружения или игнором, дело вкуса.
Как понять, что бот вообще жив
Открой в браузере https://api.telegram.org/bot<токен>/getMe. Ответ с "ok": true и username бота значит, что токен рабочий и сеть до Telegram есть. Пустой ответ или 401 — проблема в токене, а не в коде.
Что дальше
Бот из этой статьи ждёт ответа Telegram в одном потоке и, пока висит на getUpdates, не делает больше ничего. Как только захочешь параллельные задачи — рассылку по расписанию, фоновые запросы — начинай с корутин и asyncio: там разобрано, почему вызов корутины сам по себе ничего не запускает и как один time.sleep останавливает весь цикл.