Step-by-Step Tutorial

Build a Telegram Bot with Node.js

Complete coding tutorial to create your first Telegram bot using Node.js. Learn message handling, commands, webhooks, and advanced features with ready-to-use code examples.

~45 min
Reading Time
Beginner
Difficulty
Node.js
Technology
2025
Updated

Prerequisites

What you'll need:

  • Node.js (v16 or higher) installed
  • Basic JavaScript knowledge
  • Code editor (VS Code recommended)
  • Telegram account
  • Internet connection
  • Hosting service (for webhooks)
1

Project Setup & Dependencies

Let's start by creating a new Node.js project and installing the required dependencies.

Terminal Commands:
# Create project directory
mkdir my-telegram-bot
cd my-telegram-bot

# Initialize npm project
npm init -y

# Install dependencies
npm install node-telegram-bot-api express dotenv
npm install --save-dev nodemon

package.json

// package.json
{
  "name": "telegram-bot",
  "version": "1.0.0",
  "description": "My first Telegram bot",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "dependencies": {
    "node-telegram-bot-api": "^0.64.0",
    "express": "^4.18.2",
    "dotenv": "^16.3.1"
  },
  "devDependencies": {
    "nodemon": "^3.0.2"
  }
}

.env

# .env file
TELEGRAM_BOT_TOKEN=your_bot_token_here
WEBHOOK_URL=https://your-domain.com
PORT=3000

💡 Pro Tip: Never commit your .env file! Add it to .gitignore to keep your bot token secure.

2

Create Your First Bot

Now let's create the main bot file with basic functionality including commands and message handling.

index.js

// index.js
require('dotenv').config();
const TelegramBot = require('node-telegram-bot-api');

const token = process.env.TELEGRAM_BOT_TOKEN;
const bot = new TelegramBot(token, { polling: true });

// Handle /start command
bot.onText(//start/, (msg) => {
    const chatId = msg.chat.id;
    const welcomeMessage = `
🤖 Welcome to my Telegram Bot!

I can help you with:
• Get information
• Answer questions  
• Process commands

Try typing /help to see all commands!
    `;
    
    bot.sendMessage(chatId, welcomeMessage);
});

// Handle /help command
bot.onText(//help/, (msg) => {
    const chatId = msg.chat.id;
    const helpMessage = `
📋 Available Commands:

/start - Start the bot
/help - Show this help message
/info - Get bot information
/echo [text] - Echo your message
/time - Get current time

Just type any command to try it out!
    `;
    
    bot.sendMessage(chatId, helpMessage);
});

// Handle /info command
bot.onText(//info/, (msg) => {
    const chatId = msg.chat.id;
    const user = msg.from;
    
    const infoMessage = `
ℹ️ Bot Information:

👤 Your Info:
• Name: ${user.first_name} ${user.last_name || ''}
• Username: @${user.username || 'Not set'}
• ID: ${user.id}

🤖 Bot Status: Online ✅
📅 Bot Created: 2025
    `;
    
    bot.sendMessage(chatId, infoMessage);
});

// Handle /echo command
bot.onText(//echo (.+)/, (msg, match) => {
    const chatId = msg.chat.id;
    const text = match[1];
    
    bot.sendMessage(chatId, `🔁 You said: "${text}"`);
});

// Handle /time command
bot.onText(//time/, (msg) => {
    const chatId = msg.chat.id;
    const now = new Date();
    const timeString = now.toLocaleString('en-US', {
        timeZone: 'UTC',
        dateStyle: 'full',
        timeStyle: 'long'
    });
    
    bot.sendMessage(chatId, `🕒 Current time: ${timeString}`);
});

// Handle all other messages
bot.on('message', (msg) => {
    const chatId = msg.chat.id;
    const text = msg.text;
    
    // Skip if it's a command (starts with /)
    if (text && !text.startsWith('/')) {
        bot.sendMessage(chatId, `I received your message: "${text}". Try /help to see available commands!`);
    }
});

console.log('🤖 Bot is running...');
Running Your Bot:
# For development (auto-restart on changes)
npm run dev

# For production
npm start

🎉 Congratulations! Your bot is now running. Try sending /start to your bot in Telegram!

3

Setting Up Webhooks

For production bots, webhooks are more efficient than polling. Here's how to set them up:

webhook-server.js

// webhook-server.js
require('dotenv').config();
const express = require('express');
const TelegramBot = require('node-telegram-bot-api');

const token = process.env.TELEGRAM_BOT_TOKEN;
const port = process.env.PORT || 3000;
const webhookUrl = process.env.WEBHOOK_URL; // Your server URL

const app = express();
app.use(express.json());

// Create bot instance (no polling for webhooks)
const bot = new TelegramBot(token);

// Set webhook
bot.setWebHook(`${webhookUrl}/bot${token}`);

// Handle webhook endpoint
app.post(`/bot${token}`, (req, res) => {
    bot.processUpdate(req.body);
    res.sendStatus(200);
});

// Your bot logic here (same as polling version)
bot.onText(//start/, (msg) => {
    const chatId = msg.chat.id;
    bot.sendMessage(chatId, '🤖 Welcome! Bot is running on webhook mode.');
});

// Health check endpoint
app.get('/', (req, res) => {
    res.json({ status: 'Bot is running', mode: 'webhook' });
});

app.listen(port, () => {
    console.log(`🚀 Server running on port ${port}`);
    console.log(`📡 Webhook set to: ${webhookUrl}/bot${token}`);
});

⚠️ Important: Webhooks require HTTPS. Use services like Heroku, Railway, or Vercel for free HTTPS hosting.

4

Advanced Features

Let's add interactive menus, user sessions, and file handling to make your bot more powerful:

advanced-bot.js

// advanced-bot.js
require('dotenv').config();
const TelegramBot = require('node-telegram-bot-api');

const token = process.env.TELEGRAM_BOT_TOKEN;
const bot = new TelegramBot(token, { polling: true });

// In-memory user storage (use database in production)
const userSessions = new Map();

// Middleware to track user sessions
function getUserSession(userId) {
    if (!userSessions.has(userId)) {
        userSessions.set(userId, {
            id: userId,
            state: 'idle',
            data: {}
        });
    }
    return userSessions.get(userId);
}

// Inline keyboard for interactive menus
bot.onText(//menu/, (msg) => {
    const chatId = msg.chat.id;
    
    const options = {
        reply_markup: {
            inline_keyboard: [
                [
                    { text: '📊 Statistics', callback_data: 'stats' },
                    { text: '⚙️ Settings', callback_data: 'settings' }
                ],
                [
                    { text: '📞 Contact', callback_data: 'contact' },
                    { text: '❓ Help', callback_data: 'help' }
                ]
            ]
        }
    };
    
    bot.sendMessage(chatId, '📋 Choose an option:', options);
});

// Handle callback queries (button presses)
bot.on('callback_query', (callbackQuery) => {
    const message = callbackQuery.message;
    const data = callbackQuery.data;
    const chatId = message.chat.id;
    
    switch (data) {
        case 'stats':
            bot.editMessageText(
                `📊 Bot Statistics:
                
• Total Users: ${userSessions.size}
• Messages Processed: 1,234
• Uptime: 24 hours
• Status: Healthy ✅`,
                {
                    chat_id: chatId,
                    message_id: message.message_id,
                    reply_markup: {
                        inline_keyboard: [[
                            { text: '🔙 Back to Menu', callback_data: 'back_menu' }
                        ]]
                    }
                }
            );
            break;
            
        case 'settings':
            const session = getUserSession(callbackQuery.from.id);
            bot.editMessageText(
                `⚙️ Your Settings:
                
• Notifications: ${session.data.notifications !== false ? '✅ Enabled' : '❌ Disabled'}
• Language: English 🇺🇸
• Timezone: UTC
                
Use /toggle_notifications to change.`,
                {
                    chat_id: chatId,
                    message_id: message.message_id,
                    reply_markup: {
                        inline_keyboard: [[
                            { text: '🔙 Back to Menu', callback_data: 'back_menu' }
                        ]]
                    }
                }
            );
            break;
            
        case 'back_menu':
            bot.editMessageText('📋 Choose an option:', {
                chat_id: chatId,
                message_id: message.message_id,
                reply_markup: {
                    inline_keyboard: [
                        [
                            { text: '📊 Statistics', callback_data: 'stats' },
                            { text: '⚙️ Settings', callback_data: 'settings' }
                        ],
                        [
                            { text: '📞 Contact', callback_data: 'contact' },
                            { text: '❓ Help', callback_data: 'help' }
                        ]
                    ]
                }
            });
            break;
    }
    
    // Answer callback query to remove loading state
    bot.answerCallbackQuery(callbackQuery.id);
});

// Handle photos
bot.on('photo', (msg) => {
    const chatId = msg.chat.id;
    const photo = msg.photo[msg.photo.length - 1]; // Get highest resolution
    
    bot.sendMessage(chatId, `📸 Nice photo! File ID: ${photo.file_id}`);
});

// Handle documents
bot.on('document', (msg) => {
    const chatId = msg.chat.id;
    const doc = msg.document;
    
    bot.sendMessage(chatId, `📄 Document received: ${doc.file_name} (${Math.round(doc.file_size / 1024)}KB)`);
});

console.log('🤖 Advanced bot is running...');
New Features Added:
  • • Interactive inline keyboards
  • • User session management
  • • Photo and document handling
  • • Callback query processing
Try These Commands:
  • • /menu - Interactive menu
  • • Send a photo to the bot
  • • Send a document file
  • • Click the menu buttons
5

Deployment Options

Ready to deploy your bot? Here are the best free hosting options:

Railway
  • • Easy deployment
  • • Free $5/month credit
  • • Automatic HTTPS
Vercel
  • • Serverless functions
  • • Free tier available
  • • Great for webhooks
Render
  • • Free web services
  • • Auto-deploy from Git
  • • Built-in SSL
Quick Deploy to Railway:
# Install Railway CLI
npm install -g @railway/cli

# Login and deploy
railway login
railway init
railway up
6

Best Practices & Security

Follow these best practices to make your bot secure and maintainable:

🔒 Security
  • Never expose your bot token in code
  • Use environment variables for secrets
  • Validate user inputs
  • Implement rate limiting
⚡ Performance
  • Use webhooks for production
  • Cache frequently used data
  • Handle errors gracefully
  • Log important events
⚠️ Common Mistakes to Avoid:
  • • Don't commit .env files to version control
  • • Don't use polling in production (use webhooks)
  • • Don't store sensitive data in plain text
  • • Don't forget to handle bot errors

Frequently Asked Questions

Do I need experience with Node.js to build a Telegram bot?

Basic JavaScript knowledge is helpful, but this tutorial covers everything step-by-step. You'll learn Node.js concepts as we build the bot together.

Can I host my Telegram bot for free?

Yes! You can use free hosting services like Heroku, Railway, or Vercel. For webhooks, you'll need HTTPS which these platforms provide automatically.

What's the difference between polling and webhooks for Node.js bots?

Polling is easier for development (no HTTPS required), while webhooks are better for production (real-time, lower resource usage). This tutorial covers both methods.

How do I handle multiple users with my Node.js bot?

Node.js handles this naturally through its event-driven architecture. Each user interaction creates a separate event, and you can store user data in variables or databases.

Can I add a database to my Telegram bot?

Absolutely! You can integrate MongoDB, PostgreSQL, or any database. We'll show basic in-memory storage in this tutorial, but database integration follows similar patterns.

🎉 Congratulations! What's Next?

You've successfully built a Telegram bot with Node.js! Here are some ideas to enhance it further:

🚀 Advanced Features

  • • Add database integration (MongoDB, PostgreSQL)
  • • Implement user authentication
  • • Create admin panels and moderation tools
  • • Add payment processing with Telegram Payments
  • • Build mini-apps with Telegram Web Apps

📚 Learning Resources