НОВОЕ 📢 Ограниченное стартовое предложение: скидка до 70% на первый месяц для любой игры!Посмотреть тарифы

Как запустить бота Telegram.Bot (.NET) 24/7 на VPS или тарифе

Хостинг Telegram-ботовUpdated Nov 6, 202611 min read

Чтобы запустить бота Telegram.Bot (.NET) 24/7, вы запускаете его на машине, которая всегда включена: на Linux VPS со службой systemd, которая перезапускает его при остановке, или на тарифе для ботов в хостинге Telegram-ботов PlayNHost (от US$1.99 в месяц), где вы загружаете проект на C#, вставляете токен от @BotFather и нажимаете Start. В нашем тесте бот на Telegram.Bot 22.10.3.3 занял около 61 МБ памяти на .NET 8. Telegram.Bot получает сообщения через long polling, и именно это нужно нашим тарифам: у них пока нет публичного HTTPS-адреса для вебхука. Шаги на PlayNHost:

  1. На странице хостинга Telegram-ботов нажмите Создать сервер у нужного тарифа. В окне заказа ответьте на Для какой платформы ваш бот? выбором Telegram и выберите C# (.NET).
  2. Откройте свой сервер в панели. Карточка Настройка бота на странице Обзор открывается на шаге Подключение к Telegram; его первый шаг, Что запускается, должен показывать Этот бот запускает .NET Bot.
  3. На шаге Подключение к Telegram вставьте токен в поле Вставьте токен бота, нажмите Подключить, проверьте показанное имя бота и нажмите Да, продолжить.
  4. На шаге Ваш код нажмите Загрузить файлы и загрузите Bot.csproj и Program.cs в главную папку, без папок bin и obj, либо нажмите Подключить Git.
  5. На странице Бот, на вкладке Код, оставьте Среда выполнения на .NET 8 (recommended) и оставьте поле Файл запуска пустым.
  6. Нажмите Запустить бота и откройте Console. Сервер собирает проект, затем бот выводит Logged in as @your_bot, и метка на странице Обзор меняется на Онлайн в Telegram.
  7. На странице Бот, на вкладке Telegram, нажмите Открыть в Telegram и отправьте боту /start.

Создание бота в @BotFather и шаги в панели описаны в статье Как запустить Telegram-бота на хостинге, а тип бота .NET в целом (оба способа загрузки, ошибки сборки) в статье Как запустить Discord-бота на C# (.NET). Эта страница о самом Telegram.Bot: сколько он потребляет на сервере и что стоит знать перед запуском.

Что мы измерили

БиблиотекаВерсияПамять без нагрузкиОт запуска до ответа Telegram, со сборкойОт запуска программы до ответа Telegram
Telegram.Bot22.10.3.361 МБ1,5 с0,3 с
Один .NET 8, без библиотекинет24 МБ1,3 с (сборка и запуск, без вызова)нет

Как мы измеряли: на нашем собственном узле, в одноразовом контейнере, настроенном как тариф для ботов на 1 ГБ (образ .NET 8 и команда запуска нашего типа бота .NET, которая при каждом запуске выполняет dotnet publish), бот вызвал getMe у Telegram с поддельным токеном, и Telegram его отклонил. Память это резидентная память через 15 секунд после этого ответа, первая колонка времени идёт от начала сборки до ответа, вторая от запуска программы, а каждое значение это медиана запусков со 2 по 4. Самая первая сборка, которая ещё и скачивает пакет, заняла 5 секунд.

Это нижняя граница: пока без чатов, без данных и без поллинга. К ней добавятся ваш собственный код, то, что он хранит в памяти, и число чатов. Чтобы не собирать проект при каждом запуске, можно загрузить файлы, опубликованные на вашем компьютере, вместо проекта (см. руководство по C# по ссылке выше). Сравните цифры с тарифами на странице хостинга Telegram-ботов и выбирайте по тому, что делает ваш бот.

Минимальный бот на Telegram.Bot

Он отвечает на /start, читает токен из TELEGRAM_BOT_TOKEN (панель передаёт его вашему коду под этим именем, а также как BOT_TOKEN, TOKEN, TELEGRAM_TOKEN и TELOXIDE_TOKEN) и выводит строку готовности. Два файла в главной папке:

Bot.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Telegram.Bot" Version="22.10.3.3" />
  </ItemGroup>
</Project>

Program.cs

using Telegram.Bot;
using Telegram.Bot.Exceptions;
using Telegram.Bot.Types;

const string TokenRefused = "Telegram did not accept the bot token. Paste the current one from @BotFather on the Bot page, then restart.";

string? token = Environment.GetEnvironmentVariable("TELEGRAM_BOT_TOKEN");
if (string.IsNullOrWhiteSpace(token))
{
    Console.WriteLine("No TELEGRAM_BOT_TOKEN found. Paste your bot token on the Bot page, then restart.");
    return 1;
}

var bot = new TelegramBotClient(token);

User me;
try
{
    me = await bot.GetMe();
}
catch (ApiRequestException e) when (e.ErrorCode == 401)
{
    Console.WriteLine(TokenRefused);
    return 1;
}

// Long polling only: remove a webhook left on the bot. Messages that wait are kept.
await bot.DeleteWebhook();

// Without an OnError handler, polling errors never reach the console. Set it before OnMessage.
bot.OnError += async (exception, source) =>
{
    if (exception is ApiRequestException { ErrorCode: 401 })
    {
        Console.WriteLine(TokenRefused);
        Environment.Exit(1);
    }
    Console.WriteLine($"Polling error ({source}): {exception.Message}");
    await Task.Delay(TimeSpan.FromSeconds(5));
};

// Setting OnMessage starts polling in the background.
bot.OnMessage += async (message, type) =>
{
    if (message.Text?.StartsWith("/start") == true)
    {
        await bot.SendMessage(message.Chat, "Hello! I am running on PlayNHost.");
    }
};

Console.WriteLine($"Logged in as @{me.Username}");
await Task.Delay(Timeout.Infinite);
return 0;

При каждом запуске сервер выполняет dotnet publish для Bot.csproj и запускает Bot.dll. Консоль показывает [PlayNHost] Building your bot (the first build downloads packages and can take a minute), затем [PlayNHost] Starting your bot, затем Logged in as @your_bot, строку, после которой метка меняется на Онлайн в Telegram. Сначала остановите любую копию, запущенную на вашем компьютере с настоящим токеном, иначе обе копии будут получать от Telegram ошибки 409 Conflict.

Если токен неверный

В нашем тесте с поддельным токеном GetMe() в Telegram.Bot завершился такой ошибкой:

ApiRequestException: Unauthorized

Бот выше перехватывает этот отказ (код ошибки 401) до поллинга и во время него и выводит вместо него Telegram did not accept the bot token. Paste the current one from @BotFather on the Bot page, then restart., после чего останавливается с кодом выхода 1. Панель читает эту строку и показывает баннер Telegram не принял токен вашего бота над разделом Console. Чтобы исправить, отправьте в @BotFather /mybots, выберите своего бота, затем API Token и снова скопируйте токен. На странице Бот, на вкладке Telegram, нажмите Заменить токен, вставьте его, нажмите Сохранить токен, затем Перезапустить сейчас.

Что стоит знать о Telegram.Bot на сервере

  • Версии: Telegram.Bot 22.10.3.3 вышел 9 окт. 2026 г. Он нацелен на .NET Standard 2.0 и .NET 6, а его README рекомендует .NET 8 или новее, поэтому любая Среда выполнения, которую предлагает панель (.NET 6, 8, 9 или 10), его собирает; .NET 8 (recommended) соответствует net8.0 выше.
  • У методов в версии 22 пропало Async. Теперь это GetMe() и SendMessage(); руководства с GetMeAsync или SendTextMessageAsync написаны для старых версий, этих имён нет в 22.10.3.3, и их код не собирается. Ошибка сборки находится прямо над [PlayNHost] The build failed. Read the errors above, fix them and press Start. в разделе Console.
  • Установка OnMessage запускает поллинг. Как только обработчик добавлен к OnMessage (или OnUpdate), клиент в фоне опрашивает Telegram и запрашивает все типы обновлений. Сначала добавьте обработчик OnError, как выше.
  • Без OnError ошибки невидимы. Когда опрос не удался, Telegram.Bot передаёт ошибку в OnError; без обработчика он пишет её в трассировку .NET, которая не попадает в консоль. Бот, у которого отозван токен или которого вытесняет другая копия с 409 Conflict, выглядит работающим и ничего не отвечает. Обработчик выше выводит каждую ошибку, и так как собственный текст Telegram есть в сообщении, панель может показать Ваш бот работает ещё и в другом месте или Для вашего бота задан вебхук.
  • Притормаживайте после ошибки. Цикл поллинга спрашивает снова сразу после неудачного запроса; он ждёт лишь столько, сколько работает ваш обработчик OnError. Пауза Task.Delay в 5 секунд выше не даёт стойкой ошибке превратиться в поток запросов. Ответы 429 Too Many Requests от самого Telegram повторяются за вас, когда Telegram просит подождать 60 секунд или меньше: по умолчанию запрос пробуют всего до 3 раз.
  • Вебхук сам не снимается. Поллинг при заданном вебхуке завершается ошибкой 409 Conflict: can't use getUpdates method while webhook is active. Бот выше вызывает DeleteWebhook() до поллинга, и ожидающие сообщения сохраняются; можно также нажать Удалить вебхук на вкладке Telegram. Собственному вебхуку нужен публичный HTTPS-адрес, которого в наших тарифах пока нет. Если вы переезжаете с хостинга с вебхуком: Как перенести Telegram-бота на PlayNHost.
  • Не ждите через Console.ReadLine(). Первый бот из руководства библиотеки работает, пока вы не нажмёте Enter. На сервере Enter никто не нажимает, а под systemd ввод программы по умолчанию пуст, поэтому ReadLine() возвращается сразу, и бот завершается. Ждите через await Task.Delay(Timeout.Infinite), как выше.
  • Сбои: когда бот завершается, как бот выше при отклонённом токене, панель сразу запускает его снова, предварительно пересобрав. Если он снова остановится в течение минуты, он останется остановленным, а Console объяснит причину. См. Как исправить ошибку 409 Conflict у Telegram-бота про два вида 409.

Запуск самостоятельно на Linux VPS

На VPS соберите бота на своём компьютере и запускайте на сервере только результат. Опубликуйте его с помощью .NET 8 SDK:

dotnet publish Bot.csproj -c Release -o publish

В Ubuntu 24.04 среда выполнения .NET 8 есть в собственных пакетах Ubuntu:

sudo apt update
sudo apt install dotnet-runtime-8.0
dotnet --list-runtimes

Создайте пользователя для бота и скопируйте папку publish на сервер (например, с помощью scp -r), затем в его папку:

sudo useradd --system --create-home --home-dir /opt/mybot mybot
sudo cp -r publish/. /opt/mybot/
sudo chown -R mybot: /opt/mybot

Храните токен вне кода, в файле, который может читать только root:

sudo sh -c 'echo "TELEGRAM_BOT_TOKEN=123456789:your-token" > /etc/mybot.env'
sudo chmod 600 /etc/mybot.env

Создайте /etc/systemd/system/mybot.service:

[Unit]
Description=Telegram.Bot Telegram bot
Wants=network-online.target
After=network-online.target

[Service]
User=mybot
WorkingDirectory=/opt/mybot
EnvironmentFile=/etc/mybot.env
ExecStart=/usr/bin/dotnet /opt/mybot/Bot.dll
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Запустите его сейчас и при каждой загрузке, затем следите за его выводом:

sudo systemctl daemon-reload
sudo systemctl enable --now mybot
sudo journalctl -u mybot -f

Restart=always запускает бота снова через 5 секунд после его завершения или падения, но не после того, как вы остановили его через systemctl stop. Чтобы обновить, опубликуйте снова, скопируйте новые файлы поверх старых и выполните sudo systemctl restart mybot. В Debian .NET нет в собственных пакетах дистрибутива; это описано в инструкции по установке от Microsoft.

Свой сервер или тариф для ботов

На VPS, которым вы управляете сами, на вас лежит:

  • Обновление операционной системы, безопасность и обновление среды выполнения .NET.
  • Публикация и копирование каждой новой сборки, файл службы, файл токена и его права.
  • Чтение journalctl, чтобы выяснить, почему бот остановился или перестал отвечать.
  • Резервные копии всего, что хранит ваш бот.

Взамен на VPS можно запустить что угодно, и ему можно дать домен с HTTPS для вебхука.

На тарифе для ботов PlayNHost это делает панель:

  • .NET 6, 8, 9 или 10 из списка выбора и сборка: загрузите проект и нажмите Start.
  • Токен, проверенный в Telegram до сохранения, хранящийся в зашифрованном виде и передаваемый вашему коду под пятью именами.
  • Повторный запуск бота после сбоя. Если он снова упадёт в течение минуты, он останется остановленным, а Console объяснит причину.
  • Кнопка Удалить вебхук на вкладке Telegram и баннеры над разделом Console, которые называют причину, когда строка показывает отклонённый токен, другую копию или вебхук.
  • Загрузка файлов, деплой из Git и резервные копии из панели.

Частые вопросы

Мой бот на Telegram.Bot работает, но никогда не отвечает. Почему?

Чаще всего поллинг не работает, и никто об этом не сообщает: без обработчика OnError ошибки уходят в трассировку .NET, а не в консоль. Добавьте обработчик из бота выше и перезапустите. Обычные причины: другая копия опрашивает Telegram с тем же токеном (409 Conflict), на боте всё ещё задан вебхук или токен отозван в @BotFather.

Можно ли использовать Telegram.Bot здесь с вебхуком?

В наших тарифах пока нет: вебхуку нужен публичный HTTPS-адрес, которого в них нет. Поллингу он не нужен, потому что бот сам спрашивает Telegram о новых сообщениях, и именно это делает OnMessage.

Замедляет ли сборка при каждом запуске моего бота?

Только запуск: в нашем тесте запуск со сборкой занял 1,5 секунды против 0,3 секунды у одной программы. Когда бот уже работает, он такой же. Чтобы пропустить сборку, опубликуйте проект на компьютере и загрузите файлы из папки publish вместо проекта.

Какую версию .NET выбрать?

.NET 8, рекомендуемую, с net8.0 в вашем проекте, как выше. Telegram.Bot собирается и на .NET 6, 9 и 10; задайте ту же версию в TargetFramework и в поле Среда выполнения. Проект для более нового .NET, чем в поле Среда выполнения, прерывает сборку с NETSDK1045; проект для более старого .NET собирается, но не запускается, потому что этого .NET нет в образе.

Готовы запустить своего бота на Telegram.Bot круглосуточно? Смотрите тарифы на странице хостинга Telegram-ботов.

Ваш бот уже у другого хостинга? Перенесите его к нам

ПОСЛЕДНИЕ БЛОГИ