Files
fn_registry/functions/browser/detect_captcha.md
T
egutierrez 763e06c127 feat(browser): auto-commit con 178 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-20 18:22:23 +02:00

3.7 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports params output tested tests test_file_path file_path
detect_captcha function go browser 1.0.0 impure func DetectCaptcha(c *CDPConn) (detected bool, types []string, url string, err error) Detecta captchas y challenges anti-bot en la pagina actual via CDP: reCAPTCHA, hCaptcha, Cloudflare Turnstile (por iframe/widget) y el JS-challenge de Cloudflare (por texto). Solo detecta — no resuelve ni notifica. Una responsabilidad.
captcha
browser
cdp
antibot
detection
perception
cdp_evaluate_go_browser
false error_go_core
encoding/json
fmt
name desc
c Conexion CDP activa a una tab de Chrome de tipo 'page'. La evaluacion corre en el top frame.
Tupla (detected, types, url, err). detected=true si hay al menos una senal anti-bot. types es el subconjunto de senales detectadas (de: 'recaptcha', 'hcaptcha', 'turnstile', 'challenge'), siempre slice no nulo (vacio si nada). url es la location.href del top frame. err si la conexion es nula, falla el eval CDP, o el JSON resultante es invalido. Una excepcion JS en la pagina se trata como detected=false best-effort, sin error. true
recaptcha detectado
hcaptcha detectado
turnstile detectado
challenge por texto
multiples senales
ninguno
campo error best-effort no rompe
types ausente se normaliza a slice vacio
json invalido devuelve error
functions/browser/detect_captcha_test.go functions/browser/detect_captcha.go

Ejemplo

// Conectar a un Chrome con CDP abierto (mismo patron que cdp_get_text)
conn, err := CdpConnect(9222)
if err != nil {
    log.Fatal(err)
}
defer CdpDisconnect(conn)

// Tras navegar y esperar la carga, comprobar si la pagina puso un captcha
detected, types, url, err := DetectCaptcha(conn)
if err != nil {
    log.Fatal(err)
}
if detected {
    fmt.Printf("captcha detectado en %s: %v\n", url, types)
    // p.ej. -> "captcha detectado en https://x.test/login: [recaptcha]"
} else {
    fmt.Println("sin captcha, seguir clicando")
}

Cuando usarla

Tras navegar o esperar la carga de una pagina, para saber si esta puso un captcha o challenge anti-bot antes de seguir clicando o enviando formularios. La usa el browser_mcp en sus handlers de navegacion para decidir el handoff humano: si DetectCaptcha devuelve detected=true, el flujo automatico se detiene y avisa para resolucion manual en vez de chocar contra el muro.

Gotchas

  • Solo top frame: la evaluacion corre en el frame principal. Un captcha incrustado en un iframe anidado profundo cuyo src no matchee los patrones no se detecta.
  • Iframes cross-origin: el contenido de los iframes de reCAPTCHA/hCaptcha/Turnstile NO se lee (politica same-origin), pero SI se detectan por su src y por las clases del widget host (.g-recaptcha, .h-captcha, .cf-turnstile), que viven en el top document.
  • Falsos positivos posibles: la senal challenge viene de regex sobre innerText (p.ej. "verify you are human", "unusual traffic"). Una pagina con ese texto en otro contexto (un articulo, una FAQ sobre bots) puede dar detected=true sin haber captcha real.
  • No detecta captchas custom: solo cubre los proveedores listados (reCAPTCHA, hCaptcha, Turnstile) + el JS-challenge de Cloudflare. Captchas propios o de otros vendors no se reconocen.
  • Depende de innerText: la pagina debe haber pintado el body. En una tab aun cargando (document.body nulo o vacio) la senal challenge puede no dispararse — esperar con cdp_wait_load antes de detectar si el contenido es dinamico.
  • Impura: hace un round-trip CDP (I/O de red). Requiere conexion activa a una tab de tipo page.