NEW 📢 Limited launch offer: up to 70% off your first month on every game!See plans

How to host a node-telegram-bot-api bot 24/7

Telegram bot hostingUpdated Nov 6, 202612 min read

To host a node-telegram-bot-api bot 24/7 you run it on a machine that stays on: a Linux VPS with a systemd service that starts it again when it stops, or a bot plan on PlayNHost (from US$1.99 a month), where the panel installs your packages, gives your code the token and starts the bot again if it crashes. In our test a node-telegram-bot-api 2.3.0 bot used about 63 MB of memory on Node.js 22. One thing first: version 2, the one npm installs today, is a new library with no TelegramBot class, so tutorials written for older versions no longer match it. Bots written for 0.x or 1.x keep their API when you pin their version, as shown below. The steps on PlayNHost:

  1. On Telegram bot hosting, click Create Server on a plan. In the order window, answer What is your bot for? with Telegram and pick Node.js.
  2. 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 Node.js Bot.
  3. At Connect to Telegram, paste the token from @BotFather under Paste your bot token, click Connect, check the bot name shown and click Yes, continue.
  4. Check that your package.json names the version your code is written for: ^2.3.0 for a new Bot(...) bot, or the old version for a new TelegramBot(...) bot.
  5. At Your code, click Upload files and upload your package.json and index.js without node_modules, or click Connect Git.
  6. On the Bot page, pane Code, check that Entry file is the file that starts your bot (index.js by default). Click Save if you change it.
  7. Click Start bot and open Console. npm installs the library on the first start, then your bot prints Logged in as @your_bot and the chip on Overview turns to Online in Telegram.
  8. On the Bot page, pane Telegram, click Open in Telegram and send your bot /start.

Creating the bot in @BotFather and the panel steps are explained in How to host a Telegram bot. This page is about node-telegram-bot-api itself: its versions, what it uses on a server and what to know before you host it.

Which version is your bot written for?

The package name stayed the same, but its API changed completely in August 2026:

VersionReleasedYour code looks like
0.x (last: 0.67.0)Up to 13 Dec 2025const TelegramBot = require('node-telegram-bot-api'), new TelegramBot(token, { polling: true }), bot.onText(...), bot.sendMessage(chatId, text)
1.x (1.0.0 to 1.2.0)12 Jun to 14 Jul 2026The same TelegramBot class, rewritten in TypeScript, loaded with import TelegramBot from 'node-telegram-bot-api'
2.x (now 2.3.0)From 16 Aug 2026 (2.3.0: 4 Nov 2026)const { Bot } = require('node-telegram-bot-api'), bot.command(...), ctx.reply(...), bot.api.sendMessage({ chat_id, text })

The project's README says it plainly: "v2 is a from-scratch redesign, no v1 compatibility", and its changelog says that npm install node-telegram-bot-api from an old tutorial "now lands you on a completely different API". A TelegramBot bot started with 2.x fails at once, because the class no longer exists.

For a bot written for 0.x, keep that version in package.json:

"dependencies": {
  "node-telegram-bot-api": "^0.67.0"
}

A ^ range never moves to a new major version, so the daily package install on our servers keeps your bot on 0.x. Do not write latest or *. If you install it through Packages on the Code pane instead, write the version too, node-telegram-bot-api@0.67: a name without a version asks npm for the release tagged latest, which is 2.3.0.

What we measured

LibraryVersionMemory at restStart to Telegram's answerInstall size
node-telegram-bot-api2.3.063 MB0.2 s2.4 MB
grammY1.46.060 MB0.2 s3.0 MB
Telegraf4.16.360 MB0.2 s2.7 MB
Node.js 22 alone, no library22.23.443 MBnonenone

How: on our own node, in a throwaway container set up like a 1 GB bot plan (the Node.js 22 image and start command of our Node.js bot type, with Node's memory limit at 80 percent), each bot called Telegram with a fake token, which Telegram refused; memory is the resident memory 15 seconds after that answer, start time runs from launch to the answer, and each figure is the median of runs 2 to 4. We measured version 2; 0.x was not measured.

These are floors: a bot with no chats and no data yet. Your own code, what it keeps in memory and the number of chats add to them, so the library is a small part of the 0.5 GB STARTER plan.

A minimal node-telegram-bot-api 2 bot

It answers /start, reads the token the panel gives it and prints a ready line. Put both files in your bot's main folder.

package.json

{
  "name": "my-telegram-bot",
  "private": true,
  "main": "index.js",
  "dependencies": {
    "node-telegram-bot-api": "^2.3.0"
  }
}

index.js

const { Bot, TelegramApiError } = require("node-telegram-bot-api");
const { run } = require("node-telegram-bot-api/node");

const bot = new Bot(process.env.TELEGRAM_BOT_TOKEN);

bot.command("start", (ctx) => ctx.reply("Hello! I am running on PlayNHost."));

async function main() {
  await bot.init(); // asks Telegram who the bot is, so a wrong token fails here
  await bot.api.deleteWebhook(); // version 2 does not remove a webhook by itself
  console.log(`Logged in as @${bot.botInfo.username}`);
  await run(bot); // polls for messages until the bot is stopped
}

main().catch((err) => {
  if (err instanceof TelegramApiError && err.errorCode === 401) {
    console.log("Telegram did not accept the bot token. Paste the current one from @BotFather, then restart.");
  } else {
    console.error(err);
  }
  process.exit(1);
});

The library's own examples read process.env.BOT_TOKEN. The panel gives your code the token as TELEGRAM_BOT_TOKEN and also as BOT_TOKEN, TOKEN, TELEGRAM_TOKEN and TELOXIDE_TOKEN, so those examples run without changes. run() comes from node-telegram-bot-api/node: it polls and stops cleanly on SIGINT or SIGTERM. Version 2 works with require as above or with import.

If the token is wrong

In our test, with a fake token, version 2's first call to Telegram (getMe) failed with this error:

TelegramApiError: 401: Unauthorized

Version 2 does not retry a refused token: bot.init() fails at once. The bot above catches that case and prints Telegram did not accept the bot token. Paste the current one from @BotFather, then restart. instead, and the panel shows the banner Telegram did not accept your bot token above Console. To fix it, in @BotFather send /mybots, choose your bot, then API Token, and copy the token again. On the Bot page, pane Telegram, click Replace token, paste it, click Save token, then Restart now.

A 0.x bot behaves differently: it does not stop. It logs a line such as error: [polling_error] {"code":"ETELEGRAM","message":"ETELEGRAM: 401 Unauthorized"} and asks Telegram again about every 0.3 seconds, so it looks running while nothing answers. The panel reads that line and shows the same banner.

What to know about node-telegram-bot-api on a server

  • A webhook left on the bot: version 2 does not remove it. Its polling treats the 409 as a conflict, retries 10 times, 5 seconds apart, then stops. The bot above calls bot.api.deleteWebhook() before it polls; you can also click Remove webhook on the Telegram pane. Version 0.x removes a webhook by itself when polling meets a 409.
  • Another copy of the bot: on 409 Conflict version 2 waits 5 seconds and tries again, quietly, up to 10 times in a row. After that it stops and run() prints node-telegram-bot-api: polling stopped on a fatal error: with Telegram's text, and the panel shows Your bot is running somewhere else too. Stop the copy on your PC or your old host. See Fix Telegram bot 409 Conflict.
  • An error in a command does not stop the bot. Version 2 prints Unhandled error while processing update with the error and carries on. Set your own handler with bot.catch((err, ctx) => ...).
  • Webhooks: startWebhook, createWebhookServer and webhookCallback need a public HTTPS address, which these plans do not include yet. Use run(bot) or bot.startPolling(). Moving from a webhook host: How to move a Telegram bot to PlayNHost.
  • Seeing what it does: on the Bot page, pane Environment, add the variable DEBUG with the value node-telegram-bot-api:* (Add variable) and restart. Version 2 then traces each request and each poll to the console.
  • Node.js version: 2.3.0 needs Node.js 18.2 or newer. The Runtime on the Code pane offers Node.js 20, 22 (recommended), 24, 25 and 26.
  • Memory limit: the start script sets NODE_OPTIONS=--max-old-space-size to 80 percent of your plan's memory, so the rest of the process has room. Details of the Node.js start script: How to host a Node.js Discord bot.

Host it yourself on a Linux VPS

Version 2 needs Node.js 18.2 or newer. On Debian 12 or 13, or Ubuntu 24.04, the distribution's package is new enough (Debian 12 ships Node.js 18.20, Debian 13 ships 20.19, Ubuntu 24.04 ships 18.19); Ubuntu 22.04 ships Node.js 12, which is too old for it:

sudo apt update
sudo apt install nodejs npm
node --version

Make a user for the bot, copy your files and install the packages:

sudo useradd --system --create-home --home-dir /opt/mybot mybot
sudo cp package.json index.js /opt/mybot/
sudo chown -R mybot: /opt/mybot
cd /opt/mybot && sudo -u mybot npm install --omit=dev

Keep the token out of your code, in a file only root can read:

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

Create /etc/systemd/system/mybot.service:

[Unit]
Description=node-telegram-bot-api Telegram bot
Wants=network-online.target
After=network-online.target

[Service]
User=mybot
WorkingDirectory=/opt/mybot
EnvironmentFile=/etc/mybot.env
ExecStart=/usr/bin/node index.js
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 mybot
sudo journalctl -u mybot -f

Restart=always starts the bot again after a crash or a process.exit(1). systemctl stop mybot sends SIGTERM, which run() turns into a clean stop. Stop any other copy first, or Telegram answers both with 409 Conflict.

Self-hosting or a bot plan

On a VPS you manage yourself:

  • Operating system updates and security, and Node.js upgrades.
  • Running npm install after each change, the service file, the token file and its permissions.
  • Reading journalctl to find out why the bot stopped.
  • Backups of the bot's data.

In return a VPS runs anything, and you can give it a domain with HTTPS for a webhook.

On a PlayNHost bot plan the panel does this for you:

  • A Node.js version picker, and npm install when package.json, the lock file or the Node.js version change.
  • The token, checked with Telegram before it is saved, stored encrypted and given to your code.
  • Starting the bot again after a crash. If it crashes again within a minute, it stays stopped and Console says why.
  • Banners above Console that name the cause when Telegram refuses the token, another copy is running or a webhook is set, with a Remove webhook button on the Telegram pane.
  • Upload, Git deploys and backups from the panel.

Questions people ask

My old bot stopped with an error such as TelegramBot is not a constructor. Why?

Most likely npm installed version 2, which has no TelegramBot class: require('node-telegram-bot-api') now returns an object of named exports such as Bot, not a class you can call with new. Put the version your bot was written for in package.json, for example "node-telegram-bot-api": "^0.67.0", delete node_modules and package-lock.json in Files, and restart: the packages install again. Or move the code to version 2 with the table in the project's changelog.

Should I write a new bot on version 2 or on 0.x?

For a new bot, version 2: it is the one that gets updates, and 2.3.0 supports Telegram's Bot API 10.3. Keep 0.x for an existing bot until you have time to move it; it still installs from npm.

Where do sessions survive a restart?

Not in MemorySessionStorage: it lives in the process and is empty after each restart. FileSessionStorage from node-telegram-bot-api/node writes one file per chat into a folder you name, for example ./.my_bot_sessions. On our plans that folder is in your server's files, so it survives restarts and is in your backups.

Ready to run your node-telegram-bot-api bot around the clock? See the plans on Telegram bot hosting.

Already hosting your bot somewhere else? Move it to us

OUR LATEST BLOGS