基于PyTelegramBotAPI的Telegram机器人调用download_file方法出现HTTP 403 Forbidden错误的排查求助
从你描述的情况来看,机器人只有调用download_file()下载文档时触发403 Forbidden(由nginx返回),其他功能完全正常,而且重置API令牌也没用,这说明问题不在令牌本身,大概率和文件下载的URL处理、Telegram文件服务的限制,或者旧版本库的bug有关。下面是几个最可能的原因和对应的解决办法:
1. 文件路径未做URL编码处理
Telegram返回的file_path可能包含空格、非ASCII字符(比如中文文件名)等特殊内容,而你使用的pyTelegramBotAPI 4.3.1版本可能没有自动对这些字符进行URL编码,导致请求的URL格式不合法,被Telegram的nginx服务器拦截返回403。
解决方法:在使用file_path之前,用Python的urllib.parse.quote()对其进行编码:
from urllib.parse import quote def handling_documents(message): def save_file(): file_info = bot.get_file(message.document.file_id) # 对文件路径进行URL编码 encoded_file_path = quote(file_info.file_path) downloaded_file = bot.download_file(encoded_file_path) filename = message.document.file_name # 后续保存文件的逻辑
2. 机器人IP被Telegram文件服务限制
即使你重置了API令牌,Telegram的文件服务可能因为短时间内下载请求过于频繁,把你的服务器IP加入了临时限制名单,导致下载请求被拒绝。
解决方法:
- 检查机器人的下载请求频率,如果是批量下载操作,尝试添加请求间隔(比如每次下载后
time.sleep(1)),避免触发流量限制; - 尝试更换服务器IP(或者使用代理)后重新测试;
- 如果上述方法无效,可以尝试联系Telegram官方支持,确认IP是否被列入黑名单。
3. 旧版本pyTelegramBotAPI的已知bug
你使用的4.3.1版本是2021年的旧版本,后续版本已经修复了不少文件下载相关的问题,包括URL编码、请求头设置等。
解决方法:直接升级到最新稳定版本:
pip install --upgrade pyTelegramBotAPI
升级后再测试download_file()方法,大概率能解决403问题。
4. 请求头不符合Telegram服务器要求
旧版本的库可能在请求文件时没有设置规范的请求头(比如缺少合理的User-Agent),导致nginx服务器判定请求不合法,返回403。
解决方法:绕开库的download_file()方法,用requests库手动发送请求并自定义请求头:
import requests def handling_documents(message): def save_file(): file_info = bot.get_file(message.document.file_id) # 拼接完整的文件下载URL file_url = f"https://api.telegram.org/file/bot{bot.token}/{file_info.file_path}" # 设置符合规范的请求头 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36" } response = requests.get(file_url, headers=headers) if response.status_code == 200: downloaded_file = response.content filename = message.document.file_name # 后续保存文件的逻辑 else: # 处理错误情况 print(f"下载失败,状态码:{response.status_code}")
5. 特定文档被Telegram封禁
虽然概率较低,但有可能用户发送的文档被Telegram标记为违规内容,对应的文件资源被封禁,导致无法下载。
解决方法:自己发送一个普通的、无违规内容的文档(比如空白的txt文件)给机器人,测试是否能正常下载。如果测试文档可以,说明是特定用户的文档问题;如果测试文档也不行,就可以排除这个原因。
内容的提问来源于stack exchange,提问作者Фёдор Кузнецов

