
Adélia Cruz
MCP Integration Engineer
已发表 Oct 23, 2026
已更新 Oct 23, 2026 · 最小阅读量

自托管浏览器可以导航到正确页面,却仍然让你的流程卡在 CAPTCHA 上。如果你在本地运行 Steel,仅添加云服务的求解开关是不够的:本地部署和云部署的能力不同。
本指南展示在自托管 Steel Browser 中 CAPTCHA 求解器处于哪个位置,并用一个简短的 Python 连接检查来验证。示例使用本地开发页面和 Google 公共 reCAPTCHA 测试密钥。它不针对第三方网站,也不需要使用任何 AI 模型。
Steel Browser 是为构建 Web Agent 和自动化应用的开发者提供的浏览器 API。它负责管理一个浏览器会话,客户端可以通过熟悉的自动化工具来控制该会话。Steel 官方仓库文档中包含自托管说明,以及来自 Playwright、Puppeteer 和 Selenium 的连接方法。
对于运行已授权表单流程的开发者,分工很清晰:Steel 提供浏览器;Playwright 负责页面导航和交互;CAPTCHA 求解器在遇到支持的挑战时进行处理;随后你的流程检查应用是否接受了预期操作。
本教程在 CAPTCHA 步骤中使用 CapSolver Core SDK。该 SDK 可以检查一个 Playwright 页面,并提供一个独立的求解操作。无需引入 LLM 仅为了将这些组件连接在一起。
实际场景是:你已经有一个需要 CAPTCHA 操作的自托管浏览器任务。对于你所拥有软件的常规测试,CAPTCHA 厂商提供的测试设置就可能足够。只有在授权流程确实需要时再走求解路径,而不是让每一次浏览器导航都依赖付费请求。
Steel Local 不包含云产品中的内置 CAPTCHA 求解功能。Steel 的 本地与云端功能对比表 明确区分了这两种部署。
这种差异会影响实现方式。云端教程可能在会话创建时启用求解,而自托管集成必须自行补上这一缺失操作。不要假设云端配置字段在本地服务器上也能激活同一功能。
本文使用的路径是:
websocketUrl。避免在步骤三中启动一个无关的浏览器。第二个浏览器不会是 Steel 返回的那个会话,这会让你很容易在检查一个页面的同时,真正的任务却卡在另一个页面。
前提是:有一个正在运行的独立 Steel Local 实例,以及 Python 3.12。已验证的环境使用了 Steel API 0.5.3(仓库修订版本 8362bbd)、Playwright 1.64.0 和 capsolver-core 0.1.1,系统为 macOS。
按照仓库中的本地部署说明搭建你的环境。对于本文使用的基于源码的服务器,API 是在 HOST=127.0.0.1、PORT=3300 和 CDP_REDIRECT_PORT=9323 下启动的。这些是测试环境使用的端口,而不是强制默认值。确保你的开发 API 只对预期客户端可达。
在隔离环境中安装 Python 依赖:
python -m pip install "playwright==1.64.0" "capsolver-core==0.1.1" "httpx==0.28.1"
Steel 负责启动浏览器,因此这个客户端不会再启动另一个 Chromium 实例。Playwright 的 CDP 连接方法 会附着到已存在的基于 Chromium 的浏览器上,并暴露其默认上下文。
客户端还需要能访问返回的 WebSocket 地址。如果 Steel 运行在容器或另一台机器上,确认该地址对 Python 进程是可达的;127.0.0.1 始终指向发起连接的那台机器。
下文的检测检查不需要 CapSolver 凭据。真正的求解需要你自己有效的 API 密钥和账户额度。付费求解、Token 回填以及应用是否接受结果,均未在本指南中执行。请将这一步单独列入你的部署验证清单中。
该脚本会创建一个真实的 Steel 会话,连接到其浏览器,并通过官方 SDK 读取一个开发用小组件。将脚本保存为 steel_sdk_check.py 并用 Python 运行。
示例默认连接运行在 3300 端口上的本地服务器。如果你的服务器使用了另一个地址,请设置 STEEL_URL。请使用独立实例:会话创建与释放会改变该实例的活动浏览器会话。
页面通过 Playwright 路由提供,因此在 8765 端口上不需要独立 Web 服务器。Google 的小组件脚本仍然需要网络访问。公共站点密钥在 Google 的 reCAPTCHA 测试说明中有文档记录,仅供开发使用,不适合生产。
import asyncio
import json
import os
import httpx
from capsolver_core import create_capsolver
from playwright.async_api import async_playwright
STEEL_URL = os.environ.get("STEEL_URL", "http://127.0.0.1:3300")
TEST_URL = "http://127.0.0.1:8765/"
HTML = """<!doctype html><html><head><title>Steel CAPTCHA check</title></head>
<body><h1>Owned development page</h1>
<div class="g-recaptcha" data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"></div>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</body></html>"""
async def main():
async with httpx.AsyncClient(base_url=STEEL_URL, timeout=90) as api:
response = await api.post("/v1/sessions", json={"headless": True})
response.raise_for_status()
session = response.json()
try:
async with async_playwright() as playwright:
browser = await playwright.chromium.connect_over_cdp(session["websocketUrl"])
try:
context = browser.contexts[0]
page = await context.new_page()
await page.route(TEST_URL, lambda route: route.fulfill(
content_type="text/html", body=HTML))
await page.goto(TEST_URL)
await page.wait_for_function(
"() => !!window.___grecaptcha_cfg && "
"Object.keys(window.___grecaptcha_cfg.clients || {}).length > 0",
timeout=30000)
async with create_capsolver() as cap:
infos = await cap.get_captcha_info(page)
result = [{"type": info.type.value,
"url": info.website_url,
"site_key": info.website_key} for info in infos]
print(json.dumps({"session_id": session["id"],
"captcha_parameters": result}))
assert result and result[0]["type"] == "reCaptchaV2"
finally:
await browser.close()
finally:
released = await api.post(f"/v1/sessions/{session['id']}/release")
released.raise_for_status()
print(json.dumps({"released": released.json().get("success")}))
if __name__ == "__main__":
asyncio.run(main())
实际执行的检查返回了一个 reCaptchaV2 描述符,其中包含本地页面 URL 和公共测试站点密钥。最终的释放响应返回 true。这些现象验证了真实 Steel 会话、CDP 连接、页面访问以及 SDK 读取参数的路径。
它们并不能说明付费 CAPTCHA 已被求解。开发密钥并非生产挑战,本脚本也刻意没有请求解决 Token。
代码保持页面处于 Steel 现有浏览器上下文中。清理逻辑会关闭客户端连接,并在检测失败时仍然请求服务器释放会话。如果你将其改造成共享服务,请让单一组件负责会话生命周期,而不是让互不相关的任务互相释放对方的工作会话。
在你的授权业务页面加载出其支持的 CAPTCHA 且浏览器连接和 SDK 客户端仍然存活时,添加求解调用。请用你的应用流程替换本地开发用页面,不要在生产环境中使用测试密钥。
按文档说明使用 api_key 选项创建 SDK 客户端,从受控的密钥配置中加载凭据。CapSolver 负责处理挑战请求,而 Steel 继续拥有浏览器会话。
下面这一行是官方“浏览器模式”原样调用。它需要已配置好的 API 密钥,通过本教程的 Steel 连接进行付费执行时 未做测试:
results = await cap.solve_on_page(page)
将调用放在客户端上下文有效期内。若将其粘贴到示例清理代码之后,指向的将是已关闭的浏览器和客户端。
在继续前检查每个返回结果。SDK 会报告 error、可能存在的 solution 以及是否完成回填的 filled。空结果或缺失的 solution 并不能证明你的应用已经通过了 CAPTCHA。
Core SDK 中记录的 Token 模式覆盖 reCAPTCHA v2/v3 和 Cloudflare Turnstile。不要假设同一个调用可以解决 CapSolver 更宽泛 API 文档里所有挑战类型。reCAPTCHA v2 任务文档给出了该支持路径下的任务特定要求。
只有当应用达到预期状态时,整个流程才算完成。Token 响应、字段填充和表单提交成功是三种不同的观察结果。
对于你可控的应用,请选择一个明确的成功信号,例如确认消息或预期响应。在完成正常表单动作后等待这一信号。如果没有出现,应检查应用响应,而不是在不了解失败原因的情况下盲目重复求解请求。
在操作过程中保持页面身份稳定。在求解进行中不要导航离开、关闭标签或释放会话。如果应用重新加载小组件,请再次检查当前挑战,而不是复用之前页面状态中的参数。
CAPTCHA 术语表解释了验证的核心概念,而关于 CAPTCHA Token 和 Cookie 的指南则有助于区分不同输出。无论是浏览器 Cookie 还是 Token 字符串,都不应替代你对应用自身成功状态的检查。
从最早失败的操作开始排查问题,避免连接故障演变成不必要的求解请求。
| 症状 | 检查内容 |
|---|---|
| 会话创建失败 | 确认 Steel API 正在运行,并检查 HTTP 状态和服务器日志。 |
| CDP 连接失败 | 检查 websocketUrl 是否能从 Python 进程访问,且属于当前会话。 |
| 小组件始终未初始化 | 检查浏览器是否能访问 Google 的开发脚本,并确认加载的是预期页面。 |
| 检测未返回任何描述符 | 在尝试付费求解前,检查当前页面以及支持的 CAPTCHA 类型。 |
| 返回了求解结果但流程停滞 | 检查回填、正常业务操作以及应用响应。 |
| 其他任务丢失其浏览器会话 | 在共享本地实例前,梳理会话所有权和释放调用。 |
保持诊断日志精简。记录阶段和脱敏后的错误信息,而不是 API 密钥、响应 Token 或完整浏览器存储。先只测试单个页面,仅在确认某类临时失败可以通过重试合理解决后,再加入重试逻辑。
Steel Local 集成需要在托管浏览器页面和 CAPTCHA 操作之间建立清晰的交接。本文通过一个不发起付费请求的连接检查验证了这一交接。在用于生产前,请使用你自己的凭据验证实际求解,并在授权环境中确认应用结果。
让会话在完成其工作前保持开启,并在工作结束时释放。这既为排错提供了清晰边界,也有利于未来进行依赖升级。
在 Steel 流程中,将 CapSolver 连接到支持的 CAPTCHA 步骤。先从已验证的检测路径开始,然后在增加任务量前验证带凭据的实际执行。
试用 CapSolver。在活动条款下使用优惠码 CAP26 可获得 5% 赠送额度。

问:自托管 Steel Browser 会自动求解 CAPTCHA 吗?
不会。Steel 官方对比中没有为 Steel Local 列出内置 CAPTCHA 求解功能。云端产品中的求解能力是单独的功能。
问:本示例需要 Steel Cloud 账号吗?
不需要。示例连接的是一个正在运行的本地实例。你自己负责启动和运维该实例。
问:为什么要通过 CDP 连接,而不是直接启动 Playwright 的 Chromium?
通过 CDP,Python 会附着到由 Steel 管理的浏览器上。启动另一个浏览器会创建一个与本示例打算使用的会话不同的独立会话。
问:检测检查会消耗 CapSolver 额度吗?
该检查仅读取小部件参数,不会发起任何付费求解请求。单独的求解调用需要有效的 CapSolver 凭证。
问:这里是否已经测试了完整的付费求解流程?
没有。实际运行仅验证了会话创建、CDP 连接、SDK 检测和释放。付费求解、结果回填及应用端的接受仍然需要使用单独的凭证进行测试。
问:这是官方的 Steel 合作或原生集成吗?
不是。这是一个使用 Steel 公共浏览器接口和 CapSolver 官方 SDK 的已测试连接示例。它并不构成合作关系,也不保证未来版本的兼容性。

Adélia Cruz
MCP Integration Engineer
Making CapSolver tools accessible through MCP.
关于作者