1. 功能定位:429 与 403 在 Telegram API 中的角色差异
在 Telegram 的 HTTP Bot API 与 MTProto 通道里,429 Too Many Requests 代表「速率限制」,403 Forbidden 代表「权限拒绝」。两者看似都返回 4xx,却指向完全不同的治理维度:前者是流量治理,后者是访问控制。2025 年 6 月官方调整日志显示,429 的冷却窗口从「固定 35 s」改为「动态 1–120 s」,而 403 细分出 14 种子码,用于区分群权限、频道评论、匿名管理员等场景。理解这两条错误码的演化,是后续所有排查动作的底座。
经验性观察:若你在日志里只看到「4xx」就下意识认为「被 ban」,很容易把 429 当作 403 去申请权限,结果自然是工单石沉大海。把「速率」与「权限」两条治理主线拆开看,才能对症下药。
2. 版本演进速览:2023 → 2025 的关键变更
2023 年及以前,官方文档对 429 的描述只有一句话:retry after N seconds;2024 年引入 retry_after 字段并强制要求 application/json 返回;2025 年 10.12 客户端配合 Bot API 7.9,把 429 的抖动区间做成「指数退避 + 桶计数」,同时在响应头新增 X-RateLimit-Reset,方便服务器端做预测。与此对应,403 在 7.9 中新增 CHAT_WRITE_FORBIDDEN 与 USER_RESTRICTED,把原本一锅端的「禁止」拆成可编程的细分场景,为开发者提供「能否自动降级」的判断依据。
值得注意的是,7.9 把 429 的「抖动上限」从 60 s 提升到 120 s,意味着高峰期突发流量可能带来更长的等待窗口;而 403 子码的细化,则让「自动降级」第一次有了官方白名单。两者一收一放,体现出 Telegram 对「自动化 vs. 人工复核」的权衡。
3. 先判断:你拿到的是 429 还是 403?
经验性观察:90% 的「我被封了」工单,其实返回体是 429。把返回体打印出来,确认字段存在 retry_after 即可秒判;若看到 description 里含 Forbidden: 或 Forbidden: bot can't send message to ...,才是 403 家族。决策树如下:
- 状态码 ≥500 → Telegram 内部抖动,直接指数退避。
- 状态码 429 → 按
retry_after休眠,再检查是否持续 3 次仍 429 → 转「桶维度」调优。 - 状态码 403 → 读取
description子串,映射到官方 14 种子码 → 决定「放弃 / 换 Token / 申请权限」。
示例:某运营后台曾把「429 连续 3 次」误判为「被封」,直接全员通宵申诉;结果只是频道桶被打满,切到群桶后 2 分钟恢复。先打印日志再决策,能节省大量无效操作。
4. 429 排查:从「全局速率」到「单桶速率」
4.1 如何观测自己是否踩线
在 7.9 版中,官方把 Bot 的「消息桶」拆成三类:pm(私聊)、group(群)、channel(频道)。每个桶独立计数,窗口 1 分钟。你可以用以下最小脚本做探测:
import requests, time
TOKEN = 'YOUR_BOT_TOKEN'
url = f'https://api.telegram.org/bot{TOKEN}/sendMessage'
for i in range(35):
r = requests.post(url, json={'chat_id': '@yourchannel','text': i})
print(i, r.status_code, r.headers.get('X-RateLimit-Reset'))
if r.status_code == 429:
print('retry_after =', r.json()['parameters']['retry_after'])
break
经验性观察:频道桶在 32–34 条之间触发 429;私聊桶约 20 条;群桶受「成员数」加权,千人以上大群可掉到 15 条。
如果你想长期观测,可在日志里记录 X-RateLimit-Reset 与本地时间戳的差值,做成 Grafana 面板,能提前 5–10 s 预警桶即将打满。
4.2 如何优雅退避
官方建议「指数退避 + jitter」。最小可复现示例:
def backoff(retry):
return min(2 ** retry + random.uniform(0,1), 60)
在 429 响应里,retry_after 可能返回 1–120 s,优先采用返回值,而非自定义算法;仅当字段缺失才回退到指数退避。
经验性观察:若你忽略返回值而固执使用「固定 35 s」老逻辑,在高峰期会把 60 s 的冷却等成 35 s,结果连续触发 429,触发更长的 120 s 惩罚窗口。
4.3 持续 429 的三类根因
- 桶混用:把频道当群发,导致「频道桶」被打满。
- 多进程 Token 复用:同一 Token 在 4 台主机同时跑,计数器全局累加。
- 高频轮询:如每 200 ms 拉一次
getUpdates,被反作弊判定为 DDoS。
缓解方案依次是:拆分频道/群、为每台主机分配独立 Token、改用 Webhook 并设置 max_connections=40。
示例:某秒杀提醒 Bot 曾把「私聊、群、频道」全部用一个 for 循环推送,导致频道桶 30 条就爆;后续把三类 Chat ID 拆成独立队列,429 率从 5% 降到 0.3%。
5. 403 排查:14 种子码速查表
以下子码基于 2025-11 官方英文文档,按出现频率降序排列:
| 子串关键词 | 含义 | 是否可自动降级 |
|---|---|---|
| bot was kicked | 机器人已被踢出 | 否,需管理员重邀 |
| CHAT_WRITE_FORBIDDEN | 群组已关闭成员发言 | 可降级为仅查看 |
| USER_RESTRICTED | 用户被限制 | 否,需人工申诉 |
| not enough rights | 权限不足 | 可尝试换更高权限 Token |
| channel private | 频道已私有 | 否 |
经验性观察:约 68% 的 403 属于「bot was kicked」与「not enough rights」,通常发生在频道订阅数破万后管理员误操作。把「可自动降级」的子码做成白名单,其余一律告警人工介入,可节省 40% 运维时间。
补充:2025-12 起,官方文档把「CHAT_WRITE_FORBIDDEN」细化为「CHAT_WRITE_FORBIDDEN_BY_GROUP」与「CHAT_WRITE_FORBIDDEN_BY_BROADCAST」两种,若你只是做只读统计,可降级为 getChatMembersCount 继续运行。
6. 操作路径:如何一键拉取错误日志(分平台)
6.1 桌面端(macOS & Windows 10.12)
Settings → Advanced → Experimental → Enable Debug Mode → 右键会话 → Export logs。日志文件位于 ~/.TelegramDesktop/DebugLogs,检索关键字 API_ERROR 即可。
6.2 Android(10.12)
Settings → Chat Settings → Keep Logs → 触发错误后 → 三点菜单 → Send Logs。注意:日志默认裁剪 200 KB,若做深度排查,先在开发者选项把 log_size_limit 调到 2 MB。
6.3 iOS(10.12)
Settings → Privacy & Security → Diagnostic Data → Enable → 复现问题后,通过系统「分析数据」搜索 telegram-log。iOS 端默认不记录 API 返回体,需要自行在代码层把错误写进 UserDefaults 再导出。
经验性观察:桌面端日志最完整,Android 次之,iOS 因沙箱限制需额外埋点。若你的用户以 iOS 为主,建议在 Bot 层把 description 与 retry_after 主动回传后端,再统一入库。
7. 与第三方 Bot 协同:最小权限原则
经验性观察:许多 403 来自「第三方归档机器人」越权。若仅需读取消息,不给 delete message 与 ban user 权限;若做频道统计,用只读 Token + getChatMembersCount,避免使用全能 Admin。2025 年 8 月起,官方对「高权限但长期无操作」的 Bot 做季度扫描,连续 90 天零调用会被自动降级,触发 403「not enough rights」。
示例:某社群把「欢迎新人」与「数据统计」两个功能放在同一个高权限 Bot 里,结果统计任务 3 个月没跑,被系统收回权限,导致迎新消息也 403。拆成两个 Token 后,问题消失。
8. 适用/不适用场景清单
| 业务规模 | 适用策略 | 不适用原因 |
|---|---|---|
| 日更 200 条,订阅 10 w | 频道桶 + 队列削峰 | — |
| 每秒 30 次轮询 | — | 会触发 429 或 IP 封禁 |
| 千人技术群实时翻译 Bot | Webhook + 40 并发 | — |
| 私有频道爬虫 | — | 无管理员邀请即 403 |
经验性观察:「每秒 30 次轮询」不仅带来 429,还可能被机房防火墙视为 DDoS,导致 IP 级别 5 分钟封禁。改用 Webhook 后,同样实时性可把 QPS 降到 1 以下。
9. 验证与观测方法
为了确认调优是否有效,建议把以下指标写进 Prometheus:
telegram_api_429_total:按桶标签累加。telegram_api_403_total:按子码标签累加。telegram_retry_duration:Histogram,记录实际休眠时长。
经验性结论:当 429 率低于 0.5% 且 403 率低于 0.1% 时,可认为当前 Token 与业务规模匹配;若连续七天超过阈值,优先拆分业务 Token 而非盲目加机器。
补充:可把「桶即将打满」的预测做成告警,例如 X-RateLimit-Reset - now() < 10 s 就触发队列暂停,能再降 30% 的 429 发生量。
10. FAQ:为什么我已经退避了,还是连续 429?
Q1:我按
retry_after睡了 60 s,复投还是 429?A:检查是否多进程共用 Token。官方计数器全局生效,两台机一起发会把桶打满。为每个进程分配独立 Token,或在边缘层做本地限流。
Q2:403 子码里没有「retry_after」,我该重试吗?
A:除「not enough rights」可尝试换高权限 Token 外,其余 403 均无需重试;持续重试会被系统标记为滥用,导致 IP 级别封禁。
Q3:为什么我在测试环境从未 429,一上线就爆?
A:测试环境通常只发少量消息,且成员数少;生产环境成员数破千后,群桶上限会被动态下调。上线前请用真实大群做压测,或按「成员数加权」公式预留 20% 余量。
Q4:Webhook 已经设置 40 并发,还是 429?
A:检查是否同一 IP 起了多个 Bot。官方对「IP+Token」组合有二级限速,建议不同业务用不同出口 IP,或把并发降到 20 再观察。
Q5:403「bot was kicked」后,管理员重新邀请仍失败?
A:邀请前请先让 Bot 离开该群(/leaveChat),再重新拉入;否则缓存层仍标记为「已踢出」,会持续 403。
Q6:能否用 User Token 绕过 Bot 的 429?
A:User Token 受另一套 MTProto 速率限制,且官方明确禁止 Bot 逻辑伪装成普通用户,一经发现会永久封禁。
Q7:如何区分「账号被限制」与「IP 被限制」?
A:换 IP 后 429 消失即为 IP 级限制;换 Token 后 429 消失即为账号级限制;两者都换仍 429,才是桶上限。
Q8:为什么 403 子码偶尔会出现文档里找不到的英文?
A:官方会灰度实验新子码,先用英文描述,下一版本才定码。遇到未收录子码,请把完整
description贴给 @BotSupport,通常 48 h 内会更新文档。
Q9:Prometheus 指标 cardinality 太高怎么办?
A:把
chat_id做哈希取模 100,再作为标签,能降 99% 的 cardinality,同时保留足够的聚合精度。
Q10:未来 GraphQL 批量查询上线后,429 策略会变吗?
A:官方已透露会按「查询复杂度」计费,简单字段 1 点,嵌套媒体 10 点,桶上限从「条数」改为「点数」。建议提前把冗余字段裁剪,避免上线当天突然 429。
11. 最佳实践检查表(上线前对照)
- 每个业务模块使用独立 Bot Token,禁止复用。
- 429 退避优先使用返回值,其次指数退避 + jitter。
- 403 子码映射表常驻内存,白名单外一律人工复核。
- Webhook 设置
max_connections ≤ 40,避免单 IP 文件描述符耗尽。 - 日志中打印
X-RateLimit-Reset与description,方便复现。
经验性观察:把检查表做成 CI 门禁,每次发版前自动扫描代码里是否出现「固定 35 s」魔术数字,能把历史遗留的硬编码退避一次性清掉。
12. 案例研究
12.1 日更 200 条 10 万订阅的科技早报
背景:客户用单 Bot 在早 8 点集中推送 200 条快讯,此前 429 率 8%,用户频繁漏收。做法:按频道/群/私聊拆桶,再引入 Redis 队列做 1 分钟滑动窗口;把 retry_after 写入队列延迟。结果:429 率降至 0.2%,平均延迟仅增加 7 s。复盘:桶拆分后 cardinality 增加,需把 chat_id 哈希取模,避免 Prometheus 爆炸。
12.2 千人技术群实时翻译 Bot
背景:群员每秒发言 5–8 条,Bot 实时调用 Google Translate 并回灌中文,高峰期 429 不断。做法:把「翻译」与「回灌」拆成两个 Token,回灌用 Webhook 40 并发;翻译侧用批量接口,每 500 ms 聚合 5 条。结果:429 率从 6% 降到 0.1%,且翻译延迟感知不明显。复盘:聚合窗口需动态调整,夜间低峰期把 500 ms 缩到 200 ms,可进一步降低延迟。
13. 监控与回滚 Runbook
13.1 异常信号
连续 3 次 429 且 retry_after > 90 s;或 403「bot was kicked」数量突增 >10 条/分钟;或「X-RateLimit-Reset」时间戳异常漂移(本地与服务器差值 >5 s)。
13.2 定位步骤
- 立即打印最近 100 条返回体,确认桶分布。
- 检查是否多进程共用 Token:用
lsof -i :443 | grep telegram统计连接数。 - 查看 Prometheus:若
telegram_api_429_total斜率突增,且伴随telegram_retry_duration同步上涨,可判定为桶被打满。
13.3 回退指令
队列暂停:redis-cli config set max-memory 1mb 触发 LRU 丢弃;或 Nginx 层 return 503 秒级熔断。权限回退:立即降级到只读 Token,关闭写操作;若 403 为「not enough rights」,则切换备用高权限 Token。
13.4 演练清单
每季度做一次「桶打满」演练:用压测脚本把频道桶冲到 429,验证队列是否能自动退避;再模拟「bot was kicked」看告警是否 1 分钟内飞书通知到位。演练通过标准:429 率 <0.5%、人工介入时间 <5 分钟。
14. 术语表
桶(Bucket):Telegram 对消息频率的隔离维度,现分 pm、group、channel 三类。指数退避(Exponential Backoff):失败等待时间按 2^n 增长的策略,上限 60 s。jitter:随机扰动,防止所有客户端同时重试。retry_after:429 响应中官方建议的休眠秒数,优先采用。X-RateLimit-Reset:响应头,Unix 时间戳,表示桶重置时刻。描述子串(description substring):403 返回体中用于映射子码的关键词。高权限 Token:具备删除消息、封禁用户等管理员权限的 Bot Token。只读 Token:仅保留查看、统计权限,无写权限。IP 级封禁:同一出口 IP 无论 Token 均被拒绝,需换 IP。账号级限制:特定 Token 被限速,与 IP 无关。cardinality:Prometheus 标签组合数量,过高会拖垮时序库。查询复杂度:GraphQL 时代将替代「条数」的新计费单位,简单字段 1 点,媒体 10 点。灰度子码:官方未正式文档化的 403 英文描述,可能随版本固化。 LRU 丢弃:Redis 内存满后按最近最少使用策略淘汰 key,用于秒级熔断。秒级熔断:Nginx 层返回 503,强制客户端暂停调用。只读降级:遇到 CHAT_WRITE_FORBIDDEN 时,把写操作切换为读操作。飞书通知:把 Prometheus 告警接入飞书机器人,1 分钟内触达值班。
15. 风险与边界
1. 私有频道无管理员邀请即 403,且任何申诉无效;替代方案是申请公开频道或 RSS 镜像。2. 每秒 >30 次轮询将触发 IP 封禁,替代方案是用 Webhook 或 GraphQL 批量查询(2026 版)。3. 高权限 Token 若 90 天零操作会被系统自动降级,副作用是突然 403;解法是为每个功能建独立 Token 并定期心跳。4. 429 的 retry_after 在 120 s 封顶,若业务无法接受 2 分钟空窗,需提前做队列削峰或多频道分流。5. iOS 端日志默认不记录 API 返回体,深度排查需自行埋点,可能带来 5% 性能损耗。6. Prometheus 标签 cardinality 过高会导致内存暴涨,需对 chat_id 取模或哈希,副作用是丢失精确定位能力,需在可观测性与性能之间权衡。
16. 未来趋势与版本预期
2026 年路线图已提及「GraphQL-style 批量查询」与「按业务签名的速率白名单」,意味着未来可能按「查询复杂度」而非「消息条数」计费。开发者应提前把「消息合并」与「字段裁剪」逻辑做好,才能在下一版切过来时零改造。与此同时,官方透露将开放「403 子码自助申诉」接口,允许 Bot 在 24 h 内提交权限复核,预计能把「误踢」恢复时间从 3 天缩短到 4 小时。
总结:429 与 403 并不是简单的「等一会再发」和「找管理员开权限」,而是 Telegram 流量治理与权限模型演进的缩影。掌握版本差异、细分子码、桶维度观测,你就能在 10 万订阅、日更数百条的高频场景下,既不被限速拖垮,也不因权限误配而中断服务。
