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

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

Чтобы бот заговорил, нужны три вещи: код бота, установленный Python 3 и токен от @BotFather. Токен кладут в переменную окружения, а не в код. Дальше python3 main.py — и бот отвечает в твоём Telegram. Ниже по шагам: где взять токен, как выставить переменную на трёх системах, минимальный бот на стандартной библиотеке и что делать, когда бот молчит.

Python / 01

Токен получает процесс, а не исходный файл

Токен получает процесс, а не исходный файл01 Создай бота @BotFather → /newbot Сохрани выданный токен. 02 Передай окружению TELEGRAM_BOT_TOKEN Не добавляй токен в main.py и историю Git. 03 Запусти и проверь python3 main.py Сообщение «привет» → ответ «Эхо: привет».01Создай бота@BotFather → /newbotСохрани выданный токен.02Передай окружениюTELEGRAM_BOT_TOKENНе добавляй токен в main.py и историю Git.03Запусти и проверьpython3 main.pyСообщение «привет» → ответ «Эхо: привет».
Цепочка запуска состоит из трёх шагов: получить токен, передать его процессу через окружение и запустить main.py. Сам токен в код не записывают.

Что нужно перед стартом

  • 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") — апдейт не обязан содержать ключ 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 останавливает весь цикл.

Источники