grammY: The Telegram Bot Framework
grammY is a powerful, user-friendly, and highly efficient framework designed for creating Telegram bots using TypeScript or JavaScript. As of version 1.42.0, it offers robust support for the latest Telegram Bot API features, frequently releasing updates to keep pace with Telegram's evolving platform (e.g., Bot API 9.6 in recent releases). It distinguishes itself with comprehensive documentation, seamless integration with web frameworks (like Express, Koa, Bun, Cloudflare Workers) and databases, and a thriving ecosystem of plugins. The library emphasizes scalability and performance, making it suitable for both novice bot developers and large-scale applications. It runs on Node.js (requiring ^12.20.0 || >=14.13.1) and Deno.
Common errors
-
Error: Bot token is not provided!
cause The `Bot` constructor was called with an empty or undefined string for the bot token.fixEnsure the `BOT_TOKEN` environment variable is set before running your bot, or pass a valid token string to the `Bot` constructor. Example: `process.env.BOT_TOKEN`. -
TypeError: Cannot read properties of undefined (reading 'on')
cause This usually indicates that the `bot` object was not correctly initialized or is `undefined` before attempting to call methods like `on` or `command`.fixVerify that `new Bot(BOT_TOKEN)` successfully created a bot instance and that `BOT_TOKEN` is a valid string. Check for typos or incorrect variable assignments. -
Error: EACCES: permission denied, listen '0.0.0.0:80'
cause Commonly occurs when trying to run a webhook server on a privileged port (like 80 or 443) without sufficient user permissions (e.g., running as a non-root user).fixUse a non-privileged port (e.g., 3000, 8080) for your webhook server if running as a non-root user. If you must use a privileged port, configure your system to allow the bot's process to bind to it, or use a reverse proxy (like Nginx) to forward requests. -
UnhandledPromiseRejectionWarning: Unhandled promise rejection.
cause Asynchronous middleware functions or API calls within your bot's handlers are not properly `await`ed or do not have `.catch()` blocks, leading to unhandled errors.fixAlways use `await` for asynchronous operations (e.g., `ctx.reply()`, API calls) inside your middleware. Implement proper error handling using `try...catch` blocks or `bot.catch()` middleware to gracefully manage errors.
Warnings
- gotcha Hardcoding your bot token directly into source code is a significant security risk. Anyone with access to your code repository could use your bot's token.
- breaking grammY frequently updates to support the latest Telegram Bot API versions. While this keeps the library current, it means that older grammY versions might not correctly handle new Bot API features or changes, potentially leading to unexpected behavior or `400 Bad Request` errors if your bot uses unsupported API methods.
- gotcha While grammY supports both CommonJS (`require`) and ES Modules (`import`), the documentation and examples increasingly favor ESM. Mixing module systems within a single project can lead to `TypeError: require is not a function` or other module resolution issues.
- gotcha When deploying with webhooks, ensure your server is correctly configured to listen on the specified port and is publicly accessible. Common errors include port conflicts, firewalls blocking incoming connections, or incorrect URL configurations for Telegram to send updates.
Install
-
npm install grammy -
yarn add grammy -
pnpm add grammy
Imports
- Bot
const { Bot } = require('grammy');import { Bot } from 'grammy'; - Context
import { Context } from 'grammy'; - Composer
import Composer from 'grammy';
import { Composer } from 'grammy'; - webhookCallback
import { webhookCallback } from 'grammy';import { webhookCallback } from 'grammy/webhooks';
Quickstart
import { Bot } from 'grammy';
// Ensure your bot token is stored securely, e.g., in environment variables
const BOT_TOKEN = process.env.BOT_TOKEN ?? '';
if (!BOT_TOKEN) {
console.error('Error: BOT_TOKEN environment variable is not set.');
console.error('Please get your bot token from @BotFather on Telegram.');
process.exit(1);
}
// Create a bot object with the token
const bot = new Bot(BOT_TOKEN);
// Register listeners to handle text messages
bot.on('message:text', async (ctx) => {
console.log(`Received text message from ${ctx.from?.first_name}: ${ctx.message.text}`);
await ctx.reply(`Echo: ${ctx.message.text}`);
});
// Register listener for /start command
bot.command('start', async (ctx) => {
await ctx.reply('Hello! I am your grammY bot.');
});
// Catch all other messages
bot.on('message', async (ctx) => {
await ctx.reply('I only understand text messages and the /start command for now!');
});
// Start the bot using long polling
bot.start();
console.log('Bot started via long polling. Send it a message!');