
Ethan Collins
Pattern Recognition Specialist

FunctionTool 包装一个狭窄的异步 CapSolver 函数;不要暴露 API 密钥、代理凭证、cookies 或原始浏览器对象给模型。websiteURL、websiteKey 和 pageAction。永远不要让代理生成这些值。ReCaptchaV3TaskProxyLess 用于服务器代理令牌模式,或在必须提供已批准代理时使用 ReCaptchaV3Task。可靠的 LlamaIndex reCAPTCHA v3 解决方案是一种类型化的恢复工具,而不是开放式的浏览能力。LlamaIndex 代理应决定何时批准的任务被阻塞,而可信代码验证目标,从当前页面读取确切的站点密钥和操作,调用 CapSolver,提交令牌,并验证预期状态。这种分离很重要,因为 reCAPTCHA v3 在没有交互式复选框的情况下运行,并评估特定操作的请求。为错误的 URL 或 pageAction 创建的令牌即使 API 调用本身成功也可能被拒绝。本指南展示了官方 CapSolver 任务字段、异步 LlamaIndex FunctionTool、服务器端策略控制、会话模式处理、结构化结果、有限重试、浏览器验证和生产可观测性。
LlamaIndex 的 官方工具文档 解释了 FunctionTool 包装同步或异步 Python 函数,并可以推断函数模式。它还指出工具名称、描述和参数描述强烈影响模型如何选择和调用工具。
对于 LlamaIndex reCAPTCHA v3 解决方案,保持工具的狭窄:
LlamaIndex 代理
↓ 选择一个类型化的工具
FunctionTool 包装器
↓ 验证可信引用
CapSolver 执行器
↓ 返回一个短时解决方案
浏览器服务
↓ 提交并验证
LlamaIndex 工作流继续
CapSolver AI 代理文档 描述了相同的分工:模型决定,适配器暴露模式,核心执行支持的挑战工作。
CapSolver 的 reCAPTCHA v3 文档 定义了四种任务类型:
| 任务类型 | 代理模式 | 企业 |
|---|---|---|
ReCaptchaV3TaskProxyLess |
CapSolver 服务器代理 | 否 |
ReCaptchaV3Task |
您的已批准代理 | 否 |
ReCaptchaV3EnterpriseTaskProxyLess |
CapSolver 服务器代理 | 是 |
ReCaptchaV3EnterpriseTask |
您的已批准代理 | 是 |
基础字段是:
| 字段 | 要求 | 可信来源 |
|---|---|---|
websiteURL |
必填 | 当前授权页面 URL |
websiteKey |
必填 | 实时页面配置 |
pageAction |
通常对于 v3 必填 | 页面的 grecaptcha.execute 操作 |
proxy |
非无代理任务必填 | 服务器端已批准的代理配置文件 |
enterprisePayload |
条件 | 实时企业配置 |
isSession |
条件 | 目标特定的已批准工作流 |
Google 的 reCAPTCHA v3 指南 描述了操作名称作为集成的一部分。页面上观察到的操作应精确保留。
CapSolver reCAPTCHA 博客 包含额外的故障排除和实现指南。
传递对服务器端状态的引用,而不是任意值。
from dataclasses import dataclass
from urllib.parse import urlparse
@dataclass(frozen=True)
class CaptchaContext:
context_id: str
website_url: str
website_key: str
page_action: str
enterprise: bool = False
proxy_profile: str | None = None
session_mode: bool = False
TRUSTED_CONTEXTS: dict[str, CaptchaContext] = {}
ALLOWED_HOSTS = {"staging.example.com", "portal.example.org"}
def get_trusted_context(context_id: str) -> CaptchaContext:
context = TRUSTED_CONTEXTS.get(context_id)
if context is None:
raise ValueError("未知的 CAPTCHA 上下文")
host = urlparse(context.website_url).hostname
if host not in ALLOWED_HOSTS:
raise PermissionError("目标超出批准的主机策略")
if not context.website_key or not context.page_action:
raise ValueError("受信任的上下文缺少必需的 v3 参数")
return context
模型仅接收 context_id。浏览器服务拥有当前页面、站点密钥、操作和代理绑定。
用户提供的 CapSolver 代理文档指定了在安装代理包之前安装核心包:
pip install git+https://github.com/capsolver-ai/capsolver-core.git
pip install git+https://github.com/capsolver-ai/capsolver-agent.git
pip install llama-index-core
在运行时环境中设置 API 密钥:
export CAPSOLVER_API_KEY="your-capsolver-api-key"
不要将密钥粘贴到提示、笔记本、场景数据集或跟踪中。CapSolver AI 和自动化常见问题 解释了集成模型。
capsolver-agent 为模型-适配器-核心边界提供了 create_executor()。
import os
from capsolver_agent.schema import create_executor
executor = create_executor(
api_key=os.environ["CAPSOLVER_API_KEY"],
default_timeout=120,
)
执行器将 solve_captcha 分发到 CapSolver Core 并返回结构化结果。将其保留在可信应用代码中。
该函数解析受信任的上下文,选择官方任务类型,并调用执行器。
from typing import Annotated
async def solve_recaptcha_v3(
context_id: Annotated[
str,
"用于受信任的当前浏览器 CAPTCHA 上下文的不透明 ID"
],
) -> dict:
"""为批准的浏览器上下文解决 reCAPTCHA v3。
仅在当前工作流报告支持的 reCAPTCHA v3 检查点时使用。永远不要猜测或修改目标 URL、站点密钥或操作。
"""
context = get_trusted_context(context_id)
captcha_type = (
"reCaptchaV3Enterprise"
if context.enterprise
else "reCaptchaV3"
)
args = {
"captcha_type": captcha_type,
"website_url": context.website_url,
"website_key": context.website_key,
"page_action": context.page_action,
}
if context.proxy_profile:
args["proxy"] = resolve_proxy(context.proxy_profile)
result = await executor.execute("solve_captcha", args)
if not result.get("success"):
return {
"success": False,
"context_id": context_id,
"error": normalize_error(result.get("error")),
}
solution = result.get("solution") or {}
token = solution.get("token")
if not token:
return {
"success": False,
"context_id": context_id,
"error": "solution did not contain a token",
}
receipt = await submit_solution_and_verify(
context_id=context_id,
token=token,
session_cookie=extract_session_cookie(solution),
)
return {
"success": receipt["verified"],
"context_id": context_id,
"verified": receipt["verified"],
"next_state": receipt["next_state"],
}
resolve_proxy、normalize_error 和 submit_solution_and_verify 是应用拥有的策略适配器。它们不应对模型可见。
from llama_index.core.tools import FunctionTool
tool = FunctionTool.from_defaults(
async_fn=solve_recaptcha_v3,
name="solve_recaptcha_v3",
description=(
"为批准的当前浏览器上下文解决 reCAPTCHA v3。"
"输入必须是浏览器服务提供的不透明 context_id。"
"不要为不支持的页面或未批准的主机调用。"
),
)
在开发期间检查模式:
schema = tool.metadata.get_parameters_dict()
print(schema)
这遵循 LlamaIndex 的文档 FunctionTool 模式,同时将模型的参数表面减少到一个不透明的标识符。
from llama_index.core.agent.workflow import FunctionAgent
agent = FunctionAgent(
llm=llm,
tools=[tool],
system_prompt=(
"仅操作批准的浏览器工作流。当浏览器服务报告支持的 reCAPTCHA v3 检查点时,"
"使用提供的 context_id 调用 solve_recaptcha_v3。仅调用一次。"
"仅在 verified=true 时继续;否则请求审查。"
),
)
使用受信任的浏览器观察运行工作流:
response = await agent.run(
"批准的暂存工作流在 reCAPTCHA v3 检查点等待。使用 context_id ctx_7f19 并在 verified 时继续。"
)
代理永远不会看到 API 密钥、原始代理、令牌或 cookie。
pageAction可靠的 LlamaIndex reCAPTCHA v3 解决方案不应在每个目标上重复使用通用操作,如 login。浏览器服务应读取目标的当前集成。
async def collect_v3_context(page, context_id: str) -> CaptchaContext:
website_url = page.url
host = urlparse(website_url).hostname
if host not in ALLOWED_HOSTS:
raise PermissionError("未批准的目标")
values = await page.evaluate("""
() => {
const scripts = Array.from(document.scripts)
.map(s => s.textContent || '')
.join('\n');
const siteKey =
document.querySelector('[data-sitekey]')?.getAttribute('data-sitekey')
|| null;
const actionMatch = scripts.match(
/grecaptcha(?:\.enterprise)?\.execute\([^,]+,\s*\{\s*action:\s*['\"]([^'\"]+)/
);
return {
siteKey,
pageAction: actionMatch ? actionMatch[1] : null,
enterprise: scripts.includes('grecaptcha.enterprise')
};
}
""")
if not values["siteKey"] or not values["pageAction"]:
raise RuntimeError("无法读取必需的 v3 参数")
return CaptchaContext(
context_id=context_id,
website_url=website_url,
website_key=values["siteKey"],
page_action=values["pageAction"],
enterprise=values["enterprise"],
)
对于复杂集成,使用 CapSolver 扩展指南 在批准的开发和测试期间检查页面参数。
CapSolver 的官方 v3 文档指出,某些目标在启用 isSession 时可能返回 recaptcha-ca-t。将其视为敏感的、短期的会话材料。
SESSION_KEYS = {
"recaptcha-ca-t",
"recaptcha_ca_t",
}
def extract_session_cookie(solution: dict) -> str | None:
raw = solution.get("raw") or {}
for key in SESSION_KEYS:
value = solution.get(key) or raw.get(key)
if value:
return value
return None
仅在目标集成需要且工作流已授权时启用会话模式。将值存储在进程内存或短期加密存储中;永远不要将其放在 LlamaIndex 上下文中。
Google 的 服务器端验证文档 解释了站点在其后端验证令牌。您的自动化应通过相同的受信任应用流程提交令牌,然后验证结果页面状态。
async def submit_solution_and_verify(
context_id: str,
token: str,
session_cookie: str | None,
) -> dict:
browser_state = BROWSER_CONTEXTS[context_id]
page = browser_state.page
if session_cookie:
await browser_state.context.add_cookies([{
"name": "recaptcha-ca-t",
"value": session_cookie,
"domain": urlparse(page.url).hostname,
"path": "/",
"secure": True,
}])
await page.evaluate(
"""({ token }) => {
let input = document.querySelector(
'textarea[name="g-recaptcha-response"]'
);
if (!input) {
input = document.createElement('textarea');
input.name = 'g-recaptcha-response';
input.style.display = 'none';
document.body.appendChild(input);
}
input.value = token;
input.dispatchEvent(new Event('change', { bubbles: true }));
}""",
{"token": token},
)
await trigger_trusted_callback(page, browser_state.callback_name)
try:
await page.locator(browser_state.success_selector).wait_for(
state="visible",
timeout=15000,
)
return {"verified": True, "next_state": "continue"}
except Exception:
return {"verified": False, "next_state": "operator_review"}
回调发现是目标特定的。在受信任的浏览器上下文中捕获它,而不是让模型生成 JavaScript。
CapSolver reCAPTCHA 响应 API 指南 解释了常见的响应处理模式。
from enum import Enum
class RecoveryState(str, Enum):
DETECTED = "detected"
SOLVING = "solving"
VERIFIED = "verified"
REVIEW_REQUIRED = "review_required"
ATTEMPTS: dict[str, int] = {}
async def guarded_solve(context_id: str) -> dict:
attempts = ATTEMPTS.get(context_id, 0)
if attempts >= 1:
return {
"success": False,
"context_id": context_id,
"next_state": RecoveryState.REVIEW_REQUIRED,
"error": "recovery budget exhausted",
}
ATTEMPTS[context_id] = attempts + 1
return await solve_recaptcha_v3(context_id)
重复调用通常表示参数过时、操作错误、浏览器状态过期或不支持的路径。停止循环并收集诊断信息。
记录操作元数据,而不是秘密信息。
from datetime import datetime, timezone
def recovery_event(context: CaptchaContext, result: dict) -> dict:
return {
"event": "recaptcha_v3_recovery",
"context_id": context.context_id,
"host": urlparse(context.website_url).hostname,
"page_action": context.page_action,
"enterprise": context.enterprise,
"session_mode": context.session_mode,
"success": result.get("success", False),
"next_state": str(result.get("next_state")),
"observed_at": datetime.now(timezone.utc).isoformat(),
}
如果您的策略将websiteKey视为配置,则不要记录它,并且永远不要记录解决方案令牌、会话cookie、API密钥、原始代理或完整的私有页面HTML。
[CapSolver错误常见问题](https://www.capsolver.com/faq/errors-and-troubleshooting) 可帮助规范错误类别。
> **优惠代码**:在 [CapSolver仪表板](https://dashboard.capsolver.com/dashboard/overview/?utm_source=offcial&utm_medium=blog&utm_campaign=how-to-solve-recaptcha-v3-in-llamaindex-agents) 使用代码 **WEBS** 可在每次充值时额外获得5%的奖励。
## 对比总结
| 集成模式 | 模型输入 | 密钥泄露风险 | 最佳用途 |
|---|---|---:|---|
| 模型提供所有任务字段 | URL、密钥、操作、代理 | 高 | 避免在生产环境中使用 |
| 使用验证字段的类型化FunctionTool | 明确字段 | 中 | 受控原型 |
| 不透明的上下文ID加服务器验证 | 仅上下文引用 | 低 | 生产环境LlamaIndex工作流 |
| 浏览器核心 `solve_on_page` | 无模型参数 | 最低 | 确定性Playwright恢复 |
不透明上下文模式让LlamaIndex代理有足够的控制权来请求恢复,而不会让它重写敏感或目标特定的参数。
## 生产检查清单
- 将API密钥和代理配置存储在密钥管理器中。
- 仅允许批准的主机和精确的工作流用途。
- 从当前实时页面中读取`websiteKey`和`pageAction`。
- 将企业模式和会话设置与目标集成匹配。
- 通过可信浏览器代码立即提交令牌。
- 在继续之前验证预期的应用程序状态。
- 仅允许一次解决尝试,然后转到操作员审核。
- 从追踪中删除令牌、cookie、代理和凭证。
- 每次SDK或提示更改时重新测试工具模式。
[CapSolver产品页面](https://www.capsolver.com/products) 列出了支持的解决方案类别,而 [CapSolver AI博客](https://www.capsolver.com/blog/ai) 讨论了相关的代理集成模式。
## 负责任使用
仅在您拥有、测试或明确获得自动化权限的应用程序上使用此工作流。技术能力不意味着访问权限。尊重目标条款、速率限制、隐私要求和认证边界。在未经授权的情况下,不要使用代理工具访问私人账户、受限记录或第三方工作流。在单独的策略和确认步骤后,将高影响操作(如提交、支付、预订和账户更改)进行隔离。
## 结论
生产环境中的LlamaIndex reCAPTCHA v3求解器应仅暴露一个狭窄、类型化的恢复功能。浏览器服务提供可信的上下文ID,服务器端代码保留精确的URL、站点密钥、操作、企业模式和代理策略,CapSolver返回一个短期解决方案,浏览器在代理继续之前验证预期状态。
通过 [CapSolver](https://www.capsolver.com/?utm_source=offcial&utm_medium=blog&utm_campaign=how-to-solve-recaptcha-v3-in-llamaindex-agents) 开始经过批准的LlamaIndex集成,在受控的测试工作流中进行测试,并在生产前添加参数定位和重试断言。
## 常见问题
### reCAPTCHA v3是否需要点击复选框?
不需要。reCAPTCHA v3基于评分,并且通常在后台运行。工作流必须保留目标的站点密钥、URL和操作。
### 为什么`pageAction`很重要?
该操作标识正在评估的操作,例如登录或提交。应使用从实时集成中读取的确切操作,而不是通用值。
### LlamaIndex代理应接收令牌吗?
优先选择服务器端提交,并仅返回已验证的状态。令牌是短期运行时数据,不应进入模型上下文或日志。
### 何时应启用会话模式?
仅在授权目标需要返回的会话值时才启用。将该值存储在短期加密运行时存储中。
### 失败尝试后应如何处理?
在配置的尝试预算后停止,记录已脱敏的诊断事件,如果适当的话刷新可信页面参数,并将工作流转到操作员审核。