Selenium 代理认证:真正能用的解法
作者:Mechelle Henderson · 发布:2026 年 9 月 7 日 · 阅读约 7 分钟
一句话总结: Chrome 会忽略 --proxy-server 里的 user:pass,弹出一个 Selenium 填不了的登录框。可靠解法是运行时生成一个小 Chrome 扩展,由它设置代理并用你的凭据应答 onAuthRequired —— 配合 --headless=new 无头可用。不想自己写,就用 Selenium Wire 一行搞定。两者都让你从真实住宅 IP 出去。
为什么最直觉的写法用不了
最自然的尝试是把代理写在命令行参数里:
# 这样【不会】认证 —— Chrome 会弹登录框然后卡住。
options.add_argument("--proxy-server=http://USER:[email protected]:41080")
Chrome 不会从 --proxy-server 读凭据。当代理返回 407 Proxy Authentication Required 时,Chrome 弹出一个原生对话框 —— 而 Selenium 无法在操作系统级对话框里输入,请求就一直卡着。你得换一种方式把凭据交给 Chrome。
可靠解法:运行时认证扩展
只要有扩展通过 chrome.webRequest.onAuthRequired 提供凭据,Chrome 就会自己应答那个 407。你不用真发布一个扩展 —— 用两个小文件在内存里构建、打成 zip、加载它即可。无第三方运行时依赖,无头也能用。
import zipfile
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
USER, PASSWORD = "YOUR_USERNAME", "YOUR_PASSWORD"
HOST, PORT = "gw.roamproxy.com", 41080
manifest = """{
"name": "Roam Proxy Auth",
"version": "1.0.0",
"manifest_version": 3,
"permissions": ["proxy", "webRequest", "webRequestAuthProvider"],
"host_permissions": ["<all_urls>"],
"background": { "service_worker": "background.js" }
}"""
background = f"""
chrome.proxy.settings.set({{
value: {{
mode: "fixed_servers",
rules: {{ singleProxy: {{ scheme: "http", host: "{HOST}", port: {PORT} }} }}
}},
scope: "regular"
}});
chrome.webRequest.onAuthRequired.addListener(
() => ({{ authCredentials: {{ username: "{USER}", password: "{PASSWORD}" }} }}),
{{ urls: ["<all_urls>"] }},
["blocking"]
);
"""
with zipfile.ZipFile("roam_proxy_auth.zip", "w") as zp:
zp.writestr("manifest.json", manifest)
zp.writestr("background.js", background)
options = Options()
options.add_argument("--headless=new") # 扩展只在【新版】无头里加载
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_extension("roam_proxy_auth.zip")
driver = webdriver.Chrome(options=options)
driver.get("https://ip.sb")
print(driver.find_element("tag name", "body").text)
driver.quit()
打印出的 IP 应该是 Roam 的住宅出口,而不是你本机的地址。webRequestAuthProvider 权限是让 Manifest V3 扩展能应答认证挑战的关键 —— 没有它,监听器根本不触发。
用 --headless=new,不是旧的 --headless。旧无头模式不加载扩展,这是「桌面能跑、一到服务器就 407」最常见的原因。
一行写法:Selenium Wire
如果能接受一个第三方依赖,Selenium Wire 会替你处理代理认证 —— 它跑一个本地代理注入凭据,你只要传 URL:
from seleniumwire import webdriver # pip install selenium-wire
seleniumwire_options = {
"proxy": {
"http": "http://YOUR_USERNAME:[email protected]:41080",
"https": "http://YOUR_USERNAME:[email protected]:41080",
"no_proxy": "localhost,127.0.0.1",
}
}
driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get("https://ip.sb")
print(driver.find_element("tag name", "body").text)
driver.quit()
代码最少,代价是多一个依赖和一跳本地代理。服务器上长期跑的爬虫,扩展法能让整套栈更精简。
一浏览器一 IP,以及轮换
你启动的每个 Chrome 实例就是一个身份、一个出口 IP。要跑多个身份,就启动多个 driver,给每个用户名一个不同的粘性会话标记(USERNAME_session_1、USERNAME_session_2……),各自拿到一个不同且稳定的住宅 IP。想换新 IP 就换标记。粘性会话原理见什么是轮换代理。
不需要认证的代理
如果你的代理是 IP 白名单、无需登录,上面这些都不用管 —— 裸 --proxy-server=http://host:port 就够了。上面这套折腾,纯粹是因为涉及用户名和密码,而这正是 Roam 按量计费和粘性会话的工作方式。
当问题不在 IP 时
干净的住宅 IP 能解决基于信誉的封锁,但解决不了需要真浏览器的 JavaScript 挑战(而这恰恰是 Selenium 本身就给你的),也解决不了在浏览器之外用脚本发 HTTP 请求时的 TLS 指纹不匹配。如果你是脚本发纯 HTTP 而非驱动浏览器,见用 curl_cffi 获得浏览器级指纹;要针对具体防御选对层次,见如何绕过 Cloudflare。更喜欢 Playwright?同一个代理能直接用在Playwright 和 Puppeteer,而且它们原生支持认证。
常见问题
Selenium 为什么忽略我的代理用户名和密码?
Chrome 不会从 --proxy-server 参数读凭据。当代理返回 407 Proxy Authentication Required 时,Chrome 弹出一个 Selenium 无法输入的原生登录框,请求就卡住了。你必须换种方式提供凭据 —— 用运行时扩展应答 onAuthRequired 事件,或用 Selenium Wire 这类自己代理流量的封装。
不用第三方库怎么在 Selenium 里用带认证的代理?
运行时用两个文件构建一个小 Chrome 扩展 —— 一个 manifest,一个调用 chrome.proxy.settings.set 并从 chrome.webRequest.onAuthRequired 返回 authCredentials 的后台脚本 —— 打成 zip,用 options.add_extension() 加载。这样 Chrome 会自己应答代理的 407 挑战,不再弹框。配合 --headless=new 无头可用。
扩展法在无头 Selenium 里能用吗?
能,但要用新版无头模式。加 --headless=new(不是旧的 --headless)才能加载扩展,服务器上再保留 --no-sandbox 和 --disable-dev-shm-usage。旧无头模式不加载扩展,这正是「桌面能跑、服务器上一无头就 407」的原因。
用 SOCKS5 代理能不能避开弹框?
只有当代理不需要用户名密码时才行。Chrome 接受 --proxy-server=socks5://host:port 连不带认证的代理,但它同样无法从参数发送 SOCKS5 凭据。Roam 是带用户名密码的,所以走 HTTP 用扩展或 Selenium Wire,别试图把凭据塞进 SOCKS URL。
Roam 给你的就是一个带用户名密码的 host:port 网关 —— 上面这些把它变成一个能跑的 Selenium 会话。轮换住宅 $2/GB、静态住宅 $4/IP/月,支持 HTTP 和 SOCKS5,粘性会话做到一浏览器一 IP。注册账号,拿 300MB 免费试用流量,让你的第一个 driver 从住宅出口出去。