Чтобы бот заговорил, нужны три вещи: код бота, установленный Python 3 и токен от @BotFather. Токен кладут в переменную окружения, а не в код. Дальше python3 main.py — и бот отвечает в твоём Telegram. Ниже по шагам: где взять токен, как выставить переменную на трёх системах, минимальный бот на стандартной библиотеке и что делать, когда бот молчит.
Токен получает процесс, а не исходный файл
main.py. Сам токен в код не записывают.Что нужно перед стартом
- 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") — апдейт не обязан содержать ключ message: редактирование приходит в edited_message, нажатие inline-кнопки — в callback_query. Вход участника в группу, напротив, может прийти как служебное message без текста. Поэтому пример проверяет и наличие сообщения, и поле text.
Почему бот не отвечает
KeyError: ‘TELEGRAM_BOT_TOKEN’
Переменной окружения нет в том терминале, где запущен Python. Частая причина — токен выставили в одном окне, а запускают в другом; в Windows после setx ещё и нужно открыть новое окно. Проверь наличие, не печатая секрет: python -c "import os; print(bool(os.environ.get('TELEGRAM_BOT_TOKEN')))". True означает, что переменная непустая, но не подтверждает правильность токена.
401 Unauthorized
Telegram не узнал токен. Смотри на значение целиком: лишние кавычки, пробел в начале, обрезанный при копировании хвост, старый токен после /revoke. Токен состоит из числового id бота, двоеточия и примерно 35 символов после него.
409 Conflict
Telegram отвечает описанием вида «terminated by other getUpdates request». Один и тот же бот опрашивает Telegram из двух мест сразу — например, забытый процесс в соседнем терминале или копия на сервере. Убей лишний процесс. Вторая причина — у бота настроен вебхук: тогда getUpdates работать не будет, пока не снимешь его методом deleteWebhook.
getUpdates возвращает пустой список
Бот запущен, ошибок нет, но result пуст. Значит, сообщений для него правда нет: ты пишешь другому боту (проверь username), либо сообщения уже забрал другой процесс, либо ты ещё не нажал «Запустить» в чате.
Бот не видит сообщения в группе
Так и задумано. По умолчанию включён privacy mode: бот получает адресованные ему команды, связанные с ним ответы и служебные события. Команды без имени бота приходят не всегда: надёжнее писать /command@имя_бота. Бот-администратор или бот с отключённым 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
EnvironmentFile=/etc/ritm.env
ExecStart=/usr/bin/python3 main.py
Restart=always
[Install]
WantedBy=multi-user.target
Положи юнит в /etc/systemd/system/ritm.service. До запуска создай /etc/ritm.env со строкой TELEGRAM_BOT_TOKEN=твой_токен, владельцем root и правами 600: systemd прочитает его через EnvironmentFile=. Сам токен в общедоступный файл юнита не записывай. Включи сервис: sudo systemctl enable --now ritm. Логи — journalctl -u ritm -f.
Частые вопросы
Нужен ли сервер, чтобы бот работал
Для проверки — нет, домашнего компьютера хватит. Но бот живёт ровно столько, сколько работает процесс: пока ноутбук не заснул и терминал открыт. Как только бот нужен круглосуточно — бери самую дешёвую VPS и systemd-юнит из предыдущего раздела.
Нужен ли aiogram или python-telegram-bot
Для первого бота — нет. Bot API — это обычный HTTPS с JSON, и urllib его закрывает. Библиотеки окупаются позже, когда появляются машина состояний диалога, очереди, вебхуки и десятки хендлеров.
Можно ли положить токен в файл рядом с кодом
Можно, если файл не попадёт в git: добавь его в .gitignore до первого коммита. Правило простое — токен не должен оказаться в истории репозитория, а как ты его туда не пустишь, переменной окружения или игнором, дело вкуса.
Как понять, что бот вообще жив
Перед циклом while True в примере вызови print(call("getMe", {})["result"]["username"]). Это проверит токен и доступ к API, не выводя секрет и не сохраняя его в истории браузера. 401 указывает на проблему авторизации; пустой ответ или сетевая ошибка сами по себе не доказывают неверный токен. getMe не подтверждает работу обработчика: для этого отправь боту сообщение и дождись эха.
Что дальше
Бот из этой статьи ждёт ответа Telegram в одном потоке и, пока висит на getUpdates, не делает больше ничего. Как только захочешь параллельные задачи — рассылку по расписанию, фоновые запросы — начинай с корутин и asyncio: там разобрано, почему вызов корутины сам по себе ничего не запускает и как один time.sleep останавливает весь цикл.