telegraf-ratelimit

raw JSON →
2.0.0 verified Sat Apr 25 auth: no javascript

Rate-limiting middleware for the Telegraf Telegram bot framework (v2.0.0). Simple in-memory rate limiter with configurable time window, request limit, custom key generation, and exceeded-limit callback. Lightweight, no external dependencies, designed for ease of integration with Telegraf. Suitable for basic bot rate limiting but not distributed or persistent (in-memory only). Actively maintained as part of the Telegraf ecosystem.

error TypeError: rateLimit is not a function
cause Using named destructuring import on the default export.
fix
Use const rateLimit = require('telegraf-ratelimit') (CommonJS) or import rateLimit from 'telegraf-ratelimit' (ESM).
error Cannot read property 'id' of undefined
cause Default keyGenerator tries to access ctx.from.id when ctx.from is undefined.
fix
Always provide a custom keyGenerator: keyGenerator: (ctx) => ctx.from?.id ?? ctx.chat?.id
gotcha In-memory rate limit state is not shared across processes; restarting the bot resets all counters.
fix Use an external store (e.g., Redis) with a custom keyGenerator and external state.
gotcha The default keyGenerator uses ctx.from.id; if ctx.from is undefined (e.g., in channels), it will throw.
fix Provide a custom keyGenerator that handles missing ctx.from.
gotcha The middleware does not differentiate between different chat contexts; same user across chats is counted together.
fix Use a keyGenerator that includes chat ID, e.g., (ctx) => `${ctx.from.id}:${ctx.chat.id}`.
deprecated Node.js engine requirement >=6.2.1; may not work on very old or very new Node versions.
fix Ensure Node.js >=12 (recommended) as older versions are out of support.
npm install telegraf-ratelimit
yarn add telegraf-ratelimit
pnpm add telegraf-ratelimit

Create a Telegram bot with Telegraf and apply rate limiting: 1 message per 3 seconds per user.

const Telegraf = require('telegraf')
const rateLimit = require('telegraf-ratelimit')

const bot = new Telegraf(process.env.BOT_TOKEN ?? '')

const limitConfig = {
  window: 3000,
  limit: 1,
  onLimitExceeded: (ctx, next) => ctx.reply('Rate limit exceeded')
}

bot.use(rateLimit(limitConfig))
bot.on('text', (ctx) => ctx.reply('Hello!'))
bot.launch()