如何使用 Java Selenium ChromeDriver 通过 Cloudflare bot checking?
结论
Java Selenium 没有通用配置能稳定”通过” Cloudflare bot checking。把 Python 示例改写成 Java,或补上 Accept、Accept-Language 等请求头,都解决不了这个问题。
Cloudflare 判断请求时,会综合浏览器端 JavaScript 的执行结果、Cookie、浏览器环境、IP、TLS 特征和其他安全信号。JavaScript 检测通过后,其他规则仍可能拦截请求。Cloudflare 官方文档也说明,JavaScript 检测结果只是机器人判定依据之一。
如果目标网站不属于你,合规的处理方式包括:
- 使用没有经过伪装的标准 Chrome。
- 不修改浏览器指纹和客户端提示请求头。
- 出现交互式验证时,让用户在可见的浏览器中完成。
- 由 Selenium 等待验证结束,然后继续操作页面。
- 如果验证不断循环,停止自动访问,并联系网站运营方申请授权或放行。
隐藏 WebDriver、伪造指纹、自动点击验证控件或复制 cf_clearance Cookie 都是在规避站点防护,也无法保证长期有效。
为什么添加 Request headers 没有效果
当前代码只修改了 HTTP 请求头,而 Cloudflare Challenge 会在浏览器中运行 JavaScript,并收集客户端信号。请求头只占其中很小一部分。
这段过滤器还可能造成请求信息相互矛盾:
request.headers().add("Platform", "Win64");
Platform 不是 Chromium 使用的标准 Client Hint。Chromium 可能发送 Sec-CH-UA-Platform,但这个字段应由浏览器根据真实环境生成,不适合手动伪造。
如果原请求已经包含同名字段,add() 还会追加一个值。例如,Chromium 已经设置了 Accept-Encoding,代理再次添加后就可能产生重复字段。Connection、Accept-Encoding 和 Client Hint 等请求头应由浏览器管理。
setAcceptInsecureCerts(true) 对 Cloudflare 验证也没有帮助。它只会让 WebDriver 接受无效或不受信任的 TLS 证书。只有代理确实在进行 TLS 中间人解密时,才可能需要这项设置。更合适的做法是安装并信任代理的 CA 证书。
Java 中可以采用的处理方式
移除 BrowserMobProxy 和手工添加的请求头,让 Chrome 使用正常的网络栈。启动可见浏览器后,等待目标页面中稳定的业务元素出现。如果 Cloudflare 要求交互,用户可以直接在浏览器窗口中完成验证。
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class Main {
public static void main(String[] args) {
ChromeOptions options = new ChromeOptions();
options.setPageLoadStrategy(PageLoadStrategy.NORMAL);
options.setPageLoadTimeout(Duration.ofSeconds(60));
options.setScriptTimeout(Duration.ofSeconds(30));
WebDriver driver = new ChromeDriver(options);
try {
driver.get("https://solscan.io/");
/*
* 必须替换为目标业务页面上稳定且唯一的元素。
* 不要使用 Cloudflare 验证页面中的元素作为成功条件。
*/
By applicationReady =
By.cssSelector("#replace-with-a-stable-selector");
WebDriverWait wait =
new WebDriverWait(driver, Duration.ofMinutes(2));
wait.until(
ExpectedConditions.visibilityOfElementLocated(
applicationReady
)
);
System.out.println("目标页面已经加载,可以继续执行测试。");
} catch (TimeoutException e) {
saveScreenshot(driver, "challenge-timeout.png");
throw new IllegalStateException(
"等待目标页面超时。页面可能仍处于 Cloudflare 验证状态。",
e
);
} finally {
driver.quit();
}
}
private static void saveScreenshot(WebDriver driver, String fileName) {
byte[] image = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.BYTES);
try {
Files.write(Path.of(fileName), image);
} catch (IOException e) {
System.err.println("保存截图失败: " + e.getMessage());
}
}
}
#replace-with-a-stable-selector 是占位符,需要替换为验证成功后才会出现在业务页面中的元素,比如页面的主搜索框、账户导航栏或应用根节点。
这段代码不会自动操作 Cloudflare 验证控件,只会等待正常浏览器完成验证,并在超时时保存截图。
现有代码还需要注意什么
setPageLoadTimeout() 只控制等待页面加载的时间,不会限制 Cloudflare 脚本的执行时间。
setScriptTimeout() 主要控制 Selenium 执行异步 JavaScript 时的超时,也无法决定 Cloudflare Challenge 能否通过。
Cloudflare 官方列出的验证循环原因包括 JavaScript 被阻止、Cookie 或 DOM Storage 不可用、网络不稳定、User-Agent 在会话中发生变化,以及浏览器表现出明显的自动化信号。更换请求头通常解决不了这些问题,还可能造成新的信息不一致。具体可参考验证循环排查说明。
如果必须使用公司代理,可以继续配置常规的 Selenium Proxy,但建议删除 addRequestFilter() 中改写请求头的代码。代理出口 IP 信誉较差或由多人共享时,也可能频繁触发验证。
如果目标网站由你管理
自动化测试不应针对生产环境中的真实 Challenge 编写”解题”逻辑。可以这样处理:
- 在测试环境关闭相应的 WAF Challenge,或为受控的 CI 出口设置明确的放行规则。
- 页面使用 Turnstile 时,改用 Cloudflare 提供的测试 sitekey 和测试 secret key。
- 分开测试真实安全规则和业务页面的 Selenium 流程。
- 生产环境继续使用真实验证,避免测试配置进入生产部署。
Cloudflare 明确说明,Selenium 等自动化工具可能被 Turnstile 识别为机器人,因此提供了专用的测试密钥。这些测试密钥只能用于自己控制的环境,生产 secret key 不会接受测试 token。具体可参考Turnstile 自动化测试说明。
Java 仓库和参考资料
SeleniumHQ/selenium 是 Selenium 官方仓库,包含 Java bindings、测试代码和示例。Java bindings 使用说明介绍了依赖配置和基本用法。
Cloudflare 和 Selenium 都没有官方维护的”绕过 Cloudflare” Java 仓库。声称可以稳定绕过检测的第三方项目,通常依赖隐藏自动化特征或伪造浏览器指纹。此类方案容易随着 Cloudflare、Chrome 或 ChromeDriver 更新而失效,也可能违反目标网站的使用规则。
备注:内容仅供参考。
