To host a Telegram bot 24/7 it needs to live somewhere that never sleeps, and your laptop isn't it. This guide puts your bot on a VPS with pm2 keeping it alive through crashes and reboots. About 15 minutes, and $5.99 a month.
Using an AI coding agent? There's a ready-made prompt at the end of this guide. Copy that instead of this article.
What you'll need
- A PrivateByte VPS. The Flare plan ($5.99/mo: 1 vCPU, 2 GB RAM, 25 GB SSD) is plenty, because a polling bot spends its life waiting for messages rather than computing.
- A bot token from @BotFather.
- Your bot's code, in a Git repo or ready to upload. Node.js is the example; the Python path is noted at each step.
- About 15 minutes. Every command is copy-paste.
Step 1: Create your bot
Message @BotFather and send /newbot. It asks for a display name, then a username ending in bot, and replies with a token like 1234567890:AAF....
Treat that token like a password. Anyone holding it controls your bot. If it leaks, send /revoke to BotFather immediately.
Two other BotFather commands are worth knowing. /setprivacy controls whether your bot sees all group messages or only ones starting with /, and /setcommands registers the command list Telegram shows users.
Step 2: Deploy your VPS
In the PrivateByte dashboard, open the store, choose Flare, pick Ubuntu 24.04, and deploy. Ready in under 60 seconds.
Step 3: Connect over SSH
ssh root@YOUR_SERVER_IP
Windows users: PowerShell has ssh built in, or use PuTTY. The dashboard also has a browser console if you'd rather install nothing.
ssh command.Step 4: Create a non-root user
Running the bot as root means any bug in it has full control of the server.
adduser --disabled-password --gecos "" botuser
rsync --archive --chown=botuser:botuser ~/.ssh /home/botuser
That copies your SSH key across so you can log straight in as botuser later. Stay as root for now. The next step installs system-wide packages, and botuser deliberately has no password and no sudo rights.
Step 5: Install Node.js and pm2
Still as root, because these go in system-wide directories:
apt update && apt upgrade -y
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs git
npm install -g pm2
Python instead: apt install -y python3 python3-pip python3-venv git
Step 6: Get your code onto the server
Switch to botuser now. Everything from here runs as that user:
su - botuser
git clone https://github.com/you/your-telegram-bot.git
cd your-telegram-bot
npm install
Python: python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
No repo? Copy it up from your local terminal instead:
scp -r ./your-telegram-bot botuser@YOUR_SERVER_IP:~/
Step 7: Store the token safely
Never hard-code it. Create a .env file in your project directory holding the token:
BOT_TOKEN=1234567890:AAF-your-real-token-here
Make it with nano .env, paste that line, save and exit. Then restrict the file so only your user can read it:
chmod 600 .env
Read it with dotenv (process.env.BOT_TOKEN) or python-dotenv (os.getenv("BOT_TOKEN")). Add .env to .gitignore before you commit anything.
Step 8: Keep it alive with pm2
node index.js dies the moment you close your SSH session. pm2 keeps it running, restarts it on crash, and brings it back after a reboot.
As botuser, from your project directory:
pm2 start index.js --name telegram-bot
pm2 save
pm2 startup
That last command prints another command for you to run. It needs root, and botuser has no sudo rights, so type exit to drop back to your root session, paste it there, then su - botuser again. Skip it and the bot won't survive a reboot.
Python bots: pm2 start .venv/bin/python --name telegram-bot -- bot.py
Verify it works
pm2 status
Status should read online with restarts at 0. A climbing restart count means it's crash-looping, so check pm2 logs telegram-bot --lines 50.
Confirm Telegram accepts your token. Putting BOT_TOKEN in .env does not put it in your shell, so load it first, from your project directory:
set -a; . ./.env; set +a
curl -s "https://api.telegram.org/bot$BOT_TOKEN/getMe"
A response containing "ok":true means the token works and the server can reach Telegram.
Now message your bot and check it replies. Then reboot the server, wait 30 seconds, reconnect and run pm2 status again. If it's online without you starting it, you're genuinely 24/7 rather than merely currently running.
Troubleshooting
Bot replies twice to every message. Two copies are polling the same token, usually a local instance still running on your laptop. Run pm2 list, remove the extra one with pm2 delete <name>, and stop anything running elsewhere. Telegram allows one polling connection per token.
409 Conflict: terminated by other getUpdates request. The same problem, stated by the API.
Bot works in DMs but ignores group chats. Privacy mode. Send /setprivacy to BotFather, pick your bot, choose Disable, then remove the bot from the group and re-add it. The setting only applies from the next join.
401 Unauthorized. The token is wrong, revoked, or has whitespace in it. Check .env for a trailing space or a stray quote.
pm2 doesn't restart the bot after a reboot. You ran pm2 startup but not the command it printed, or you skipped pm2 save. Do both, in that order.
Bot goes quiet after a few hours. Usually an unhandled rejection killing the process while pm2 restarts it into the same crash. pm2 logs telegram-bot --err shows what's failing. The Telegram API does time out occasionally, and a bot treating that as fatal will die on it.
Do it with an AI agent
If you'd rather hand this to Claude Code, Cursor, or another coding agent, don't paste the article at it. Articles are written for humans, and agents skim the warnings and lose the ordering. Copy this instead, and run it from your own machine with your agent able to SSH out.
Prompt for an AI agent
Deploy a Telegram bot to a fresh Ubuntu 24.04 VPS so it stays online 24/7.
FILL IN FIRST:
- SERVER_IP = <VPS IP from the PrivateByte dashboard>
- REPO_URL = <bot's git repo, or "local" if the code is on my machine>
- RUNTIME = node | python
STEPS:
1. SSH to root@SERVER_IP. Confirm Ubuntu 24.04 before changing anything.
2. Create user "botuser", copy my SSH key to it, and do all bot work as that
user. Never run the bot as root. It has no password and no sudo rights, so
run every system-wide install as root before switching to it.
3. Install the runtime (Node.js 20 LTS from NodeSource, or python3 + venv)
and git.
4. Clone REPO_URL as botuser. If REPO_URL is "local", give me the scp command
to run from my machine and wait.
5. Install dependencies.
6. Create .env with BOT_TOKEN. ASK ME for the token, chmod 600 the file, and
add .env to .gitignore if one exists.
7. Install pm2 globally as root. Start the bot as botuser named
"telegram-bot", run "pm2 save", then run "pm2 startup" and execute the
command it prints as root.
RULES:
- Never print, echo or log the token. To check it is set, check the variable
is non-empty, never what it contains.
- Do not enable a firewall unless I ask. If I do, allow OpenSSH BEFORE
enabling it or we both lose access to the server.
- Nothing destructive. If a user, file or pm2 process already exists, stop
and ask rather than overwriting.
- Do not edit my bot's source. If it won't start, show me the error.
VERIFY, SHOWING ME THE OUTPUT OF EACH:
- "pm2 status" -> online, restarts 0
- "pm2 logs telegram-bot --lines 30" -> no repeating errors
- load .env first ("set -a; . ./.env; set +a"), then
"curl -s https://api.telegram.org/bot$BOT_TOKEN/getMe" as botuser -> "ok":true
- reboot, wait 30s, "pm2 status" again -> still online without you starting it
Do not tell me a step succeeded without showing the output that proves it. If
a check fails, stop and report the real error. Do not retry silently or
improvise a workaround.Two things there are worth copying into your own agent work. It forbids the agent from ever echoing the token, and it demands command output rather than a claim of success. Agents are agreeable by default and will report a step as done when it half-worked.
Deploy your VPS
A Telegram bot is close to an ideal VPS workload: always on, almost no CPU, tiny memory footprint. The Flare plan at $5.99/mo runs several bots at once and is the most cost-effective option we sell for this.
- Unmetered bandwidth, no overage
- Free DDoS protection
- Daily automated backups
- Browser console access
Common questions
How much does it cost to host a Telegram bot? About $5.99/month on a Flare VPS, and one server runs several bots at once. Bots are idle most of the time, so you're paying for availability rather than compute.
Can I run multiple bots on one VPS?
Yes. Give each its own directory, its own .env, and its own pm2 process name. A 2 GB server handles a handful of typical Node or Python bots comfortably.
Do I need a domain name? Not for a polling bot, which is what this guide covers. It connects out to Telegram and needs no inbound traffic. You would only need a domain and an HTTPS certificate for webhooks, where Telegram connects to you. Polling is the right starting point for almost everyone.
Will my bot stay online if the server reboots?
Yes, provided you completed Step 8: pm2 save followed by pm2 startup and the command it prints. Test it by rebooting deliberately, because finding out now beats finding out during an unplanned restart.