Para alojar un bot de grammY 24/7 lo ejecutas en una máquina que siempre está encendida: un VPS Linux con un servicio systemd que lo arranca de nuevo cuando se detiene, o un plan de bots de PlayNHost (desde US$1.99 al mes), donde el panel instala tus paquetes, da el token a tu código y vuelve a iniciar el bot si se cae. En nuestra prueba, un bot con grammY 1.46.0 usó unos 60 MB de memoria en Node.js 22. bot.start() de grammY usa long polling, que es lo que necesitan nuestros planes: todavía no tienen una dirección HTTPS pública para un webhook. Los pasos en PlayNHost:
- En alojamiento de bots de Telegram, haz clic en Crear servidor en un plan. En la ventana del pedido, responde ¿Para qué plataforma es tu bot? con Telegram y elige Node.js.
- Abre tu servidor en el panel. La tarjeta Configura tu bot en Resumen se abre en Conectar con Telegram; su primer paso, Qué se ejecuta, debería decir Este bot ejecuta Node.js Bot.
- En Conectar con Telegram, pega el token de @BotFather en Pega el token de tu bot, haz clic en Conexión, comprueba el nombre del bot que aparece y haz clic en Sí, continuar.
- En Tu código, haz clic en Subir archivos y sube tu
package.jsony tuindex.jssinnode_modules, o haz clic en Conectar Git. ¿Aún no tienes código? Crear un bot inicial te escribe un pequeño bot de grammY. - En la página Bot, panel Código, comprueba que Archivo de entrada es el archivo que inicia tu bot (
index.jspor defecto). Haz clic en Guardar si lo cambias. - Haz clic en Iniciar bot y abre Console. npm instala grammY en el primer inicio, después tu bot imprime
Logged in as @your_boty el indicador de Resumen pasa a En línea en Telegram. - En la página Bot, panel Telegram, haz clic en Abrir en Telegram y envía
/starta tu bot.
Cómo crear el bot en @BotFather y qué hace cada paso del panel se explica en Cómo alojar un bot de Telegram. Esta página trata sobre grammY en sí: qué usa en un servidor y qué debes saber antes de alojarlo.
Qué medimos
| Biblioteca | Versión | Memoria en reposo | Del inicio a la respuesta de Telegram | Tamaño de instalación |
|---|---|---|---|---|
| grammY | 1.46.0 | 60 MB | 0.2 s | 3.0 MB |
| Telegraf | 4.16.3 | 60 MB | 0.2 s | 2.7 MB |
| node-telegram-bot-api | 2.3.0 | 63 MB | 0.2 s | 2.4 MB |
| Node.js 22 solo, sin biblioteca | 22.23.4 | 43 MB | ninguno | ninguno |
Cómo: en nuestro propio nodo, en un contenedor desechable configurado como un plan de bots de 1 GB (la imagen de Node.js 22 y el comando de inicio de nuestro tipo de bot Node.js, con el límite de memoria de Node al 80 por ciento), cada bot llamó a Telegram con un token falso, que Telegram rechazó. La memoria es la memoria residente 15 segundos después de esa respuesta, el tiempo de inicio va desde el arranque hasta la respuesta, y cada cifra es la mediana de las ejecuciones 2 a 4.
Son valores mínimos: un bot sin chats ni datos todavía. Tu propio código, lo que guarde en memoria y el número de chats se suman a ellos, así que la biblioteca es una parte pequeña del plan STARTER de 0.5 GB.
Un bot mínimo con grammY
Responde a /start, lee el token que le da el panel e imprime una línea de listo. Pon los dos archivos en la carpeta principal de tu bot.
package.json
{
"name": "my-grammy-bot",
"private": true,
"main": "index.js",
"dependencies": {
"grammy": "^1.46.0"
}
}
index.js
const { Bot, GrammyError } = require("grammy");
const bot = new Bot(process.env.TELEGRAM_BOT_TOKEN);
bot.command("start", (ctx) => ctx.reply("Hello! I am running on PlayNHost."));
// Without this, an error in one command stops the whole bot.
bot.catch((err) => {
console.error(`Error while handling update ${err.ctx.update.update_id}:`, err.error);
});
// bot.start() only returns when the bot stops, so the ready line goes in onStart.
bot.start({
onStart: (me) => console.log(`Logged in as @${me.username}`),
}).catch((err) => {
if (err instanceof GrammyError && err.error_code === 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);
});
El panel da el token a tu código como TELEGRAM_BOT_TOKEN, y también como BOT_TOKEN, TOKEN, TELEGRAM_TOKEN y TELOXIDE_TOKEN, así que process.env.BOT_TOKEN de otros ejemplos también funciona. La línea Logged in as @your_bot es la que pone el indicador en En línea en Telegram.
Si el token es incorrecto
En nuestra prueba, con un token falso, bot.start() de grammY se detuvo con este error:
GrammyError: Call to 'deleteWebhook' failed! (401: Unauthorized)
bot.start() envía getMe y deleteWebhook a la vez, así que el error nombra la llamada que Telegram rechazó primero: en algunas de nuestras ejecuciones fue Call to 'getMe' failed! (401: Unauthorized). grammY no reintenta un token rechazado: bot.start() falla de inmediato. El bot de arriba captura ese caso e imprime en su lugar Telegram did not accept the bot token. Paste the current one from @BotFather, then restart., y el panel muestra el aviso Telegram no aceptó el token de tu bot encima de Console. Para arreglarlo, en @BotFather envía /mybots, elige tu bot, luego API Token, y copia el token otra vez. En la página Bot, panel Telegram, haz clic en Reemplazar token, pégalo, haz clic en Guardar token y después en Reiniciar ahora.
Qué debes saber de grammY en un servidor
- La línea de listo va en
onStart.bot.start()solo devuelve el control cuando el bot se detiene, así que unconsole.logdespués deawait bot.start()nunca se imprime mientras funciona. grammY llama aonStartcon los datos de tu bot justo antes de pedir a Telegram los primeros mensajes. - Un error en un comando detiene el bot si no configuras
bot.catch. Sin él, grammY imprimeNo error handler was set!, detiene el polling y lanza el error, así que el proceso termina. Nuestro panel vuelve a iniciar un bot caído en aproximadamente un minuto, pero hasta entonces está fuera de línea. Conbot.catch, como arriba, el error se imprime y el bot sigue. - Un webhook que haya quedado en el bot se elimina por ti.
bot.start()llama adeleteWebhookantes de hacer polling y conserva los mensajes en espera, salvo que pasesdrop_pending_updates: true. Esto importa cuando mueves un bot desde un alojamiento que usaba un webhook: Cómo mover un bot de Telegram a PlayNHost. - Otra copia del bot detiene esta. Con
409 Conflict(el mismo token haciendo polling en otro sitio),bot.start()falla en lugar de reintentar. El panel muestra Tu bot también se está ejecutando en otro sitio: detén la copia de tu PC o de tu antiguo alojamiento. Consulta Solucionar el error 409 Conflict de un bot de Telegram. - Los errores de red al iniciar se reintentan en silencio. Si la primera llamada a Telegram falla por la red, grammY lo intenta de nuevo con esperas cada vez más largas (hasta 20 minutos entre intentos en la versión 1.46.0) y no imprime nada. Para ver esos intentos, en la página Bot, panel Entorno, añade la variable
DEBUGcon el valorgrammy*(Añadir variable) y reinicia. - Versión de Node.js: grammY 1.46.0 requiere Node.js 12.20 o 14.13.1 y posteriores. El Entorno de ejecución del panel Código ofrece Node.js 20, 22 (recommended), 24, 25 y 26.
- Límite de memoria: el script de inicio fija
NODE_OPTIONS=--max-old-space-sizeal 80 por ciento de la memoria de tu plan, para que el resto del proceso tenga espacio. Detalles del script de inicio de Node.js: Cómo alojar un bot de Discord en Node.js.
Alójalo tú mismo en un VPS Linux
En Debian 12 o 13, o Ubuntu 24.04, basta con el paquete de la distribución para grammY (Debian 12 incluye Node.js 18.20, Debian 13 incluye 20.19, Ubuntu 24.04 incluye 18.19):
sudo apt update
sudo apt install nodejs npm
node --version
Crea un usuario para el bot, copia tus archivos e instala los paquetes:
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
Mantén el token fuera de tu código, en un archivo que solo root pueda leer:
sudo sh -c 'echo "TELEGRAM_BOT_TOKEN=123456789:your-token" > /etc/mybot.env'
sudo chmod 600 /etc/mybot.env
Crea /etc/systemd/system/mybot.service:
[Unit]
Description=grammY 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
Inícialo ahora y en cada arranque, y luego sigue su salida:
sudo systemctl daemon-reload
sudo systemctl enable --now mybot
sudo journalctl -u mybot -f
Restart=always vuelve a iniciar el bot tras una caída o un process.exit(1). Detén antes cualquier otra copia, o Telegram responderá a ambas con 409 Conflict.
Alojamiento propio o plan de bots
En un VPS que gestionas tú, te encargas de:
- Las actualizaciones y la seguridad del sistema operativo, y las actualizaciones de Node.js.
- Ejecutar
npm installdespués de cada cambio, el archivo del servicio, el archivo del token y sus permisos. - Leer
journalctlpara saber por qué se detuvo el bot. - Las copias de seguridad de los datos del bot.
A cambio, un VPS ejecuta cualquier cosa, y puedes darle un dominio con HTTPS para un webhook.
En un plan de bots de PlayNHost, el panel lo hace por ti:
- Un selector de versión de Node.js y
npm installcuando cambianpackage.json, el archivo de bloqueo o la versión de Node.js. - El token, comprobado con Telegram antes de guardarlo, almacenado cifrado y entregado a tu código.
- Volver a iniciar el bot tras una caída. Si se cae otra vez en un minuto, se queda detenido y Console explica por qué.
- Avisos encima de Console que nombran la causa cuando Telegram rechaza el token, hay otra copia en marcha o hay un webhook configurado, con un botón Quitar webhook en el panel Telegram.
- Subida de archivos, despliegues con Git y copias de seguridad desde el panel.
Consulta también Cómo usar una base de datos MySQL con un bot de grammY (mysql2).
Preguntas frecuentes
¿Es lo mismo que el bot inicial del panel?
Casi. En un servidor Node.js, Crear un bot inicial escribe index.js y package.json con grammY ^1.46.0: responde a /start con tu nombre, imprime Logged in as @your_bot, captura errores con bot.catch e imprime una línea clara cuando Telegram rechaza el token. Cámbialo como quieras y reinicia.
¿Tengo que quitar mi webhook antes de bot.start()?
No. bot.start() lo elimina con deleteWebhook antes de hacer polling, y los mensajes que estaban esperando se conservan. Si tu código anterior usaba webhookCallback(bot, ...) con un servidor web, sustitúyelo por bot.start(): estos planes todavía no tienen una dirección HTTPS pública para un webhook.
¿Basta bot.start() para un bot con mucho tráfico?
Para la mayoría de los bots, sí. bot.start() procesa los mensajes uno tras otro; las propias notas de grammY dicen que sirve para unos 5,000 mensajes por hora, y apuntan al paquete @grammyjs/runner para más, o para comandos que tardan mucho, como transferencias de archivos grandes. El runner también usa long polling, así que funciona en nuestros planes.
¿Puedo ejecutar grammY en Bun o Deno en lugar de Node.js?
Sí. Al hacer el pedido, elige Bun o Deno en lugar de Node.js: nuestra página de alojamiento de bots de Telegram incluye grammY para ambos. Los pasos de esta página son para Node.js.
¿Listo para ejecutar tu bot de grammY a todas horas? Consulta los planes en alojamiento de bots de Telegram.



