Quick Start
Get your first VK bot running in just a few minutes. This guide walks you through creating a simple bot that responds to user messages and commands.
Prerequisites
Before you begin, make sure you have:
Node.js 12.20.0+ installed
VK-IO installed (Installation Guide )
A VK Community token with message permissions (Get a token )
Long Poll API enabled in your community settings
Your First Bot
Let’s create a simple bot that responds to user messages.
Create your project
Create a new directory and initialize your project: mkdir my-vk-bot
cd my-vk-bot
npm init -y
npm install vk-io
Add your token
Create a .env file with your VK token: TOKEN = your_vk_community_token_here
Never commit your .env file to version control. Add it to .gitignore.
Create your bot file
Create bot.js (or bot.mjs for ESM) with the following code: import { VK } from 'vk-io' ;
const vk = new VK ({
token: process . env . TOKEN
});
vk . updates . on ( 'message_new' , async ( context ) => {
await context . send ( 'Hello! You said: ' + context . text );
});
vk . updates . start (). then (() => {
console . log ( 'Bot started!' );
});
Run your bot
Start your bot: TOKEN = your_token_here node bot.js
You should see “Bot started!” in the console. Send a message to your community, and the bot will echo it back!
Adding Commands
Let’s make the bot more interactive by adding command support using the @vk-io/hear package.
Create a bot with commands
Update your bot.js: import { VK } from 'vk-io' ;
import { HearManager } from '@vk-io/hear' ;
const vk = new VK ({
token: process . env . TOKEN
});
const hearManager = new HearManager ();
// Connect the hear manager to updates
vk . updates . on ( 'message_new' , hearManager . middleware );
// Command: /start
hearManager . hear ( '/start' , async ( context ) => {
await context . send ( `
Welcome! 🎉
Available commands:
/start - Show this message
/time - Get current time
/cat - Get a random cat photo
/reverse <text> - Reverse your text
` );
});
// Command: /time or /date
hearManager . hear ([ '/time' , '/date' ], async ( context ) => {
await context . send ( String ( new Date ()));
});
// Command: /cat
hearManager . hear ( '/cat' , async ( context ) => {
await context . send ( 'Loading your cat... 😺' );
await context . sendPhotos ({
value: 'https://loremflickr.com/400/300/cat'
});
});
// Command: /reverse with regex
hearManager . hear ( / ^ \/ reverse ( . + ) / i , async ( context ) => {
const text = context . $match [ 1 ];
const reversed = text . split ( '' ). reverse (). join ( '' );
await context . send ( reversed );
});
// Default handler for unknown messages
vk . updates . on ( 'message_new' , async ( context ) => {
await context . send ( 'Unknown command. Type /start for help.' );
});
vk . updates . start (). then (() => {
console . log ( 'Bot started with commands!' );
}). catch ( console . error );
Test your commands
Run the bot and try these commands:
/start - Shows the help message
/time - Returns the current date and time
/cat - Sends a random cat photo
/reverse hello - Returns “olleh”
Adding a Keyboard
Make your bot even more user-friendly by adding interactive keyboards.
import { VK , Keyboard } from 'vk-io' ;
import { HearManager } from '@vk-io/hear' ;
const vk = new VK ({
token: process . env . TOKEN
});
const hearManager = new HearManager ();
// Handle button payloads
vk . updates . on ( 'message_new' , ( context , next ) => {
const { messagePayload } = context ;
// Set command from button payload
context . state . command = messagePayload ?. command || null ;
return next ();
});
vk . updates . on ( 'message_new' , hearManager . middleware );
// Custom helper for commands that work with both text and buttons
const hearCommand = ( name , conditions , handle ) => {
if ( typeof handle !== 'function' ) {
handle = conditions ;
conditions = [ `/ ${ name } ` ];
}
if ( ! Array . isArray ( conditions )) {
conditions = [ conditions ];
}
hearManager . hear (
[( _text , { state }) => state . command === name , ... conditions ],
handle
);
};
// /start command with keyboard
hearCommand ( 'start' , async ( context ) => {
await context . send ({
message: `
Welcome! 👋
Use the buttons below or type commands:
/help - Show help
/time - Current time
/cat - Random cat photo
` ,
keyboard: Keyboard . builder ()
. textButton ({
label: 'Help' ,
payload: { command: 'help' },
color: Keyboard . SECONDARY_COLOR
})
. row ()
. textButton ({
label: 'Current Time' ,
payload: { command: 'time' },
color: Keyboard . PRIMARY_COLOR
})
. row ()
. textButton ({
label: 'Cat Photo 😺' ,
payload: { command: 'cat' },
color: Keyboard . POSITIVE_COLOR
})
});
});
hearCommand ( 'help' , async ( context ) => {
await context . send ( 'Type /start to see the menu!' );
});
hearCommand ( 'time' , [ '/time' , '/date' ], async ( context ) => {
await context . send ( `Current time: ${ new Date (). toLocaleString () } ` );
});
hearCommand ( 'cat' , async ( context ) => {
await context . send ( 'Loading... 😺' );
await context . sendPhotos ({
value: 'https://loremflickr.com/400/300/cat'
});
});
vk . updates . start (). then (() => {
console . log ( 'Bot started with keyboard!' );
}). catch ( console . error );
Keyboards in VK can be persistent (always shown) or inline (one-time use). Use .inline() when building the keyboard for one-time buttons.
Understanding the Code
Let’s break down the key components:
VK Instance
const vk = new VK ({
token: process . env . TOKEN
});
The VK class is your main entry point. It provides three key properties:
vk.api - Make direct API calls to any VK method
vk.updates - Handle incoming events (messages, posts, etc.)
vk.upload - Upload photos, documents, and other files
Updates & Events
vk . updates . on ( 'message_new' , async ( context ) => {
// Handle new messages
});
vk . updates . start ();
The updates module listens for events from VK using Long Poll API. Common events:
message_new - New message received
message_reply - Message reply from community
wall_post_new - New wall post
group_join - User joined the community
Message Context
The context object provides everything you need to interact with messages:
context . text // Message text
context . senderId // User who sent the message
context . peerId // Chat or user ID
context . send () // Send a message
context . reply () // Reply to the message
context . sendPhotos () // Send photos
context . messagePayload // Button payload data
Keyboard Builder
Keyboard . builder ()
. textButton ({ label: 'Click me' , payload: { action: 'click' } })
. row () // Start a new row
. textButton ({ label: 'Another button' , color: Keyboard . PRIMARY_COLOR })
Keyboard colors:
Keyboard.PRIMARY_COLOR - Blue (main action)
Keyboard.SECONDARY_COLOR - White (secondary action)
Keyboard.POSITIVE_COLOR - Green (confirm, agree)
Keyboard.NEGATIVE_COLOR - Red (delete, reject)
Making API Calls
You can call any VK API method directly:
// Get user information
const users = await vk . api . users . get ({
user_ids: [ 1 , 2 , 3 ],
fields: [ 'photo_100' , 'city' ]
});
// Post to wall
await vk . api . wall . post ({
owner_id: - 123456 , // Your community ID (negative for communities)
message: 'Hello from VK-IO!' ,
attachments: 'photo-123456_789'
});
// Send a message
await vk . api . messages . send ({
peer_id: 123456 ,
message: 'Hello!' ,
random_id: 0
});
VK-IO automatically handles rate limits and request parallelization for you. Make as many API calls as you need!
Next Steps
You now have a working VK bot! Here’s what to explore next:
Updates Guide Learn about all available events and how to handle them
Keyboard Guide Master keyboard creation with buttons and layouts
Uploads Upload photos, documents, audio, and videos
Sessions & Scenes Build conversational flows with state management
API Reference Explore the complete API documentation
Examples See real-world bot implementations
Common Issues
Bot doesn't respond to messages
Make sure:
Long Poll API is enabled in your community settings
Messages are enabled for the community
Your token has the messages permission
The bot is running without errors (console.log the context to debug)
'TOKEN is not defined' error
Your environment variable isn’t set. Either:
Use TOKEN=your_token node bot.js when running
Or install dotenv and load it: require('dotenv').config()
Keyboards only appear in private messages and community chats. Make sure:
You’re testing in a private message to your community
The keyboard is properly built with .builder()
You’re passing it in the options: { keyboard: Keyboard.builder()... }
Check that:
The URL is publicly accessible
You’re using context.sendPhotos() or context.sendDocuments()
Your token has the necessary permissions
The file format is supported (JPG, PNG, GIF for photos)