
Aloísio Vítor
Image Processing Expert

sessions: write, que devuelve 403, y la falta de una anotación BaseModel de Pydantic en el primer parámetro de la herramienta, que activa un ValidationError.Este guía integra CapSolver con Composio como una herramienta de agente que completa un flujo de reCAPTCHA v2. En lugar de devolver solo un token, la herramienta ejecuta la secuencia completa de la página y trata la respuesta real de la página como la condición de éxito. SDK de Agentes de OpenAI decide cuándo llamar a la herramienta, mientras que automatización del navegador de Playwright preserva el contexto de la página utilizado para la presentación y verificación.
Use este patrón solo para flujos legales, razonables, responsables y autorizados por el usuario. La capacidad técnica no otorga permiso para acceder a datos privados, restringidos, sensibles o no autorizados; revise la guía de automatización de IA antes de la implementación.
Flujo de trabajo:
Ejecute el script
-> El SDK de Agentes de OpenAI decide qué herramienta llamar
-> Herramienta personalizada de Composio: complete_recaptcha_v2
-> Playwright abre la página
-> capsolver.solve(...) devuelve gRecaptchaResponse
-> Aplicar el token a g-recaptcha-response
-> Playwright envía y espera la página
-> Leer la página y determinar aceptado
-> La herramienta devuelve {"accepted": ..., "message": ...}
-> El agente informa el resultado de accepted
Los componentes tienen las siguientes responsabilidades:
| Componente | Responsabilidad |
|---|---|
| SDK de Agentes de OpenAI | Entiende las instrucciones en lenguaje natural, decide cuándo llamar a la herramienta, la ejecuta y organiza la respuesta |
| Composio | Registra una función de Python estándar como una herramienta llamable por el agente |
| Playwright | Abre la página, aplica el resultado, envía el formulario y lee el estado de la página resultante |
| SDK de CapSolver | Devuelve el resultado de la CAPTCHA a través de una llamada única solve() |
pip install composio composio-openai-agents openai-agents capsolver pydantic playwright
playwright install chromium
Cada dependencia sirve un rol específico:
| Paquete | Propósito |
|---|---|
| composio | Crea sesiones y registra o carga herramientas personalizadas |
| composio-openai-agents | Convierte herramientas de Composio en objetos que los Agentes de OpenAI pueden llamar |
| openai-agents | Proporciona Agent, Runner y memoria multi-turno de SQLite |
| capsolver | Proporciona el SDK oficial y devuelve un resultado a través de solve() |
| pydantic | Define el esquema de entrada de la herramienta |
| playwright | Abre páginas, aplica resultados, envía formularios y lee respuestas |
# Claves de API.
COMPOSIO_API_KEY = "ak_..."
OPENAI_API_KEY = "sk-..." # Su clave oficial de API de OpenAI.
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY # El SDK de OpenAI lee la clave desde el entorno.
# Configure CapSolver y Composio.
capsolver.api_key = "CAP-..."
composio = Composio(
api_key=COMPOSIO_API_KEY,
provider=OpenAIAgentsProvider(),
)
Notas de configuración:
OPENAI_API_KEYdebe escribirse en el entorno porque el SDK la lee allí;OpenAIAgentsProviderhace que las herramientas devueltas porsession.tools()sean compatibles con Agent; y la clave de Composio necesita permisosessions: writeo la creación de sesión devuelve 403.
La actual proveedor de OpenAI de Composio y SDK de Agentes de OpenAI explican el límite del proveedor y agente utilizado por esta configuración.
Canjea tu código de bonificación de CapSolver
¡Aumenta tu presupuesto de automatización de inmediato!
Usa el código de bonificación CAP26 al recargar tu cuenta de CapSolver para obtener un 5% adicional de bonificación en cada recarga — sin límites.
Canjéalo ahora en tu Panel de CapSolver
Condición de parada: la herramienta reporta éxito solo cuando la página contiene el texto de éxito esperado. El bloque
finallycierra el navegador en ambos caminos de éxito y fallo.
import os
from typing import List, cast
import capsolver
from agents import Agent, Runner, SQLiteSession
from composio import Composio
from composio.core.models.custom_tool import CustomTool
from composio.core.models.tool_router import ToolRouterExperimentalConfig
from composio_openai_agents import OpenAIAgentsProvider
from playwright.sync_api import sync_playwright
from pydantic import BaseModel, Field
# Claves de API.
COMPOSIO_API_KEY = "ak_..."
OPENAI_API_KEY = "sk-..." # Su clave oficial de API de OpenAI.
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
# Configure CapSolver y Composio.
capsolver.api_key = "CAP-..."
composio = Composio(
api_key=COMPOSIO_API_KEY,
provider=OpenAIAgentsProvider(),
)
# Esquema de entrada para la herramienta personalizada; Composio requiere un BaseModel de Pydantic aquí.
class CompleteRecaptchaInput(BaseModel):
target_url: str = Field(
default="https://www.google.com/recaptcha/api2/demo",
description="URL de la página que contiene el demo de reCAPTCHA v2",
)
website_key: str = Field(
default="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
description="Clave de sitio de reCAPTCHA v2 del sitio actual",
)
# Registre todo el flujo como una herramienta de Composio que el agente puede llamar.
# La anotación del tipo del primer parámetro es requerida por Composio para inferir el esquema.
@composio.experimental.tool(preload=True)
def complete_recaptcha_v2(input: CompleteRecaptchaInput, _ctx):
"""Abra la página con Playwright, resuelva reCAPTCHA v2, envíe y verifique."""
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # Establezca headless=True para ocultar la ventana.
page = browser.new_page()
try:
page.goto(input.target_url)
# Pida a CapSolver que resuelva el desafío reCAPTCHA v2.
solution = capsolver.solve(
{
"type": "ReCaptchaV2TaskProxyLess",
"websiteURL": input.target_url,
"websiteKey": input.website_key,
}
)
token = solution.get("gRecaptchaResponse")
page.evaluate(
"""
(token) => {
const textarea = document.getElementById('g-recaptcha-response');
if (textarea) {
textarea.value = token;
}
}
""",
token,
)
page.click("#recaptcha-demo-submit")
page.wait_for_load_state("networkidle")
result_page = page.content()
# Éxito solo si la página muestra realmente el texto de éxito
accepted = "Verification Success" in result_page
return {
"accepted": accepted,
"message": (
"Verification Success"
if accepted
else "La página no informó Verification Success"
),
}
finally:
browser.close()
def main():
experimental: ToolRouterExperimentalConfig = {
"custom_tools": cast(List[CustomTool], [complete_recaptcha_v2]),
}
session = composio.sessions.create(
user_id="playwright-recaptcha-demo-user",
experimental=experimental,
sandbox={"enable": False}, # Ejecute la herramienta en este proceso, no en un sandbox.
)
agent = Agent(
name="Asistente de reCAPTCHA de Playwright",
instructions=(
"Cuando el usuario pida ejecutar el demo, llame a complete_recaptcha_v2 "
"con sus valores predeterminados. Informe éxito solo cuando accepted sea verdadero."
),
model="gpt-5.2",
tools=session.tools(),
)
# Memoria para conversación multi-turno
memory = SQLiteSession("conversation")
print("Demo de Composio + reCAPTCHA v2 de Playwright en ejecución...")
user_input = (
"Llame a complete_recaptcha_v2 ahora con sus valores predeterminados de target_url "
"y website_key. No pida confirmación."
)
result = Runner.run_sync(
starting_agent=agent,
input=user_input,
session=memory,
)
print(f"Asistente: {result.final_output}\n")
if __name__ == "__main__":
main()
El mismo patrón puede manejar una CAPTCHA estándar de imagen-texto registrando una segunda herramienta de Composio. Este ejemplo utiliza el demo de CAPTCHA de BotDetect: el elemento de imagen es #demoCaptcha_CaptchaImage, el campo de entrada es #captchaCode y el botón de validación es #validateCaptchaButton.

La solicitud ImageToTextTask envía la imagen en base64 a través de body. A diferencia de las tareas basadas en tokens, esta tarea devuelve directamente el texto reconocido y no requiere un bucle de sondeo separado.
image_src = page.locator("#demoCaptcha_CaptchaImage").get_attribute("src")
if not image_src or "," not in image_src:
raise RuntimeError("No se encontró una URL de datos de imagen CAPTCHA válida")
base64_image = image_src.split(",", 1)[1] # Elimine el prefijo "data:image/...;base64,"
class CompleteImageCaptchaInput(BaseModel):
target_url: str = Field(
default="https://captcha.com/demos/features/captcha-demo.aspx",
description="URL de la página de demostración de CAPTCHA de imagen",
)
module: str = Field(
default="common",
description="Módulo de reconocimiento ImageToTextTask de CapSolver",
)
@composio.experimental.tool(preload=True)
def complete_image_captcha(input: CompleteImageCaptchaInput, _ctx):
"""Abra la página con Playwright, reconozca la CAPTCHA de imagen, envíe y verifique."""
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
try:
page.goto(input.target_url)
page.wait_for_selector("#demoCaptcha_CaptchaImage", state="visible")
# La src de la imagen ya es una URL de datos; elimine el prefijo para obtener Base64.
image_src = page.locator("#demoCaptcha_CaptchaImage").get_attribute("src")
if not image_src or "," not in image_src:
raise RuntimeError("No se encontró una URL de datos de imagen CAPTCHA válida")
base64_image = image_src.split(",", 1)[1]
solution = capsolver.solve(
{
"type": "ImageToTextTask",
"websiteURL": input.target_url,
"module": input.module,
"body": base64_image,
}
)
captcha_text = solution.get("text")
if not isinstance(captcha_text, str) or not captcha_text:
raise RuntimeError("CapSolver no devolvió texto reconocido")
page.fill("#captchaCode", captcha_text) # Escriba el resultado en #captchaCode.
page.click("#validateCaptchaButton")
page.wait_for_load_state("networkidle")
result_page = page.content()
# La página de demostración muestra "Correct!" en éxito, "Incorrect!" en fallo.
accepted = "Correct!" in result_page
return {
"accepted": accepted,
"recognized_text": captcha_text,
"message": "Correct!" if accepted else "La página no informó Correct!",
}
finally:
browser.close()
Resumen del flujo:
Playwright abre la página de CAPTCHA
-> Esperar a que #demoCaptcha_CaptchaImage sea visible
-> Leer src (URL de datos) y eliminar el prefijo para obtener Base64
-> capsolver.solve(ImageToTextTask) devuelve texto
-> page.fill escribe el resultado en #captchaCode
-> page.click activa #validateCaptchaButton
-> page.content comprueba Correct! o Incorrect!
-> finally cierra el navegador
El parámetro module es opcional y predeterminado a common. Si la CAPTCHA contiene solo números, use number. Los estilos especiales pueden usar un modelo independiente documentado cuando sea apropiado.

Por ejemplo, use el siguiente código sin cambios para el reconocimiento solo numérico:
solution = capsolver.solve({
"type": "ImageToTextTask",
"module": "number",
"images": [base64_image],
})
answers = solution["answers"]
El modelo number admite múltiples imágenes en una sola entrega, y images puede contener hasta nueve cadenas en base64. Los nombres de los modelos admitidos y los casos de uso se enumeran en la página ImageToTextTask de CapSolver.
experimental.tool: el primer parámetro de "complete_recaptcha_v2" debe estar anotado con una subclase de BaseModel de Pydantic. Obtenido: <class 'inspect._empty'>
Composio infiere el esquema de entrada del primer parámetro de la anotación de tipo, por lo que input: CompleteRecaptchaInput no puede omitirse. Esta es una anotación funcional, no una pista de tipo opcional. La referencia BaseModel de Pydantic describe el tipo de modelo utilizado para el esquema.
La creación de sesión puede devolver el siguiente error:
403 APIKey_InsufficientPermissions
Esta ruta requiere acceso de escritura a "sessions"
La causa es que composio.sessions.create() requiere acceso de escritura al project-key para sesiones, mientras que la clave actual tiene acceso de solo lectura. La clave es válida, pero su alcance es insuficiente, por lo que la respuesta es 403 en lugar de 401.
Pasos para resolver:
sessions: write y reemplace COMPOSIO_API_KEY en la parte superior del script.El núcleo de esta integración es un flujo de trabajo empresarial completo empaquetado como una herramienta de Composio:
Herramienta de Composio = Acciones de página de Playwright + resultado de CapSolver + verificación del estado de la página
Ejecute el ejemplo solo en páginas y procesos que usted posea o esté autorizado a automatizar. Use variables de entorno o un gestor de secretos para las credenciales, deténgase cuando la página no alcance el estado empresarial esperado y revise los errores repetidos en lugar de reintentar indefinidamente.
Para un flujo de trabajo de agente autorizado de Composio que necesite una capa de infraestructura de CAPTCHA enfocada, pruebe CapSolver con sus propias páginas controladas y verifique el resultado de la aplicación después de cada resolución.
¿Qué maneja Composio en esta integración?
Composio registra la función de Python como una herramienta personalizada llamable por un agente, crea la sesión, expone el esquema de la herramienta y enruta la ejecución desde el agente de OpenAI.
¿Por qué el primer parámetro de la herramienta debe ser un Pydantic BaseModel?
Composio usa esta anotación para inferir el esquema de entrada de la herramienta. Omitirla impide la construcción del esquema y genera un error de validación antes de que comience el flujo del navegador.
¿La herramienta reCAPTCHA v2 se detiene después de que CapSolver devuelve un token?
No. El código sin cambios aplica el token, envía el formulario de demostración, lee el HTML resultante y reporta éxito solo cuando la página contiene el texto de Verificación Exitosa esperado.
¿Requiere ImageToTextTask un bucle de sondeo separado?
No. En este flujo de trabajo, el SDK oficial devuelve el texto reconocido directamente. La herramienta luego completa el campo de entrada, envía la página y verifica "Correcto!" como condición de detención.
¿Puede usarse este flujo en cualquier sitio web?
No. úselo solo para automatización legal, razonable, responsable y autorizada por el usuario. Respete los términos del sitio, las leyes aplicables, los límites de frecuencia y los requisitos de minimización de datos.
Un agente de IA solucionador de reCAPTCHA v3 es confiable solo cuando el agente preserva la acción, la página, la sesión del navegador y el contexto de autorización que generaron el desafío. CapSolver proporciona la capa de infraestructura de CAPTCHA documentada a través de Core SDK, Herramientas del Agente y MCP. El agente sigue teniendo política, reintentos y confirmación de la tarea original. Este guía explica una integración en producción para reCAPTCHA v3, incluido Enterprise, sin tratar un token devuelto como el final succ

Cuando llega un informe de que el agente de IA no resuelve el CAPTCHA, la frase oculta varios fallos diferentes. La detección puede estar equivocada, el agente puede redirigirse a una herramienta no disponible, el navegador puede navegar antes de que el resultado regrese, o la aplicación puede rechazar un resultado que fue técnicamente producido. CapSolver proporciona la infraestructura de CAPTCHA documentada, mientras que su orquestador debe preservar la evidencia y elegir la rama de recuperación correcta. Este guía convierte un incidente vago en una capa
