← back to blog

Bot broadcast limits and how to stay under them

If you run a bot that sends messages to more than a handful of users, you will hit a 429 eventually. It’s not a bug in your code and it’s not Telegram being difficult. It’s the system working as designed. The question isn’t whether you’ll hit the limit, it’s whether your bot handles it gracefully or falls over and starts dropping messages.

We host bots and manage proxy configurations for a living, and the same question comes up constantly: what’s the actual telegram bot rate limit, and how do you build around it instead of getting surprised by it. Here’s what the limits actually are and how to design a broadcast system that respects them.

What Telegram actually limits

Telegram documents three separate ceilings for bots, and they don’t stack the way people expect.

The first is per-chat: a bot can send roughly one message per second into any single chat. This applies whether that chat is a private conversation, a group, or a channel. Send faster than that into the same chat and you’ll get throttled on that chat specifically, regardless of what else your bot is doing.

The second is per-group: messages into the same group or supergroup are capped at around 20 per minute. This is much stricter than the per-chat number because groups have many members watching a shared timeline, and Telegram’s backend treats rapid-fire posting into one group as a signal worth slowing down, separate from the one-per-second chat limit.

The third is global, across all the different chats a single bot messages: roughly 30 messages per second when you’re sending to distinct users. This is the number that matters for broadcasts, since a broadcast by definition is one message fanned out to many different chat IDs rather than many messages into one chat.

These three limits are independent. A bot broadcasting to 10,000 individual users at 30 messages per second isn’t touching the per-group limit at all, because none of those sends share a chat ID. A bot posting updates into one channel is bound by the per-chat number, not the broadcast number. Knowing which limit you’re actually up against changes how you design the send loop.

Why proxies and hosting location don’t move these numbers

This comes up often enough that it’s worth being direct about it: these limits are enforced against your bot token, not against the IP address or server the request comes from. Routing bot API calls through a proxy, running your bot from a different region, or spreading requests across multiple hosting locations does nothing to raise the ceiling. Telegram’s backend is counting messages against your token’s send rate, and that counter follows the token wherever the request originates.

Where proxy configuration does matter is reliability, not throughput. If your hosting provider has intermittent connectivity to Telegram’s API endpoints, or you’re operating in a region where direct access is unreliable, a stable proxy path keeps your queue draining consistently instead of timing out and retrying in bursts that make rate limiting worse. That’s a legitimate reason to care about your network path. It’s just not a rate limit workaround, because there isn’t one.

The only way to legitimately raise your effective broadcast capacity is to run multiple bots with different tokens for genuinely different purposes, since each token gets its own limit. That’s not a trick to dodge the cap on one bot, it’s just how the limits are scoped.

What a 429 actually tells you

When you exceed a limit, Telegram’s API returns an HTTP 429 with a retry_after field in the response body, telling you how many seconds to wait before trying again. That field is not a suggestion. It’s Telegram’s backend telling you exactly how long the current throttle window lasts.

The mistake we see most often is bots that catch the 429, wait a fixed short interval like one second, and retry immediately, ignoring the actual retry_after value. That makes the problem worse, not better, because you’re now sending a retry into a window that’s still rate limited, which can extend the backoff. Read the field and wait the full duration it specifies before sending into that chat again.

Building a queue that respects the limits

The fix isn’t clever, it’s a queue. Instead of firing off a message to every recipient as fast as your code can loop, put every outgoing message into a queue and drain it at a fixed rate that stays under the relevant ceiling.

A simple token bucket does this well. Give yourself a budget of, say, 25 sends per second, refilled continuously, and pull from the queue only when a token is available. That gives you headroom under the roughly-30-per-second global limit so that normal jitter in your own processing doesn’t accidentally push you over it. If any part of your broadcast is going into the same chat more than once (a bot that also replies to a group it’s broadcasting into, for example) serialize sends to that specific chat ID separately so you never do more than one per second there, on top of respecting the global bucket.

When a 429 does land, the correct response is to pause the whole queue, or at minimum that chat’s lane, for the exact retry_after window, then resume. Don’t discard the message. Requeue it for the next available slot so it still gets delivered instead of silently vanishing from your logs.

This is genuinely a couple hundred lines of code, not an infrastructure project. A worker process, a rate-limited queue, and a retry handler that reads retry_after will keep a bot broadcasting to tens of thousands of users without ever tripping the throttle in a way your users notice.

Local Bot API server: what it changes and what it doesn’t

Telegram publishes an open source local Bot API server that you can run yourself instead of calling api.telegram.org directly. It’s worth knowing what it actually buys you, because it’s often misunderstood as a rate limit bypass. It isn’t one.

Running the local server changes things like file upload size limits, letting you send files up to 2GB instead of the 50MB cap on the hosted API, and it can reduce latency for high volume file transfers since you’re talking to a server you control. What it does not change is the message rate ceilings described above. Those are enforced by Telegram’s backend on the other side of the connection, not by which API server your requests pass through first. If your broadcast bottleneck is send rate rather than file size, the local server won’t help.

Segmenting broadcasts instead of blasting them

Even with a well behaved queue, sending a broadcast to a large list all at once is worth reconsidering on its own terms. A queue that respects a 25-per-second budget sending to 50,000 recipients takes about half an hour to clear, which is fine for most use cases, but it also means the first recipient and the last recipient get the message half an hour apart. If timing matters for what you’re sending, plan for that spread rather than assuming a broadcast is instantaneous.

It’s also worth splitting large recipient lists into batches with a short pause between batches, even below the point where you’d trigger a 429. This gives you natural checkpoints to catch failures, log delivery status, and stop early if something in the batch looks wrong, rather than discovering a problem only after the entire list has been processed.

Practical checklist

Keep the per-chat rate at one message per second or below, always. Keep group posting under 20 messages per minute per group. Budget global broadcast throughput a bit under 30 messages per second to leave headroom. Read and honor retry_after on every 429 instead of guessing a wait time. Requeue failed sends rather than dropping them. Don’t expect proxies or hosting changes to raise any of these numbers, since they’re tied to the bot token. Use the local Bot API server if you need bigger file uploads, not as a throughput fix. And batch large broadcasts with checkpoints so a bad send list doesn’t clear before you notice.

None of this requires exotic infrastructure. It requires respecting the numbers Telegram publishes and building a queue that does the same.

If you’re setting up bot hosting or proxy configuration and want it done by people who deal with this daily, take a look at what we run.

Get new guides and videos first — join the Telegram channel.

need infra for this today?