Skip to main content

telethon-floodgate

Flood-wait handling for Telethon user accounts: a proactive rate-limit gate, a reactive circuit breaker, and flood-wait sleep/retry helpers — three layers that keep a working account out of Telegram's multi-hour FLOOD_WAIT bans.

Telegram does not publish rate limits. This library is the production flood stack of a multi-account Telegram content collector, calibrated against real incidents: a fresh session firing 160+ auth.resolveUsername calls in seconds escalated into 15–18 hour bans, and repeated getDialogs sweeps ran a account into a 14.8-hour ban. The defaults are deliberately conservative and every bucket is configurable.

Install

pip install telethon-floodgate

Requires Python 3.11+, Telethon 1.x, pydantic 2.x and pybreaker.

The three layers

1. Proactive rate-limit gate — before the call

from telethon_floodgate import TelegramRateLimitGate, TelegramRateLimitedError

gate = TelegramRateLimitGate()          # create once, next to your client pool

def before_telegram_call(phone: str, operation: str) -> None:
    category = gate.category_for(operation)   # "send", "history", "dialogs", ...
    retry_after = gate.try_acquire(phone, category)
    if retry_after > 0:
        raise TelegramRateLimitedError(phone, category, retry_after)

Buckets are independent sliding windows keyed by (phone, category): dialogs (1/min — the #1330 incident), dialog_sweep, history, admin_action, send (30/min), channel_lifecycle (3 per 5 min), plus a permissive default. Override any of them:

from telethon_floodgate import RateLimitSpec, TelegramRateLimitGate

gate = TelegramRateLimitGate(
    category_limits={"send": RateLimitSpec(max_calls=10, window_sec=60.0)}
)

resolve and reaction are intentionally no-op categories: in the origin project those paths have dedicated limiters (see ResolveRateLimiter, also shipped here).

Per-peer send limits

Telegram throttles sending per peer, not just per account: roughly one message per second to the same private chat and about twenty per minute into the same group or channel. Pass a peer key to try_acquire and the gate checks a second, independent (phone, category, peer) bucket before the category one:

from telethon_floodgate import peer_key

retry_after = gate.try_acquire(phone, "send", peer=peer_key(entity))
if retry_after > 0:
    raise TelegramPeerRateLimitedError(phone, peer_key(entity), retry_after)
  • A per-peer refusal does not consume the account-wide category slot, so a burst aimed at one peer cannot burn the account budget.
  • peer_key() derives "user:123" / "channel:-100123" / "chat:-456" / "username:durov" / "id:123" from ints, strings, Telethon TL peers, input peers and full entities — purely local attribute access, never a network round-trip.
  • Only send:user, send:channel and send:chat are configured by default; unknown kinds pass through unthrottled. Override or disable via peer_limits (a "send:user" entry with a permissive spec effectively turns it off) and cap memory with peer_max_buckets (LRU, default 4096).
gate = TelegramRateLimitGate(
    peer_limits={"send:user": RateLimitSpec(max_calls=1, window_sec=5.0)},
    peer_max_buckets=4096,
)

TelegramPeerRateLimitedError subclasses TelegramRateLimitedError, so one "operation unavailable, move on" handler covers every layer.

2. Reactive circuit breaker — when Telegram answers anyway

from telethon_floodgate import FloodCircuitBreaker

breaker = FloodCircuitBreaker(threshold=3, cooldown_seconds=300)

breaker.check(operation, phone)            # raises TelegramOperationSuspendedError
                                           # while the pair is suspended
try:
    await client.some_call()
    breaker.record_success(operation, phone)
except telethon.errors.FloodWaitError:
    breaker.record_flood(operation, phone)

After threshold flood waits on the same (operation, phone) the pair is suspended for cooldown_seconds, then exactly one half-open trial call is allowed. TelegramOperationSuspendedError subclasses TelegramRateLimitedError, so a single "operation unavailable, move on" handler covers both layers.

3. Flood-wait helpers — classify, sleep, retry, report

from telethon_floodgate import (
    HandledFloodWaitError, FloodWaitInfo,
    handle_flood_wait, run_with_flood_wait, run_with_flood_wait_retry,
    is_transient_flood_wait_seconds, is_blocking_flood_wait_until,
)

# wraps one awaitable: FloodWaitError -> HandledFloodWaitError (+ pool report)
await run_with_flood_wait(client.get_dialogs(), operation="warm", phone=phone, pool=pool)

# retries transient waits (<=60s) under a total budget (120s default)
await run_with_flood_wait_retry(factory, operation="fetch", phone=phone, pool=pool)

handle_flood_wait reports the wait back to the pool via await pool.report_flood(phone, seconds) so account rotation can skip the flooded account — persist that to your own storage; the library is storage-agnostic.

Design notes

  • Everything runs on one event loop; the limiter state is plain in-memory deques, no locks, no DB.
  • try_acquire never sleeps and never raises — it returns seconds to defer, so callers decide whether to reschedule, skip or await.
  • Atomic multi-slot reservations (try_acquire(..., slots=n)) are supported for compound operations.

License

MIT — see LICENSE. Unofficial third-party library; not affiliated with the Telethon project.

Metadata

Release files for telethon-floodgate 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for telethon-floodgate 0.1.0
File Size Uploaded
telethon_floodgate-0.1.0.tar.gz 27.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for telethon-floodgate 0.1.0
File Interpreter ABI Platform
telethon_floodgate-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 48.3 kB

Release files / telethon_floodgate-0.1.0.tar.gz

Download URL telethon_floodgate-0.1.0.tar.gz
Size 27.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e6fbc92019a2bb2b58bdeea5f6cf66bd3da5a15e88383f9b07702a125d363089
BLAKE2b-256 checksum
How to use checksums
18bcabb6114a702ecddd1ce67132d6f4c9da506423c5056d4fcbc1049965001c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release files / telethon_floodgate-0.1.0-py3-none-any.whl

Download URL telethon_floodgate-0.1.0-py3-none-any.whl
Size 20.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
31449e6cf288196b63159029a40a01c5408c3949d3e04cf3a68be191cec28523
BLAKE2b-256 checksum
How to use checksums
9c2919d55bd9d0d7e7bf5369cf5a72bd2cb5d6a751d0a586b0960f16e6646fce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release history Release notifications | RSS feed

0.1.4

2 release files

0.1.2

2 release files

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page