
Adélia Cruz
Neural Network Developer

capsolver-agent como a camada de adaptador de ferramentas sobre capsolver-core, com ferramentas da LangChain para frameworks de agentes e métodos de navegador para sessões do Playwright.Uma integração LangGraph Cloudflare Turnstile permite que um agente recupere de um passo de verificação dentro de um fluxo de trabalho autorizado do navegador e depois retome a tarefa original. O gráfico não deve pedir ao modelo de linguagem para clicar ou raciocinar sobre o widget. Em vez disso, o modelo ou controlador do navegador detecta que o fluxo está bloqueado, o gráfico avalia a política e um adaptador determinístico chama a capacidade documentada da CapSolver.
CapSolver documenta essa divisão de tarefas em seu guia de ferramentas para agentes: o modelo lida com navegação e decisões, capsolver-agent expõe esquemas de ferramentas e um executor, e capsolver-core realiza detecção, resolução e preenchimento de volta no navegador.
Essa arquitetura dá ao LangGraph um papel útil. Ele pode tornar a recuperação observável, impor orçamentos de retriados, rotear ações sensíveis para um humano e garantir que o navegador verifique o sucesso antes que o gráfico continue.
Use um ambiente Python isolado. A atual guia oficial da CapSolver instala os pacotes core e agent a partir do GitHub:
python -m venv .venv
source .venv/bin/activate
pip install git+https://github.com/capsolver-ai/capsolver-core.git
pip install "capsolver-agent[langchain] @ git+https://github.com/capsolver-ai/capsolver-agent.git"
pip install langchain-openai langgraph playwright
playwright install chromium
Coloque CAPSOLVER_API_KEY e quaisquer credenciais de modelo em um repositório de segredos aprovado. Não escreva valores reais no estado do gráfico, checkpoints, prompts, eventos de rastreamento ou arquivos de origem.
Você também precisa de:
Mantenha apenas dados operacionais não secretos no estado do gráfico:
from typing import Literal, TypedDict
class AgentState(TypedDict, total=False):
request_id: str
purpose: str
page_id: str
current_url: str
step: str
challenge_detected: bool
challenge_attempts: int
challenge_status: Literal[
"not-needed", "pending", "resolved", "review", "denied"
]
error_code: str | None
final_assertion_passed: bool
Não adicione a credencial da CapSolver, o token de solução, cookies ou conteúdo bruto da página. Armazene objetos do navegador em um registro proprietário da aplicação, com chave por page_id; os checkpoints do gráfico devem conter apenas o identificador opaco.
A autorização deve ocorrer antes de qualquer ferramenta de desafio:
from urllib.parse import urlparse
ALLOWED_HOSTS = {"staging.example.com", "research.example.com"}
ALLOWED_PURPOSES = {"qa-validation", "public-data-research"}
def authorize_challenge(state: AgentState) -> AgentState:
host = urlparse(state["current_url"]).hostname
attempts = state.get("challenge_attempts", 0)
if host not in ALLOWED_HOSTS:
return {**state, "challenge_status": "denied", "error_code": "domain"}
if state.get("purpose") not in ALLOWED_PURPOSES:
return {**state, "challenge_status": "denied", "error_code": "purpose"}
if attempts >= 2:
return {**state, "challenge_status": "review", "error_code": "retry-limit"}
return {**state, "challenge_status": "pending"}
Este nó é validado sintaticamente e independente do modelo. Na produção, carregue a política de configurações versionadas e rejeite campos desconhecidos.
class BrowserRegistry:
def __init__(self):
self._pages = {}
def register(self, page_id: str, page) -> None:
self._pages[page_id] = page
def get(self, page_id: str):
if page_id not in self._pages:
raise KeyError("browser page is not registered")
return self._pages[page_id]
async def remove(self, page_id: str) -> None:
page = self._pages.pop(page_id, None)
if page is not None:
await page.close()
O registro evita a serialização de um Page do Playwright e fornece um único local para impor limpeza.
Resgate seu código promocional da CapSolver
Aumente seu orçamento de automação instantaneamente!
Use o código promocional CAP26 ao recarregar sua conta da CapSolver para obter um bônus adicional de 5% em cada recarga — sem limites.
Resgate-o agora em seu Painel da CapSolver
O SDK Core da CapSolver documenta detect(page) e solve_on_page(page) para o modo de navegador. O adaptador abaixo usa esses métodos e retorna apenas uma decisão do gráfico:
import os
from capsolver_core import create_capsolver
async def solve_turnstile_node(
state: AgentState,
registry: BrowserRegistry,
) -> AgentState:
page = registry.get(state["page_id"])
attempts = state.get("challenge_attempts", 0) + 1
async with create_capsolver(
api_key=os.environ["CAPSOLVER_API_KEY"],
default_timeout=120,
polling_interval=5,
) as cap:
detected = await cap.detect(page)
if not detected:
return {
**state,
"challenge_attempts": attempts,
"challenge_status": "not-needed",
"error_code": None,
}
results = await cap.solve_on_page(page)
failures = [item for item in results if item.error or not item.filled]
if failures:
return {
**state,
"challenge_attempts": attempts,
"challenge_status": "review" if attempts >= 2 else "pending",
"error_code": "fill-back-failed",
}
return {
**state,
"challenge_attempts": attempts,
"challenge_status": "resolved",
"error_code": None,
}
O código foi verificado sintaticamente, mas não executado com credenciais. Um teste em produção requer uma página aprovada e segredo. O gráfico nunca recebe solution.token.
Um token preenchido é um resultado intermediário. Verifique o estado esperado da aplicação:
async def verify_page_node(
state: AgentState,
registry: BrowserRegistry,
) -> AgentState:
page = registry.get(state["page_id"])
try:
await page.get_by_test_id("authorized-content").wait_for(timeout=15_000)
return {
**state,
"final_assertion_passed": True,
"step": "continue",
"error_code": None,
}
except Exception:
return {
**state,
"final_assertion_passed": False,
"challenge_status": "review",
"error_code": "page-assertion-failed",
}
Use uma afirmação pertencente à sua aplicação. Evite seletores que exponham conteúdo de página pessoal ou sensível nos logs.
from langgraph.graph import END, StateGraph
def route_after_authorization(state: AgentState) -> str:
if state["challenge_status"] == "pending":
return "solve"
if state["challenge_status"] in {"denied", "review"}:
return "human_review"
return "verify"
def route_after_solve(state: AgentState) -> str:
if state["challenge_status"] == "resolved":
return "verify"
if state["challenge_status"] == "pending":
return "authorize"
return "human_review"
def build_graph(authorize, solve, verify, human_review):
graph = StateGraph(AgentState)
graph.add_node("authorize", authorize)
graph.add_node("solve", solve)
graph.add_node("verify", verify)
graph.add_node("human_review", human_review)
graph.set_entry_point("authorize")
graph.add_conditional_edges(
"authorize",
route_after_authorization,
{"solve": "solve", "verify": "verify", "human_review": "human_review"},
)
graph.add_conditional_edges(
"solve",
route_after_solve,
{"authorize": "authorize", "verify": "verify", "human_review": "human_review"},
)
graph.add_edge("verify", END)
graph.add_edge("human_review", END)
return graph.compile()
As funções injetadas podem fechar sobre o registro do navegador. A injeção de dependência torna as políticas e rotas de falha testáveis sem um serviço ativo.
O revisor deve receber:
O revisor não deve receber a credencial da CapSolver ou o token de solução. Uma ação que mude o estado, como envio, compra, alteração de conta ou envio de mensagem, deve exigir sua própria autorização mesmo após a verificação ser bem-sucedida.
Testes unitários podem substituir o nó de resolução por stubs determinísticos:
async def solved_stub(state: AgentState) -> AgentState:
return {
**state,
"challenge_attempts": state.get("challenge_attempts", 0) + 1,
"challenge_status": "resolved",
"error_code": None,
}
async def failed_stub(state: AgentState) -> AgentState:
return {
**state,
"challenge_attempts": state.get("challenge_attempts", 0) + 1,
"challenge_status": "review",
"error_code": "fixture-failure",
}
Teste domínios aprovados e negados, propósitos não suportados, exaustão de retriados, páginas do navegador ausentes, desafio resolvido com afirmação de página falha e limpeza após estados terminais.
O modo de navegador é apropriado quando o agente já controla uma página do Playwright. O modo de token pode ser mais simples quando seu aplicativo conhece a URL e a chave pública da página Turnstile. A CapSolver documenta a tarefa AntiTurnstileTaskProxyLess com websiteURL e websiteKey obrigatórios, mais metadata.action e metadata.cdata opcionais.
Não deixe o modelo inventar esses campos. Extraia-os de forma determinística da página aprovada ou da configuração do aplicativo.
Rastreie:
Não rastreie prompts contendo credenciais, cookies do navegador, tokens brutos ou dados de formulário não redigidos. Defina regras de retenção e acesso para capturas de tela e evidências do DOM.
Confirme que a página terminou de carregar, o navegador usa a sessão desejada e a versão do SDK suporta o tipo de desafio. Trate um resultado de detecção vazio como not-needed somente quando a afirmação da página ainda puder passar.
Registre a categoria de erro, compare os parâmetros com a documentação atual da CapSolver e pare após o orçamento de retriados. Não aumente automaticamente os retriados.
Mantenha a mesma página do navegador, revise o comportamento de callback ou widget e verifique se a navegação da página não substituiu o contexto.
Armazene e impeça challenge_attempts. Roteie para revisão humana após o limite configurado.
Mantenha a recuperação de CAPTCHA separada da ação subsequente. O gráfico deve apresentar o erro da ação em vez de reresolver o desafio.
Uma integração LangGraph Cloudflare Turnstile é mais confiável quando se comporta como um fluxo de recuperação finito: detectar, autorizar, resolver, verificar, continuar ou parar. O gráfico fornece roteamento e observabilidade; código determinístico fornece política; a CapSolver fornece a camada de reconhecimento documentada.
Use a CapSolver apenas para automação legal e autorizada. Revise a documentação atual das ferramentas para agentes, guia do SDK Core e tutoriais relacionados da CapSolver blog antes de fixar uma implementação.
Q: O LangGraph resolve o Cloudflare Turnstile por conta própria?
Não. O LangGraph controla o estado e o roteamento do fluxo de trabalho; o adaptador da CapSolver chama o serviço de reconhecimento e métodos do navegador.
Q: O token de solução deve ser retornado para o modelo?
Não. Aplicá-lo dentro do adaptador do navegador controlado e retornar apenas status, categoria de erro e resultado da verificação.
Q: Qual método da CapSolver é usado com o Playwright?
O SDK Core atual documenta detect(page), get_captcha_info(page) e solve_on_page(page) para o modo de navegador.
Q: Quantos retriados o gráfico deve permitir?
Use um orçamento pequeno e explícito baseado no seu fluxo e roteie para revisão em vez de permitir um loop sem limite.
Q: O agente pode chamar o nó de recuperação para qualquer URL?
Não. Impõe uma lista de domínios e propósitos permitidos antes que o nó possa invocar a CapSolver.
Q: O que comprova que o desafio foi tratado com sucesso?
Uma asserção de aplicação no nível da página demonstra a recuperação de fluxo de trabalho; o status do provedor ou um token preenchido sozinhos não são suficientes.
Crie uma ferramenta de agente solucionador de CAPTCHA com o CapSolver, esquemas de ferramentas seguras, orçamentos de tentativas e verificação para reCAPTCHA e Cloudflare Turnstile.

Construa um fluxo de trabalho de resolução de CAPTCHA para o Claude Computer com guardas do CapSolver, IDs de evidências visuais, verificações de políticas e verificação confiável.
