To host a pyTelegramBotAPI (telebot) bot 24/7, run it on a machine that stays on instead of your PC: a Linux VPS with a systemd service that starts it again after a crash or a reboot, or a PlayNHost bot plan (from US$1.99 a month, see Telegram bot hosting), where you upload your code, paste the token and press Start. In our test a pyTelegramBotAPI 4.37.1 bot used about 40 MB of memory at rest; our smallest bot plan, STARTER, has 0.5 GB. Both routes use long polling: bot.infinity_polling() asks Telegram for new messages, so the bot needs no public address. The PlayNHost steps:
- In Telegram, send
/newbotto @BotFather and copy the token it gives you. - On Telegram bot hosting, click Create Server on a plan. In the order window, answer What is your bot for? with Telegram and choose Python.
- Open your server in the panel. The Set up your bot card on Overview opens at Connect to Telegram; its first step, What runs, should say This bot runs Python Bot.
- At Connect to Telegram, paste the token and click Connect. Check the bot name shown and click Yes, continue.
- At Your code, click Upload files to open Files and upload
bot.pyandrequirements.txt, or click Connect Git. Inrequirements.txtthe package ispyTelegramBotAPI, nottelebot. - On the Bot page, pane Code, check that Entry file is the file that calls
infinity_polling()(bot.pyby default), and that Runtime is Python 3.11 or newer. - Click Start bot, open Console and wait for
Logged in as @your_bot. The chip on Overview turns to Online in Telegram. Send your bot/start.
The first start takes longer while pip installs pyTelegramBotAPI. After that it installs again only when your requirements file, the extra packages or the Python version change, or once a day. Step by step with screenshots: How to host a Telegram bot.
What we measured
We ran the three Python Telegram libraries on one of our own servers, in throwaway containers set up the way the panel runs a Python bot: Python 3.12 (the Runtime marked recommended), packages installed with the same pip command, a 1 GB memory limit and one CPU core.
| Library | Version | Memory at rest | Start to Telegram's answer | Installed size, with dependencies |
|---|---|---|---|---|
| pyTelegramBotAPI (TeleBot) | 4.37.1 | 40 MB | 0.7 s | 21.9 MB |
| python-telegram-bot | 22.8 | 44 MB | 0.9 s | 12.3 MB |
| aiogram | 3.31.0 | 173 MB | 4.3 s | 33.9 MB |
| Python 3.12 alone | 9 MB |
Each bot loaded the library and asked Telegram who it is with a fake token (pyTelegramBotAPI: bot.get_me() on the plain TeleBot). Memory is what the bot's processes held 15 seconds after Telegram refused the token; start time runs from launching Python to the library reporting that answer, so it includes one round trip to Telegram. Both are the median of three runs after a warm-up run.
These figures are the library's floor: no chats, no handlers at work, nothing cached. Your own code, the data it keeps in memory and the number of chats it serves come on top, so size the plan by what your bot does. The installed size includes both HTTP libraries pyTelegramBotAPI depends on, requests and aiohttp, even when you use only the plain TeleBot.
A minimal pyTelegramBotAPI bot
It answers /start, reads the token the panel gives it and prints a ready line. Put the library in requirements.txt:
pyTelegramBotAPI>=4,<5
And the code in bot.py:
import os
import telebot
bot = telebot.TeleBot(os.environ["TELEGRAM_BOT_TOKEN"])
@bot.message_handler(commands=["start"])
def start(message):
bot.reply_to(message, "Hello! I am running on PlayNHost.")
bot.delete_webhook()
print(f"Logged in as @{bot.user.username}")
bot.infinity_polling()
The two calls before polling matter on a host. delete_webhook() removes a webhook left from another host, and bot.user asks Telegram who the bot is, so Logged in as @your_bot appears only with a token Telegram accepts. The panel reads that line to show Online in Telegram. Both calls also stop the bot at once with a clear error when the token is wrong, instead of letting polling retry it in the background. The panel gives the token to your code as TELEGRAM_BOT_TOKEN, and also as BOT_TOKEN, TOKEN and TELEGRAM_TOKEN.
If the token is wrong
In our test, with a token Telegram refuses, our test bot printed:
ApiTelegramException: A request to the Telegram API was unsuccessful. Error code: 401. Description: Unauthorized
In a full traceback the class reads telebot.apihelper.ApiTelegramException. With the bot above, the first call fails and the bot stops with exit code 1; on PlayNHost the panel shows Telegram did not accept your bot token above the console, with Replace the token. To fix it, copy the token again: in @BotFather send /mybots, choose your bot, then API Token. Paste it on the Bot page, pane Telegram, under Token, and start the bot again.
A bot that calls infinity_polling() straight away, as most examples do, behaves differently: it does not stop. Polling first asks Telegram who the bot is; with a refused token that fails, and the bot logs Infinity polling exception: A request to the Telegram API was unsuccessful. Error code: 401. Description: Unauthorized and tries again every 3 seconds, for as long as the process runs. A token revoked while the bot is already polling gives Threaded polling exception: with the same message instead, retried after a wait that doubles each time, up to a minute. Either way the bot looks running while nothing answers. The panel recognises both lines and shows the same banner.
What a host should know about pyTelegramBotAPI
- Package and import names: you install
pyTelegramBotAPIand importtelebot. The PyPI package calledtelebotis a different, small project; putpyTelegramBotAPIinrequirements.txt. - Python version: pyTelegramBotAPI 4.37.1 needs Python 3.11 or newer. On Python 3.10, pip does not fail: it installs 4.37.0, the last release that allowed 3.10. Keep Runtime on the Code pane at 3.11 or newer (3.12 is marked recommended) to get the current release.
infinity_polling()orpolling(): useinfinity_polling(). Plainpolling()stops at the first error from Telegram, and an exception in one of your handlers ends it too, so the bot exits. Withinfinity_polling(), errors from Telegram are retried, and any other exception in a handler is logged asInfinity polling exception: ...before polling starts again 3 seconds later.- Logging: pyTelegramBotAPI has its own logger,
TeleBot, set toERROR, so it prints nothing when it starts; that is why the bot above prints its own ready line. Errors show as one line without the traceback. To see where a handler failed, start withbot.infinity_polling(logger_level=logging.DEBUG)(andimport logging), which adds the traceback. These lines hide the secret part of your token. - A webhook left from another host: polling does not remove it, and Telegram refuses polling while one is set. Keep
bot.delete_webhook()as above, or click Remove webhook on the Bot page, pane Telegram. - Threads or asyncio:
TeleBotuses requests and runs handlers in two worker threads by default (num_threads=2); a slow handler holds one of them.AsyncTeleBotfromtelebot.async_telebotuses aiohttp and runs withasyncio.run(bot.polling()). Both run the same way on the panel. - A second copy: when another copy polls with the same token, Telegram answers
409 Conflictandinfinity_polling()retries for as long as it runs. The panel shows Your bot is running somewhere else too. See Fix Telegram bot 409 Conflict.
Host it yourself on a Linux VPS
On Debian or Ubuntu, install Python, create a user for the bot and install the library in a virtual environment. Check python3 --version first: below 3.11, pip installs an older pyTelegramBotAPI.
sudo apt update
sudo apt install -y python3 python3-venv
sudo useradd --system --create-home --home-dir /opt/tgbot --shell /usr/sbin/nologin tgbot
sudo cp bot.py requirements.txt /opt/tgbot/
sudo -u tgbot python3 -m venv /opt/tgbot/venv
sudo -u tgbot /opt/tgbot/venv/bin/pip install -r /opt/tgbot/requirements.txt
Put the token in a file only root can read. Open it with sudo nano /etc/tgbot.env, write one line, save, then run sudo chmod 600 /etc/tgbot.env:
TELEGRAM_BOT_TOKEN=123456789:your-token-from-botfather
Create /etc/systemd/system/tgbot.service:
[Unit]
Description=Telegram bot (pyTelegramBotAPI)
Wants=network-online.target
After=network-online.target
[Service]
User=tgbot
WorkingDirectory=/opt/tgbot
EnvironmentFile=/etc/tgbot.env
Environment=PYTHONUNBUFFERED=1
ExecStart=/opt/tgbot/venv/bin/python /opt/tgbot/bot.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Start it now and at every boot, then follow its output:
sudo systemctl daemon-reload
sudo systemctl enable --now tgbot
sudo journalctl -u tgbot -f
PYTHONUNBUFFERED=1 matters here: when Python's output does not go to a terminal it is block-buffered, so without it Logged in as can sit in a buffer instead of reaching the journal. Restart=always also starts the bot again 5 seconds after it stops on a wrong token, so check the journal if it keeps restarting. After you change the code, run sudo systemctl restart tgbot. Stop any copy on your PC first, or Telegram answers 409 Conflict.
Self-hosting or a bot plan
- On a VPS you manage: system updates, the Python version, the virtual environment, reinstalling packages, the unit file, reading the journal and noticing when the bot stops answering. In return you have root, and you can run a webhook if you add a domain and HTTPS.
- On a bot plan the panel does: it installs
requirements.txtwhen it changes, starts the bot again after a crash, checks the token with Telegram before saving it, gives it to your code under five names, reads the console and names the cause when the bot stops answering (a refused token, a second copy, a webhook), with a button for the token and the webhook. Our bot plans do not include a public HTTPS address yet, so bots there use long polling, which is whatinfinity_polling()does.
Questions people ask
Why does my telebot bot run but never answer?
Because infinity_polling() retries every error from Telegram without stopping: a refused token, another copy using the same token, a webhook left on the bot. Look for lines with Infinity polling exception (a token refused at start) or Threaded polling exception (once polling runs) in Console; the panel turns each of the three causes into a banner that names it.
I get ModuleNotFoundError: No module named 'telebot'. What is missing?
The package. Add pyTelegramBotAPI to requirements.txt and start the bot again: the requirements file changed, so pip installs it on that start. The import stays import telebot.
Does pyTelegramBotAPI need a webhook to stay online?
No. infinity_polling() keeps asking Telegram for new messages, so the bot answers as long as the process runs. Moving a bot that used a webhook: How to move a Telegram bot to PlayNHost.
Should I use TeleBot or AsyncTeleBot?
Either runs on a bot plan. Use the one your code or tutorial uses: with TeleBot the handlers are plain functions, with AsyncTeleBot they are async def functions that await the bot's methods. Our measurement above is for the plain TeleBot.
pyTelegramBotAPI runs on every PlayNHost bot plan, from STARTER (0.5 GB) up. Compare the plans and click Create Server on Telegram bot hosting.



