Чтобы запустить бота 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:
- На странице хостинга Telegram-ботов нажмите Создать сервер у нужного тарифа. В окне заказа ответьте на Для какой платформы ваш бот? выбором Telegram и выберите C# (.NET).
- Откройте свой сервер в панели. Карточка Настройка бота на странице Обзор открывается на шаге Подключение к Telegram; его первый шаг, Что запускается, должен показывать Этот бот запускает .NET Bot.
- На шаге Подключение к Telegram вставьте токен в поле Вставьте токен бота, нажмите Подключить, проверьте показанное имя бота и нажмите Да, продолжить.
- На шаге Ваш код нажмите Загрузить файлы и загрузите
Bot.csprojиProgram.csв главную папку, без папокbinиobj, либо нажмите Подключить Git. - На странице Бот, на вкладке Код, оставьте Среда выполнения на .NET 8 (recommended) и оставьте поле Файл запуска пустым.
- Нажмите Запустить бота и откройте Console. Сервер собирает проект, затем бот выводит
Logged in as @your_bot, и метка на странице Обзор меняется на Онлайн в Telegram. - На странице Бот, на вкладке Telegram, нажмите Открыть в Telegram и отправьте боту
/start.
Создание бота в @BotFather и шаги в панели описаны в статье Как запустить Telegram-бота на хостинге, а тип бота .NET в целом (оба способа загрузки, ошибки сборки) в статье Как запустить Discord-бота на C# (.NET). Эта страница о самом Telegram.Bot: сколько он потребляет на сервере и что стоит знать перед запуском.
Что мы измерили
| Библиотека | Версия | Память без нагрузки | От запуска до ответа Telegram, со сборкой | От запуска программы до ответа Telegram |
|---|---|---|---|---|
| Telegram.Bot | 22.10.3.3 | 61 МБ | 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-ботов.



