CAPSOLVER
Blog
Cómo resolver Cloudflare Turnstile en agentes de LangGraph

Cómo resolver Cloudflare Turnstile en agentes de LangGraph

Logo of CapSolver

Aloísio Vítor

Image Processing Expert

23-Jul-2026

TL;DR

  • Una integración de LangGraph Cloudflare Turnstile debe modelar el manejo de CAPTCHA como un nodo de recuperación controlada, no como una herramienta sin restricciones disponible en cada ruta.
  • CapSolver documenta capsolver-agent como la capa de adaptador de herramientas sobre capsolver-core, con herramientas de LangChain para marcos de agentes y métodos de navegador para sesiones de Playwright.
  • Mantén las decisiones de navegación en el gráfico, la autorización determinista en el código de la aplicación y el reconocimiento en el servicio CapSolver.
  • Preserva una sesión de navegador a través de la detección, resolución, llenado de vuelta y verificación final de la página; nunca devuelvas el token sin procesar al modelo.
  • Usa reintentos limitados, estados terminales explícitos, seguimiento con redacción y revisión humana para acciones que cambien el estado o sean poco claras.
  • El gráfico de ejemplo incluye definiciones de estado, enrutamiento de políticas, un nodo de recuperación de CapSolver, manejo de errores y verificación.

Lo que debe hacer una integración de LangGraph Cloudflare Turnstile

Una integración de LangGraph Cloudflare Turnstile permite a un agente recuperarse de un paso de verificación dentro de un flujo de navegación autorizado y luego reanudar la tarea original. El gráfico no debe pedir al modelo de lenguaje que haga clic o razonar sobre el widget. En su lugar, el modelo o el controlador de navegador detecta que el flujo está bloqueado, el gráfico evalúa la política y un adaptador determinista llama a la capacidad documentada de CapSolver.

CapSolver documenta esta división del trabajo en su guía de herramientas para agentes: el modelo maneja la navegación y las decisiones, capsolver-agent expone esquemas de herramientas y un ejecutor, y capsolver-core realiza la detección, resolución y llenado de vuelta en el navegador.

Esta arquitectura da a LangGraph un papel útil. Puede hacer que la recuperación sea observable, imponer presupuestos de reintentos, enrutar acciones sensibles a un humano y asegurarse de que el navegador verifique el éxito antes de que el gráfico continúe.

Requisitos previos y ruta de integración admitida

Usa un entorno Python aislado. La guía oficial actual de CapSolver instala los paquetes core y agent desde GitHub:

bash Copy
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

Coloca CAPSOLVER_API_KEY y cualquier credencial de modelo en un almacén de secretos aprobado. No escribas valores reales en el estado del gráfico, puntos de verificación, prompts, eventos de seguimiento o archivos de código fuente.

También necesitas:

  • un dominio propiedad o explícitamente autorizado;
  • una lista blanca de dominios;
  • un propósito de negocio definido;
  • un registro de sesión de navegador;
  • un número máximo de reintentos;
  • un presupuesto de tiempo de espera;
  • una verificación final de la página;
  • una regla de revisión humana para acciones importantes.

Diseña el estado de LangGraph

Mantén solo datos operativos no secretos en el estado del gráfico:

python Copy
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

No agregues la credencial de CapSolver, el token de solución, cookies o contenido sin procesar de la página. Almacena objetos de navegador en un registro propiedad de la aplicación, clave por page_id; los puntos de verificación del gráfico deben contener solo el identificador opaco.

Crea un nodo de autorización determinista

La autorización debe ejecutarse antes de cualquier herramienta de desafío:

python Copy
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 nodo es validado sintácticamente e independiente del modelo. En producción, carga la política desde configuración versionada y rechaza campos desconocidos.

python Copy
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()

El registro evita la serialización de un Page de Playwright y da a la aplicación un lugar para imponer la limpieza.

Redime tu código de bonificación de CapSolver

¡Aumenta tu presupuesto de automatización instantáneamente!
Usa el código de bonificación CAP26 al recargar tu cuenta de CapSolver para obtener un 5% adicional en cada recarga — sin límites.
Redímelo ahora en tu Panel de CapSolver
Código de bonificación

Implementa el nodo de recuperación de CapSolver

El SDK Core de CapSolver documenta detect(page) y solve_on_page(page) para el modo de navegador. El adaptador siguiente usa estos métodos y devuelve solo una decisión del gráfico:

python Copy
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,
    }

El código ha sido verificado sintácticamente pero no ejecutado con credenciales. Una prueba en vivo requiere una página aprobada y un secreto. El gráfico nunca recibe solution.token.

Verifica el resultado de la página

Un token llenado es un resultado intermedio. Verifica el estado esperado de la aplicación:

python Copy
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",
        }

Usa una afirmación propiedad de tu aplicación. Evita selectores que expongan contenido personal o sensible en los registros.

Ensambla el flujo de trabajo de LangGraph

python Copy
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()

Las funciones inyectadas pueden cerrar sobre el registro de navegadores. La inyección de dependencias hace que las políticas y rutas de error sean testables sin un servicio en vivo.

Añade un nodo de revisión humana

El revisor debe recibir:

  • ID de solicitud;
  • propósito aprobado;
  • nombre de host;
  • acción intentada;
  • recuento de reintentos;
  • categoría de error redactada;
  • referencia de captura de pantalla segura, si se permite;
  • paso siguiente propuesto.

El revisor no debe recibir la credencial de CapSolver o el token de solución. Una acción que cambie el estado, como una entrega, compra, cambio de cuenta o envío de mensaje, debe requerir su propia autorización incluso después de que la verificación tenga éxito.

Prueba el gráfico sin llamar a servicios externos

Las pruebas unitarias pueden reemplazar el nodo de resolución con stubs deterministas:

python Copy
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",
    }

Prueba dominios aprobados y denegados, propósitos no admitidos, agotamiento de reintentos, páginas de navegador faltantes, un desafío resuelto con una afirmación de página fallida y la limpieza después de estados terminales.

Usa el modo token cuando se conozcan los parámetros de la página

El modo de navegador es adecuado cuando el agente ya controla una página de Playwright. El modo token puede ser más sencillo cuando tu aplicación conoce la URL y la clave pública de la página de Turnstile. CapSolver documenta la tarea AntiTurnstileTaskProxyLess con websiteURL y websiteKey requeridos, más metadata.action y metadata.cdata opcionales.

No dejes que el modelo invente estos campos. Extraelos de forma determinista de la página aprobada o de la configuración de la aplicación.

Observabilidad sin fuga de secretos

Rastrea:

  • nodo del gráfico;
  • ID de solicitud;
  • decisión de política;
  • nombre de host;
  • tipo de desafío;
  • número de intentos;
  • tiempo transcurrido;
  • categoría de error;
  • booleano de llenado de vuelta;
  • booleano de afirmación final.

No rastrees prompts que contengan credenciales, cookies de navegador, tokens sin procesar o datos de formulario no redactados. Define reglas de retención y acceso para capturas de pantalla y evidencia DOM.

Modos de fallo y soluciones

No se detecta ningún desafío

Confirma que la página terminó de cargar, que el navegador usa la sesión deseada y que la versión del SDK admite el tipo de desafío. Trata un resultado de detección vacío como "not-needed" solo cuando la afirmación de página aún puede pasar.

La tarea falla antes de estar lista

Registra la categoría de error, compara los parámetros con la documentación actual de CapSolver y detente después del presupuesto de reintentos. No aumentes automáticamente los reintentos.

El llenado del token falla

Mantén la misma página de navegador, revisa el comportamiento de la devolución de llamada o widget y verifica que la navegación de la página no haya reemplazado el contexto.

El gráfico se ejecuta indefinidamente

Almacena y aplica challenge_attempts. Enruta a revisión humana después del límite configurado.

La verificación tiene éxito pero la acción comercial falla

Mantén separada la recuperación de CAPTCHA de la acción posterior. El gráfico debe mostrar el error de la acción en lugar de resolver nuevamente el desafío.

Lista de verificación para producción

  • Fija versiones de dependencias o commits.
  • Usa políticas separadas para entorno de prueba y producción.
  • Almacena secretos fuera del estado del gráfico.
  • Restringe dominios y propósitos.
  • Establece plazos por llamada y totales.
  • Preserva una sesión de navegador.
  • Redacta tokens y cookies.
  • Verifica la página después del llenado.
  • Añade revisión humana para acciones importantes.
  • Prueba la limpieza y cancelación.
  • Supervisa las tasas de denegación, error, recuperación y afirmación.
  • Revisa cambios en políticas como código.

Conclusión: haz que el manejo de desafíos sea un estado de recuperación del gráfico

Una integración de LangGraph Cloudflare Turnstile es más confiable cuando se comporta como un flujo de recuperación finito: detectar, autorizar, resolver, verificar, continuar o detenerse. El gráfico proporciona enrutamiento y observabilidad; el código determinista proporciona política; CapSolver proporciona la capa de reconocimiento documentada.

Usa CapSolver solo para automatización legal y autorizada. Revisa la documentación actual de herramientas para agentes, guía del SDK Core y tutoriales relacionados de CapSolver blog antes de fijar una implementación.

Preguntas frecuentes

P: ¿Resuelve LangGraph Cloudflare Turnstile por sí mismo?

No. LangGraph controla el estado y el enrutamiento del flujo de trabajo; el adaptador de CapSolver llama al servicio de reconocimiento y a los métodos del navegador.

P: ¿Debe devolverse el token de solución al modelo?

No. Aplica el token dentro del adaptador de navegador controlado y devuelve solo el estado, la categoría de error y el resultado de la verificación.

P: ¿Qué método de CapSolver se usa con Playwright?

El SDK Core actual documenta detect(page), get_captcha_info(page) y solve_on_page(page) para el modo de navegador.

P: ¿Cuántos reintentos debe permitir el gráfico?

Usa un pequeño presupuesto explícito basado en tu flujo y enruta a revisión en lugar de permitir un bucle sin límites.

P: ¿Puede el agente llamar al nodo de recuperación para cualquier URL?

No. Aplica una lista blanca determinista de dominios y propósitos antes de que el nodo pueda invocar a CapSolver.

P: ¿Qué demuestra que el desafío se manejó con éxito?
Una afirmación de aplicación a nivel de página demuestra la recuperación del flujo de trabajo; un estado del proveedor o un token completado por sí solo no es suficiente.

Aviso de Cumplimiento: La información proporcionada en este blog es solo para fines informativos. CapSolver se compromete a cumplir con todas las leyes y regulaciones aplicables. El uso de la red de CapSolver para actividades ilegales, fraudulentas o abusivas está estrictamente prohibido y será investigado. Nuestras soluciones para la resolución de captcha mejoran la experiencia del usuario mientras garantizan un 100% de cumplimiento al ayudar a resolver las dificultades de captcha durante el rastreo de datos públicos. Fomentamos el uso responsable de nuestros servicios. Para obtener más información, visite nuestros Términos de Servicio y Política de Privacidad.

Máse