Host a Telegram bot 24/7 with Python

Bot-Hosting team,

A Telegram bot is just a program that asks Telegram for new messages and answers them. Running it 24/7 means running that program on a server that never sleeps. This guide builds one in Python with aiogram 3 and puts it online for free, first with long polling (simplest), then with a webhook (lightest).

Step 1: get a token from BotFather

  1. In Telegram, open a chat with @BotFather.
  2. Send /newbot, choose a display name, then a username ending in bot.
  3. BotFather replies with a token like 123456789:AAH.... Keep it secret: it controls your bot.

Step 2: write the bot

requirements.txt:

aiogram>=3.13

main.py:

import asyncio
import logging
import os

from aiogram import Bot, Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message

dp = Dispatcher()


@dp.message(CommandStart())
async def start(message: Message):
    await message.answer(f"Hello, {message.from_user.full_name}!")


@dp.message()
async def echo(message: Message):
    await message.send_copy(chat_id=message.chat.id)


async def main():
    bot = Bot(token=os.environ["BOT_TOKEN"])
    await dp.start_polling(bot)


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    asyncio.run(main())

That is a complete bot: it greets /start and echoes anything else, text, stickers and photos included. The token comes from the BOT_TOKEN environment variable, so it never lands in a file you upload or a repository you push.

Step 3: host the Telegram bot 24/7

Sign up on Bot-Hosting.net and start a new deployment:

  1. What are you deploying? Application, then Python.
  2. Source: Archive with a .zip of the two files, or GitHub if they are in a repository.
  3. Click Launch deployment. The entry file defaults to main.py (change it in the Startup tab if needed).

Then open the Environment tab, Add variable, key BOT_TOKEN, paste the token, tick Secret. Saving restarts the deployment, which installs requirements.txt and starts the bot. The Console shows:

INFO:aiogram.dispatcher:Start polling
INFO:aiogram.dispatcher:Run polling for bot @my_echo_bot id=123456789 - 'My Echo Bot'

Send /start to your bot. It answers, and keeps answering when your computer is off.

Polling or webhook?

Long polling (what the code above does) keeps a request open to Telegram and receives updates through it. It needs no public address, works anywhere and is the right default.

A webhook reverses the direction: Telegram sends each update to an HTTPS URL you give it. It uses slightly fewer resources when the bot is idle and scales better under load, but it needs a public HTTPS address with a valid certificate.

On Bot-Hosting, that address is free. In the deployment’s Domains tab, activate a subdomain under apps.bot-hosting.cloud, with HTTPS set up automatically, or attach your own domain. Then make the bot listen on the port the platform gives it, SERVER_PORT, on 0.0.0.0:

import os

from aiohttp import web
from aiogram import Bot, Dispatcher
from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application

WEBHOOK_PATH = "/webhook"
BASE_URL = os.environ["BASE_URL"]  # e.g. https://my-bot.apps.bot-hosting.cloud

dp = Dispatcher()
# ... same handlers as above ...


async def on_startup(bot: Bot):
    await bot.set_webhook(f"{BASE_URL}{WEBHOOK_PATH}", secret_token=os.environ["WEBHOOK_SECRET"])


def main():
    bot = Bot(token=os.environ["BOT_TOKEN"])
    dp.startup.register(on_startup)
    app = web.Application()
    SimpleRequestHandler(dispatcher=dp, bot=bot, secret_token=os.environ["WEBHOOK_SECRET"]).register(app, path=WEBHOOK_PATH)
    setup_application(app, dp, bot=bot)
    web.run_app(app, host="0.0.0.0", port=int(os.environ["SERVER_PORT"]))


if __name__ == "__main__":
    main()

Add BASE_URL and a random WEBHOOK_SECRET in the Environment tab. Telegram sends the secret in a header with every update, and the handler rejects requests without it, so nobody else can post fake updates to your URL.

Common problems

  • TelegramConflictError: terminated by other getUpdates request: two copies of the bot are polling with the same token, usually your local one and the deployed one. Stop the local one.
  • TelegramUnauthorizedError: the token is wrong, or you revoked it in BotFather. Paste the current one in the Environment tab.
  • The webhook gets no updates: check getWebhookInfo (https://api.telegram.org/bot<token>/getWebhookInfo). A last_error_message there tells you what Telegram saw. And a bot with an active webhook cannot poll: call delete_webhook() before going back to polling.

Storing data

The deployment’s disk is persistent, so a SQLite file works for a small bot. For more, add a PostgreSQL, MySQL, MongoDB or Redis deployment in the same account; they are covered by backups like everything else.

Free, 24/7

The free plan gives 256 MB of RAM, far more than an aiogram bot needs, with no sleep timer and no card. It is renewed by hand every 4 days with one click on Renew now. More on the platform: Telegram bot hosting.

Deploy it in one click

The Telegram Bot Starter template is this exact bot, on aiogram 3, with dozens of examples to grow from. Deploy it, paste your BotFather token, done.

Deploy the Telegram Bot Starter template Telegram bot hosting