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:
- Node.js (version 12 or higher recommended)
- npm (comes with Node.js) or yarn
- A Telegram account
- 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:
- Open Telegram and search for "@botfather" (the official bot that creates other bots)
- Start a chat with BotFather and send the command
/newbot
- 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")
- 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
Install the required dependencies:
npm install telegraf dotenv
-
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
Create a .gitignore
file with:
node_modules/
.env
Step 4: Configure Environment Variables
Create a .env
file in your project root:
BOT_TOKEN=your_bot_token_here
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'));
Step 6: Run Your Bot
Start your bot with:
node index.js
If everything is set up correctly, you should see "Bot is running..." in your console.
Step 7: Test Your Bot
- Open Telegram and search for your bot's username
- Start a chat with your bot
- 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());
});
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!');
});
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!');
});
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);
}
});
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)
- Install the Heroku CLI and login
- Create a
Procfile
in your project root with:
worker: node index.js
- Initialize a git repository:
git init
git add .
git commit -m "Initial commit"
- Create a Heroku app:
heroku create your-app-name
- Set your environment variable:
heroku config:set BOT_TOKEN=your_bot_token_here
- Deploy:
git push heroku main
Option 2: Using a VPS
- Set up a Node.js environment on your VPS
- Clone your repository or upload your files
- Install dependencies with
npm install
- Use PM2 to keep your bot running:
npm install -g pm2
pm2 start index.js --name telegram-bot
pm2 save
pm2 startup
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
}
});
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
- Error Handling: Wrap your bot logic in try-catch blocks
- Rate Limiting: Respect Telegram's API limits (30 messages per second)
- Privacy: Be clear about what data you collect and how it's used
- User Experience: Provide clear instructions and feedback
- Security: Never hardcode your bot token; always use environment variables
- Logging: Implement logging for debugging and monitoring
- 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();
For this to work, you'll need to:
- Sign up for a free API key at OpenWeatherMap
- Add it to your
.env
file asOPENWEATHER_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:
- Keep your bot token secure
- Handle errors gracefully
- Provide clear user instructions
- Test thoroughly before deployment
- 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)
it's very well explained, well done, I'm just wondering if Telegram works a bit like Pyrogram?
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
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
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?