DEV Community

Ali zaib
Ali zaib

Posted on

How to Create a Telegram Bot Using Node.js

Telegram bots are powerful tools that can automate tasks, provide information, and enhance user interaction within the Telegram messaging platform. In this comprehensive guide, we'll walk through the entire process of creating a Telegram bot using Node.js, from setting up your development environment to deploying a fully functional bot.

Building bots is what I do at aziqdev.com — from scratch-built business bots to advanced automation with AI, crypto integrations, payments, and more.

If you want a bot tailored to your business needs, let’s talk!

✅ Custom bots for Telegram, WhatsApp, and Discord
✅ Automation tools and full backend logic
✅ Fast delivery and clean code

Visit here to get started.

Prerequisites

Before we begin, make sure you have the following installed:

  1. Node.js (version 12 or higher recommended)
  2. npm (comes with Node.js) or yarn
  3. A Telegram account
  4. A code editor (VS Code, Sublime Text, etc.)

Step 1: Create a New Telegram Bot

First, you need to register your bot with Telegram's BotFather:

  1. Open Telegram and search for "@botfather" (the official bot that creates other bots)
  2. Start a chat with BotFather and send the command /newbot
  3. Follow the prompts to:
    • Choose a name for your bot (what users will see)
    • Choose a username for your bot (must end with "bot", e.g., "my_test_bot")
  4. After completion, BotFather will give you an API token - save this securely

Important: Never share your bot token publicly. If compromised, revoke it immediately via BotFather.

Step 2: Set Up Your Node.js Project

Create a new directory for your project and initialize a Node.js project:

mkdir telegram-bot
cd telegram-bot
npm init -y
Enter fullscreen mode Exit fullscreen mode

Install the required dependencies:

npm install telegraf dotenv
Enter fullscreen mode Exit fullscreen mode
  • telegraf: A modern Telegram bot framework for Node.js
  • dotenv: For loading environment variables from a .env file

Step 3: Create Basic Project Structure

Your project structure should look like this:

telegram-bot/
├── node_modules/
├── .env
├── .gitignore
├── package.json
├── package-lock.json
└── index.js
Enter fullscreen mode Exit fullscreen mode

Create a .gitignore file with:

node_modules/
.env
Enter fullscreen mode Exit fullscreen mode

Step 4: Configure Environment Variables

Create a .env file in your project root:

BOT_TOKEN=your_bot_token_here
Enter fullscreen mode Exit fullscreen mode

Replace your_bot_token_here with the token you received from BotFather.

Step 5: Create Your Bot's Entry Point

Create an index.js file with the following basic bot setup:

require('dotenv').config();
const { Telegraf } = require('telegraf');

const bot = new Telegraf(process.env.BOT_TOKEN);

// Start command handler
bot.start((ctx) => {
  ctx.reply('Welcome to my Telegram bot!');
});

// Help command handler
bot.help((ctx) => {
  ctx.reply('Send /start to begin\nSend /echo to get a message echoed back');
});

// Echo command handler
bot.command('echo', (ctx) => {
  const input = ctx.message.text;
  const echo = input.substring(input.indexOf(' ') + 1);
  ctx.reply(echo || 'You need to send some text after /echo');
});

// Handle text messages
bot.on('text', (ctx) => {
  ctx.reply('You said: ' + ctx.message.text);
});

// Handle sticker messages
bot.on('sticker', (ctx) => {
  ctx.reply('Nice sticker!');
});

// Launch the bot
bot.launch()
  .then(() => console.log('Bot is running...'))
  .catch((err) => console.error('Bot failed to start', err));

// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));
Enter fullscreen mode Exit fullscreen mode

Step 6: Run Your Bot

Start your bot with:

node index.js
Enter fullscreen mode Exit fullscreen mode

If everything is set up correctly, you should see "Bot is running..." in your console.

Step 7: Test Your Bot

  1. Open Telegram and search for your bot's username
  2. Start a chat with your bot
  3. Try the following commands:
    • /start - Should show the welcome message
    • /help - Should show help information
    • /echo hello - Should reply with "hello"
    • Send a text message - Should reply with "You said: [your message]"
    • Send a sticker - Should reply with "Nice sticker!"

Advanced Bot Features

Now that you have a basic bot working, let's add some more advanced functionality.

1. Keyboard Markup

Add custom keyboards to make interaction easier:

// Add this to your index.js
bot.command('keyboard', (ctx) => {
  ctx.reply('Here is your custom keyboard', Markup.keyboard([
    ['Option 1', 'Option 2'],
    ['Option 3', 'Option 4']
  ]).resize());
});

bot.command('remove', (ctx) => {
  ctx.reply('Keyboard removed', Markup.removeKeyboard());
});
Enter fullscreen mode Exit fullscreen mode

2. Inline Keyboard

Add inline buttons that appear under messages:

const { Markup } = require('telegraf');

bot.command('inline', (ctx) => {
  ctx.reply('Here is your inline keyboard', Markup.inlineKeyboard([
    Markup.button.callback('Button 1', 'btn1'),
    Markup.button.callback('Button 2', 'btn2')
  ]));
});

// Handle inline button callbacks
bot.action('btn1', (ctx) => {
  ctx.answerCbQuery('You pressed Button 1');
  ctx.reply('Button 1 was pressed!');
});

bot.action('btn2', (ctx) => {
  ctx.answerCbQuery('You pressed Button 2');
  ctx.reply('Button 2 was pressed!');
});
Enter fullscreen mode Exit fullscreen mode

3. Handling Different Message Types

// Photo handler
bot.on('photo', (ctx) => {
  ctx.reply('Nice photo!');
});

// Document handler
bot.on('document', (ctx) => {
  ctx.reply('Thanks for the document!');
});

// Voice message handler
bot.on('voice', (ctx) => {
  ctx.reply('I heard your voice message!');
});
Enter fullscreen mode Exit fullscreen mode

4. User Sessions and State Management

To remember user data between interactions:

const session = require('telegraf/session');

// Add session middleware
bot.use(session());

bot.command('register', (ctx) => {
  ctx.reply('Please enter your name:');
  ctx.session.waitingForName = true;
});

bot.on('text', (ctx) => {
  if (ctx.session.waitingForName) {
    ctx.session.name = ctx.message.text;
    ctx.session.waitingForName = false;
    ctx.reply(`Thanks, ${ctx.session.name}! Your name has been saved.`);
  } else {
    ctx.reply('You said: ' + ctx.message.text);
  }
});
Enter fullscreen mode Exit fullscreen mode

Step 8: Deploy Your Bot

For your bot to be always available, you need to deploy it to a server. Here are two options:

Option 1: Using Heroku (Free Tier)

  1. Install the Heroku CLI and login
  2. Create a Procfile in your project root with:
   worker: node index.js
Enter fullscreen mode Exit fullscreen mode
  1. Initialize a git repository:
   git init
   git add .
   git commit -m "Initial commit"
Enter fullscreen mode Exit fullscreen mode
  1. Create a Heroku app:
   heroku create your-app-name
Enter fullscreen mode Exit fullscreen mode
  1. Set your environment variable:
   heroku config:set BOT_TOKEN=your_bot_token_here
Enter fullscreen mode Exit fullscreen mode
  1. Deploy:
   git push heroku main
Enter fullscreen mode Exit fullscreen mode

Option 2: Using a VPS

  1. Set up a Node.js environment on your VPS
  2. Clone your repository or upload your files
  3. Install dependencies with npm install
  4. Use PM2 to keep your bot running:
   npm install -g pm2
   pm2 start index.js --name telegram-bot
   pm2 save
   pm2 startup
Enter fullscreen mode Exit fullscreen mode

Step 9: Webhooks vs Polling

By default, Telegraf uses polling to get updates from Telegram. For production, webhooks are recommended as they're more efficient.

Setting Up Webhooks

// Replace bot.launch() with:
bot.launch({
  webhook: {
    domain: 'https://your-app-name.herokuapp.com',
    port: process.env.PORT || 3000
  }
});
Enter fullscreen mode Exit fullscreen mode

For local development, polling is fine. For production with webhooks, you'll need:

  • A domain with HTTPS (Heroku provides this automatically)
  • To set the webhook URL with Telegram's API

Best Practices for Telegram Bot Development

  1. Error Handling: Wrap your bot logic in try-catch blocks
  2. Rate Limiting: Respect Telegram's API limits (30 messages per second)
  3. Privacy: Be clear about what data you collect and how it's used
  4. User Experience: Provide clear instructions and feedback
  5. Security: Never hardcode your bot token; always use environment variables
  6. Logging: Implement logging for debugging and monitoring
  7. Modular Code: Split your bot into multiple files as it grows

Example: Weather Bot

Here's a more complete example that fetches weather data:

require('dotenv').config();
const { Telegraf, Markup } = require('telegraf');
const axios = require('axios');

const bot = new Telegraf(process.env.BOT_TOKEN);

bot.command('start', (ctx) => {
  ctx.reply(
    'Welcome to Weather Bot!\n' +
    'Send /weather [city] to get weather information\n' +
    'Or use the buttons below:',
    Markup.keyboard([
      ['Weather in London', 'Weather in New York'],
      ['Weather in Tokyo', 'Weather in Paris']
    ]).resize()
  );
});

bot.command('weather', async (ctx) => {
  const city = ctx.message.text.split(' ')[1];
  if (!city) {
    return ctx.reply('Please specify a city, e.g., /weather London');
  }

  try {
    const response = await axios.get(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${process.env.OPENWEATHER_API_KEY}&units=metric`
    );

    const weather = response.data;
    ctx.reply(
      `Weather in ${weather.name}:\n` +
      `🌡 Temperature: ${weather.main.temp}°C\n` +
      `🌤 Condition: ${weather.weather[0].description}\n` +
      `💧 Humidity: ${weather.main.humidity}%\n` +
      `🌬 Wind: ${weather.wind.speed} m/s`
    );
  } catch (error) {
    ctx.reply('Sorry, I couldn\'t fetch weather data for that city.');
  }
});

// Handle the keyboard buttons
bot.hears(/^Weather in (.+)$/i, async (ctx) => {
  const city = ctx.match[1];
  try {
    const response = await axios.get(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${process.env.OPENWEATHER_API_KEY}&units=metric`
    );

    const weather = response.data;
    ctx.reply(
      `Weather in ${weather.name}:\n` +
      `🌡 Temperature: ${weather.main.temp}°C\n` +
      `🌤 Condition: ${weather.weather[0].description}\n` +
      `💧 Humidity: ${weather.main.humidity}%\n` +
      `🌬 Wind: ${weather.wind.speed} m/s`
    );
  } catch (error) {
    ctx.reply('Sorry, I couldn\'t fetch weather data for that city.');
  }
});

bot.launch();
Enter fullscreen mode Exit fullscreen mode

For this to work, you'll need to:

  1. Sign up for a free API key at OpenWeatherMap
  2. Add it to your .env file as OPENWEATHER_API_KEY=your_api_key_here

Conclusion

Creating a Telegram bot with Node.js is a straightforward process that opens up numerous possibilities for automation and user interaction. With the Telegraf library, you can quickly build anything from simple echo bots to complex applications with rich interfaces.

Remember to:

  1. Keep your bot token secure
  2. Handle errors gracefully
  3. Provide clear user instructions
  4. Test thoroughly before deployment
  5. Monitor your bot's performance

As your bot grows, consider adding more advanced features like:

  • Database integration (MongoDB, PostgreSQL)
  • Authentication
  • Payment processing
  • Natural language processing
  • Integration with other APIs

Happy bot building!

Top comments (3)

Collapse
 
technootaku profile image
Techno Otaku V2

it's very well explained, well done, I'm just wondering if Telegram works a bit like Pyrogram?

Collapse
 
alizaibwebdev profile image
Ali zaib

Great question! Telegram bots can be developed in various programming languages, and while the underlying Telegram Bot API remains the same, different libraries offer different approaches. Let me compare Telegraf (Node.js) with Pyrogram (Python) to highlight their similarities and differences.

Core Similarities
Same Telegram API: Both libraries ultimately interact with the same Telegram Bot API

Event-driven architecture: Both use handlers for messages, commands, and other updates

Session management: Both support user sessions and state management

Keyboard support: Both can create reply and inline keyboards

File handling: Both support sending/receiving files, photos, documents, etc.

Key Differences

  1. Language Ecosystem Telegraf (Node.js):

JavaScript/TypeScript ecosystem

Asynchronous by design (Promises, async/await)

NPM package ecosystem

Typically used with Express for webhooks

Pyrogram (Python):

Python ecosystem

Uses async/await (since Pyrogram v2)

Pip package ecosystem

Often used with Flask/FastAPI for webhooks

Collapse
 
technootaku profile image
Techno Otaku V2 • Edited

So if I understand correctly, they have the same features; only the ecosystem between the two differentiates them.

But my question is, does Telegraf support connecting to a user account just like Pyrogram, or is it only focused on bots?

How does Telegraf differ from Node-Telegram-API on a technical level?