Как запустить телеграм-бота на Python: токен и первый старт

Python Автор: Среда и версия: Python 3.8+; Telegram Bot API

Чтобы бот заговорил, нужны три вещи: код бота, установленный 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, в чате, за минуту.

  1. Найди в поиске Telegram @BotFather — у настоящего синяя галочка верификации.
  2. Отправь /newbot.
  3. Введи имя бота — его видят люди в заголовке чата. Кириллица можно, пробелы можно: Ритм.
  4. Введи username — только латиница, цифры и подчёркивания, обязательно заканчивается на bot: ritm_habit_bot. Если занят, BotFather попросит другой.
  5. В ответ придёт строка вида 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 останавливает весь цикл.

Источники