Library / SDK
yagop/node-telegram-bot-api avatar
yagop/node-telegram-bot-api

node-telegram-bot-api v2: what the from-scratch rewrite changes for TypeScript bot developers

Telegram Bot API for NodeJS

9,205 stars1,646 forksTypeScriptMIT

At a glance

What is it?
The MIT-licensed Telegram Bot API client for NodeJS has been redesigned around middleware, typed builders and a runtime-agnostic core. Here is how the v2 surface works, how to install it, and where it is the wrong choice.
Who is it for?
Adopt node-telegram-bot-api v2 if you are starting a new bot in TypeScript and want middleware, typed builders and one codebase that can run on Node, Bun, Deno, Cloudflare Workers or Vercel Functions. Do not adopt it if you maintain an existing v1 bot and cannot absorb a rewrite: the README states v2 has no v1 compatibility, and the migration guide lives in CHANGELOG.md.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 24 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem node-telegram-bot-api v2 is aimed at

Most Telegram bot code in JavaScript starts as a single file that polls getUpdates and branches on message text. That holds until you need a webhook, a rate-limit retry, an inline keyboard, and a handler that runs before every update. At that point the branching turns into a router you wrote yourself, and the router is the part that breaks.

v2 is a from-scratch redesign of the yagop/node-telegram-bot-api package around that problem. The README states plainly that v2 has no v1 compatibility and points to the v1 to v2 migration guide in CHANGELOG.md. So the audience is specific: developers starting a new TypeScript bot, or teams willing to rewrite an existing one, who want command routing, middleware and typed request builders from the library instead of from their own glue.

The package description calls it a runtime-agnostic TypeScript client. That framing matters more than the bot features. The package.json exports map has separate entries for the core, ./node, ./types and ./bun, which is how the same library reaches Node, Bun, Deno, Cloudflare Workers and Vercel Functions without a second package.

How the middleware chain and the Api client fit together

There are two layers, and the README keeps them distinct.

The Api class mirrors the wire API one-to-one: one method per Bot API method, each taking a single params object. The README gives api.getMe() and api.sendMessage({ chat_id: 12345, text: "hello" }) as examples, and notes that the same client instance is reachable as bot.api and ctx.api. If you already know the Telegram HTTP API, this layer adds almost nothing to learn.

The Bot class is the layer above. Commands, regex handlers and update types are all middleware in one chain, and the README says registration order wins. bot.command("start", handler) and bot.hears(/echo (.+)/, handler) are filters in that chain rather than separate registries. koa-style middleware wraps every update, and downstream work runs behind await next(), so timing, logging and error capture sit around the handler instead of inside it. bot.catch() is described as a last-resort error handler.

Structured fields stay plain typed objects. Builders such as InlineKeyboardBuilder, ReplyKeyboardBuilder and EntityBuilder produce those objects, and the README says the pipeline serializes a literal or a builder result the same way. EntityBuilder computes UTF-16 offsets for you, which is the detail that usually goes wrong when you hand-write entities for formatted text.

Install node telegram bot api and send a first reply

The README gives one install command, and the package is published on npm as node-telegram-bot-api.

bash
npm install node-telegram-bot-api

The README's usage example imports Bot and InlineKeyboardBuilder from the package root, and run from the node-telegram-bot-api/node subpath. The token comes from an environment variable in the example, so export BOT_TOKEN before starting.

ts
import { Bot, InlineKeyboardBuilder } from "node-telegram-bot-api";
import { run } from "node-telegram-bot-api/node";

const bot = new Bot(process.env.BOT_TOKEN!);

bot.command("start", (ctx) => ctx.reply("Hi! Send me anything."));
bot.hears(/echo (.+)/, (ctx) => ctx.reply(ctx.match![1]!));

await run(bot);

The README describes run as a managed runner that wires Ctrl-C to bot.stop(). It also names a core-only alternative, await bot.startPolling(), for runtimes where the managed runner is not available. Send /start in Telegram and the bot replies; send "echo hello" and the regex handler echoes the captured group.

For a webhook deployment the repository ships examples for the frameworks it targets: examples/03-webhook-workers.ts, examples/04-webhook-express.ts, examples/05-webhook-nextjs.ts and examples/13-webhook-node-server.ts. Those files are the concrete reference, since the README excerpt does not document webhook configuration itself.

Uploads, streaming and the retry behaviour you have to design around

The upload rules are the most opinionated part of the README, and they are where a naive implementation will surprise you.

A bare string is always treated as a file_id or a URL. To send bytes you wrap them in InputFile. The README warns that the core does no content sniffing, so the filename you pass is what Telegram sees; fromPath uses the basename. Pass the right extension or Telegram receives a mislabelled file.

Uploads stream, so memory stays flat regardless of file size, and fromPath re-opens a disk stream on each attempt. The failure mode is documented: a Blob or Uint8Array is re-streamed if the transport retries, but a ReadableStream is one-shot. It is sent once and a failure surfaces immediately instead of retrying. To keep retries for an arbitrary stream source, the README says to pass a factory that returns a fresh stream.

ts
await bot.api.sendVideo({
  chat_id,
  video: new InputFile(() => openVideoStream(), { filename: "video.mp4", contentType: "video/mp4" }),
});

A raw InputFile nested inside a structure is auto-hoisted to an attach:// part, which is why sendMediaGroup can mix an InputFile and a plain URL in the same media array. MediaGroupBuilder, StickerSetBuilder, StaticProfilePhotoBuilder and PhotoStoryBuilder are described as optional sugar: each .build() returns the plain shape, so you can drop the builders without changing the request.

Where node-telegram-bot-api v2 is the wrong tool

The v1 break is the largest cost, and the README does not soften it. If you have a v1 bot in production, v2 is a rewrite, not an upgrade. The migration guide is in CHANGELOG.md, and the release history shows the v2 line still moving: v2.2.0-rc0 on 2026-09-04, v2.2.0-rc1 on 2026-09-07 and v2.2.0-rc2 on 2026-09-07. Those are release candidates. A team that needs a stable tag has to decide whether that is acceptable, and the README does not state a date for a final 2.2.0.

Runtime breadth is also a constraint in the other direction. The README says the library runs on Bun, modern Node.js, Deno, Cloudflare Workers and Vercel Functions, but helpers such as fromPath are marked Node only, and the package exposes a ./bun entry alongside ./node. Code that reads from disk does not travel to an edge runtime unchanged.

The documentation is thin in places. The README excerpt covers polling, the Api client, middleware, keyboards, formatting and uploads, but it does not document webhook setup, session storage or conversation state. The repository carries examples/12-conversation.ts, examples/16-sessions.ts, examples/17-callback-tracking.ts and examples/18-reply-tracking-lru.ts, so the material exists, but it is in the examples directory rather than the README.

node telegram bot api vs telegraf: the difference in approach

Telegraf is the comparison people search for, and the split is architectural. Telegraf is built around a context object with a large set of convenience methods and a plugin ecosystem, and it targets Node as its primary runtime.

node-telegram-bot-api v2 splits the two concerns instead. The Api class is a one-to-one mirror of the wire API with a single params object per method, so there is no abstraction between your call and the HTTP request shape. The Bot class adds the middleware chain on top, and commands, regex handlers and update types are filters in that same chain rather than separate registries. The README's phrase for the ordering rule is that registration order wins.

The other difference is reach. The package ships ./node and ./bun export entries and its keywords list includes edge and cloudflare-workers, so the same library is intended to run in Workers and Vercel Functions, not only in a long-lived Node process. If your bot lives entirely in Node and you want a broad plugin surface, that portability buys you nothing. If you want to deploy the same handler code to an edge runtime, it is the reason to pick this package.

Licence, maintenance and upgrade cost

The licence is MIT, declared in LICENSE.md and included in the published files list alongside dist and README.md. MIT is permissive: you can use, modify and redistribute the package, including in closed-source products, provided the copyright notice and permission notice are preserved. That is a description of the licence text, not legal advice; check the file for the exact wording.

The repository is not archived, and the last push was on 2026-09-07. The most recent releases are the three v2.2.0 release candidates dated 2026-09-04 and 2026-09-07. The README states that v2 is a from-scratch redesign with no v1 compatibility, so the upgrade cost from v1 is a port rather than a version bump, and the migration guide is in CHANGELOG.md.

The repository carries AGENTS.md, CLAUDE.md, .agents/ and .claude/ entries alongside CONTRIBUTING.md, and the build uses zshy with tsconfig.build.json plus a postbuild script at scripts/fix-cjs-sourcemaps.mjs. Tests run through bun test test/unit. Anyone forking the project inherits that toolchain, not just the source.

Editorial conclusion

Adopt node-telegram-bot-api v2 if you are starting a new bot in TypeScript and want middleware, typed builders and one codebase that can run on Node, Bun, Deno, Cloudflare Workers or Vercel Functions. Do not adopt it if you maintain an existing v1 bot and cannot absorb a rewrite: the README states v2 has no v1 compatibility, and the migration guide lives in CHANGELOG.md. Before committing, verify your target runtime against the ./node and ./bun export entries, and confirm that the 2.2.0 release candidates on 2026-09-04 and 2026-09-07 are acceptable for production.

Frequently asked questions

How do I install node-telegram-bot-api?

Install it from npm with npm install node-telegram-bot-api. The README then imports Bot from the package root and run from the node-telegram-bot-api/node subpath.

Is node-telegram-bot-api v2 compatible with v1?

No. The README states that v2 is a from-scratch redesign with no v1 compatibility, and directs v1 users to the v1 to v2 migration guide in CHANGELOG.md.

Which runtimes does node-telegram-bot-api v2 support?

The README says it runs on Bun, modern Node.js, Deno, Cloudflare Workers and Vercel Functions. The package.json exports map provides separate core, ./node, ./types and ./bun entries, and helpers such as fromPath are marked Node only.

How do I send an inline keyboard with node-telegram-bot-api?

Build one with InlineKeyboardBuilder, chain .text() or .url() calls, and pass the result as reply_markup on a sendMessage call. The README notes that a tapped inline button comes back as a callback_query.

What is the latest version of node-telegram-bot-api?

The most recent release listed is v2.2.0-rc2, published on 2026-09-07, following v2.2.0-rc1 and v2.2.0-rc0 on 2026-09-04. These are release candidates, and the README does not state a date for a final 2.2.0.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. yagop/node-telegram-bot-api on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/yagop-node-telegram-bot-api.svg)](https://hysenlabs.com/projects/yagop-node-telegram-bot-api)