zalo-bot-js
v0.2.1
Published
TypeScript SDK for the Zalo Bot API.
Readme
zalo-bot-js

zalo-bot-js is a TypeScript SDK for the Zalo Bot API, designed for Node.js developers who want a practical bot runtime with polling, webhook handling, event listeners, message sending APIs, and a TypeScript-friendly structure.
Docs public | Tiếng Việt | English docs
What You Get
- A
Botclient for the Zalo Bot API - Event-based message handling with
on()andonText() - Built-in polling runtime with
startPolling() - Webhook integration through
processUpdate()andsetWebhook() - Message sending APIs such as
sendMessage(),sendPhoto(),sendSticker(), andsendChatAction() - Sequential multi-photo helper
sendPhotos()with indexed captions - Handler-based APIs with
Application,ApplicationBuilder,CommandHandler,MessageHandler, andfilters
Who This Is For
This SDK is for developers who want to:
- build a Zalo bot in Node.js or TypeScript
- start quickly with polling before moving to webhook
- organize bot logic with either event listeners or handler-based APIs
- choose event API as default or handler API when command/filter routing is preferred
- integrate bot flows with internal services, workflow engines, or external systems
Documentation Path
If you are new to the project, the recommended reading order is:
- Getting started to install dependencies, configure
.env, and run the first bot flow - API Reference to navigate each method and helper page
- Examples and tests to choose between polling, webhook, and local verification scripts
- Architecture to understand the SDK layers
- n8n integration if you want to connect the bot to automation workflows
Installation
npm i zalo-bot-jsEnvironment
ZALO_BOT_TOKEN=your_zalo_bot_token_here
ZALO_BOT_LANG=vi
ZALO_BOT_ADMIN_ID=your_zalo_account_id_hereZALO_BOT_LANG currently supports vi and en.
Quick Start
import "dotenv/config";
import { Bot } from "zalo-bot-js";
const bot = new Bot({ token: process.env.ZALO_BOT_TOKEN! });
bot.on("text", async (message) => {
if (message.text && !message.text.startsWith("/")) {
await bot.sendMessage(message.chat.id, `Ban vua noi: ${message.text}`);
}
});
bot.onText(/\/start(?:\s+(.+))?/, async (message, match) => {
const payload = match[1]?.trim() ?? "ban";
await bot.sendMessage(message.chat.id, `Xin chao ${payload}!`);
});
void bot.startPolling();This is the fastest path to a working bot:
- create a bot and get its token
- create
.env - verify the token
- run polling
- respond to text or commands
Detailed guide: Getting started
Admin Setup And Identity Commands
The SDK now includes built-in identity/admin helper commands in the polling flow:
/id: replies with your account id andadmin=true/false/setadmin: sets admin only one time and writesZALO_BOT_ADMIN_ID=<id>into.env
After admin is set, /setadmin is locked and cannot be changed by other users.
The SDK also auto-creates per-user SQLite data files:
- folder:
Data<bot-name>/(for exampleDataBot_icheck/) - file:
<userId>.db(for example988625821124609868.db) - creation time: first incoming message from that user
Use admin checks in your bot code:
bot.on("text", async (message) => {
if (!message.admin) {
return;
}
await bot.sendMessage(message.chat.id, "Admin-only command");
});
bot.onText(/\/secure/, async (message) => {
const isAdmin = bot.isAdmin(message.fromUser?.id);
if (!isAdmin) {
await bot.sendMessage(message.chat.id, "You are not admin.");
return;
}
await bot.sendMessage(message.chat.id, "Secure command executed.");
});Main API Surface
Bot lifecycle and identity
initialize()shutdown()cachedUsergetMe()getAdminId()isAdmin(userId)
Updates and runtime
getUpdate()getUpdates()processUpdate()startPolling()stopPolling()isPolling()
Sending
sendMessage()sendPhoto()sendPhotos()sendSticker()sendChatAction()editMessageText(),deleteMessage(),pinMessage(),unpinMessage()banChatMember(),unbanChatMember(),promoteChatAdmin(),demoteChatAdmin()setChatKeyboard(),deleteChatKeyboard()uploadFile(),getFileInfo(),getFileDownloadUrl()
Webhook
setWebhook()deleteWebhook()getWebhookInfo()
Event listeners
on("message" | "text" | "photo" | "sticker" | "command", callback)onText(regexp, callback)command(name, callback)
Message helpers
message.replyText()message.replyPhoto()message.replySticker()message.replyAction()message.admin
Handler-based API
ApplicationBuilderApplicationCommandHandlerMessageHandlerfiltersCallbackContext
The handler/filter API remains a long-term compatibility layer. Command parsing semantics are shared with event-style bot.command(...), so trimming, case-insensitive matching, and argument parsing behave consistently across both styles.
Event Shape In This SDK
This project does not expose raw Bot API payloads as the main developer interface. Event callbacks receive SDK models such as Message and Update metadata.
Example:
import { Bot } from "zalo-bot-js";
bot.on("message", async (message, metadata) => {
console.log("[message]", {
updateId: metadata.update.updateId,
chatId: message.chat.id,
messageId: message.messageId,
fromUserId: message.fromUser?.id,
messageType: message.messageType,
eventTypes: metadata.update.eventTypes,
text: message.text ?? null,
sticker: message.sticker ?? null,
photoUrl: message.photoUrl ?? null,
});
});
bot.on("text", async (message) => {
console.log("[text]", {
chatId: message.chat.id,
text: message.text,
});
});
bot.onText(/.*/, async (message, match) => {
console.log("[onText]", {
chatId: message.chat.id,
match: match[0],
});
});Webhook Flow
For production-style deployments, the webhook flow is:
- register the webhook with
setWebhook() - expose a public HTTP endpoint
- validate the webhook secret header
- pass the request body to
processUpdate() - handle the resulting SDK events
See:
Project Structure
src/request: HTTP transport and API error mappingsrc/models: parsed models such asUser,Chat,Message,Update,WebhookInfosrc/core:Bot,Application,ApplicationBuilder,CallbackContextsrc/handlers: handler-based APIs such asCommandHandlerandMessageHandlersrc/filters: composable filtersexamples: example integrationstest: local verification scriptsdocs: VitePress documentation site
Local Development
Core commands:
npm run check
npm run build
npm testUseful scripts:
npm run test:tokennpm run test:hello-botnpm run test:event-debugnpm run test:bot-apinpm run docs:devnpm run docs:build
Current Scope
The SDK currently focuses on the practical bot core and the most common message flows first.
Current limitations:
- multipart media upload is still incomplete
- native single-call album send is not implemented; use
sendPhotos()fallback for now - framework-specific webhook adapters are not split into separate packages
Read Next
License
MIT License. See LICENSE for details.
