推荐用 auth=("user", "pass") 参数,requests 自动处理 Base64 编码和 Authorization 头格式;手动拼接易出错,尤其含冒号或非 ASCII 字符时。

Python requests 怎么传 Basic Auth 头
直接在 requests.get() 或 requests.post() 里用 auth 参数最稳妥,requests 会自动拼接 Authorization: Basic base64(username:password)。别手动拼 header,容易漏编码或加错空格。
实操建议:
- 用元组传参:
requests.get(url, auth=("user", "pass"))—— 这是推荐方式,requests 内部处理 base64 编码和 header 格式 - 避免手写
headers={"Authorization": "Basic ..."},除非你确认 base64 编码无误(比如含特殊字符或非 ASCII 用户名时易出错) - 如果用户名或密码含冒号
:,auth元组仍可用,但手动构造 header 会失败 —— 因为 Basic Auth 规范只允许第一个冒号分隔用户/密码
遇到 401 但账号密码没错,可能卡在哪
401 不一定代表凭证错,常见干扰项比想象中多。
排查要点:
立即学习“Python免费学习笔记(深入)”;
- 目标站点是否实际用的是
Bearer Token或 session 登录,而非 Basic Auth?抓包看真实请求的Authorizationheader 类型 - 服务器是否校验
User-Agent?有些服务对无 UA 的 Basic Auth 请求直接拒掉,加个headers={"User-Agent": "Mozilla/5.0"}再试 - URL 是否带 trailing slash?
https://api.example.com/v1/和https://api.example.com/v1可能被当成不同 realm,触发重复鉴权 - 某些 Nginx/Apache 配置下,Basic Auth 的
realm名称大小写敏感,但 requests 不传 realm —— 这通常不影响,除非后端做了非常规校验
用 urllib.request 怎么配 Basic Auth
urllib 没有开箱即用的 auth 参数,得自己注册 HTTPBasicAuthHandler,步骤略繁琐但可控性强。
关键代码片段:
import urllib.request
import urllib.error
<p>auth_handler = urllib.request.HTTPBasicAuthHandler()
auth_handler.add_password(realm=None, uri="<a href="https://www.php.cn/link/b05edd78c294dcf6d960190bf5bde635">https://www.php.cn/link/b05edd78c294dcf6d960190bf5bde635</a>", user="user", passwd="pass")
opener = urllib.request.build_opener(auth_handler)
urllib.request.install_opener(opener)</p><p>try:
resp = urllib.request.urlopen("<a href="https://www.php.cn/link/b05edd78c294dcf6d960190bf5bde635/protected">https://www.php.cn/link/b05edd78c294dcf6d960190bf5bde635/protected</a>")
except urllib.error.HTTPError as e:
print(e.code, e.reason) # 注意这里捕获的是 HTTPError,不是 URLError</p>注意点:
-
realm=None表示不校验 realm,适用于多数情况;若知道确切 realm(比如响应头WWW-Authenticate: Basic realm="API"),就填字符串 - 必须调用
install_opener(),否则urlopen()不走你配的 handler - 错误类型要区分:
HTTPError是服务端返回的 4xx/5xx,URLError是网络层失败(如 DNS 解析失败),别混用 except
Session 复用时 Basic Auth 会不会自动带上
会,但仅限于同一域名下的后续请求 —— requests 的 Session 对象会缓存认证信息,并按 RFC 规则在匹配的 host + port 范围内自动重发 Authorization header。
不过要注意边界情况:
- 子域名不算匹配:从
api.example.com登录后,访问www.example.com不会自动带 Auth header - 端口不同也不算:
http://localhost:8000和http://localhost:8001视为两个 realm - 如果中间跳转(302)到了不同域,requests 默认不会转发 Auth header,需显式设
allow_redirects=True并确认跳转目标是否接受跨域 Auth - Session 复用时,别在后续请求里再传
auth=...,否则会覆盖或冲突
实际用 Basic Auth 抓取时,最难 debug 的往往是服务端没按标准实现 —— 比如要求 header 必须小写、或对 base64 编码结果做额外校验。先用 curl 验证:curl -u user:pass <a href="https://www.php.cn/link/b05edd78c294dcf6d960190bf5bde635/protected">https://www.php.cn/link/b05edd78c294dcf6d960190bf5bde635/protected</a>,再对比 Python 发出的请求头差异。


















