Files
fn_registry/python/functions/browser/fetch_http_fingerprint_cdp.md
T
egutierrez 1430039688 feat(recon): modo CDP en fingerprint_web_stack para detectar SPAs
Añade fetch_http_fingerprint_cdp_py_browser (domain browser): recoge el HTML
renderizado tras ejecutar JavaScript usando un Chrome remoto via CDP, componiendo
cdp_open_url_and_wait + cdp_eval. Devuelve la misma estructura que el fetch
estático para que detect_web_tech lo consuma sin cambios.

Integra use_cdp en el pipeline fingerprint_web_stack (v1.1.0): combina los headers
reales del fetch estático con el HTML post-JS del CDP. Detecta frameworks de SPA
(React/Vue/Angular/Next) que el fetch estático no ve porque montan el DOM en
runtime. Si no hay Chrome en cdp_port, degrada al fetch estático con un warning
(no rompe). cdp_port=9333 (Chrome aislado) recomendado para terceros, 9222 diario.

Verificado en vivo (Chrome 9333): sobre una SPA cuyo marcador de framework solo
aparece tras ejecutar JS, el estático detecta solo nginx; con use_cdp=True detecta
además Next.js, React y Node.js.

Tests: 48 verdes (error path sin Chrome + happy path mockeado + degradación).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 15:31:28 +02:00

5.1 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
fetch_http_fingerprint_cdp function py browser 1.0.0 impure def fetch_http_fingerprint_cdp(url: str, *, port: int = 9222, wait_render_s: float = 2.0, timeout_s: float = 30.0, close_tab: bool = True) -> dict Fingerprint web con HTML RENDERIZADO tras ejecutar JavaScript via Chrome DevTools Protocol (CDP). Navega con un Chrome remoto, espera a que la SPA monte el DOM y recoge el HTML post-JS, titulo, URL final y nombres de cookie. Detecta frameworks que el fetch estatico NO ve: React, Vue, Angular, Next, Svelte montados en runtime. Wappalyzer dinamico: devuelve la MISMA estructura que fetch_http_fingerprint para que detect_web_tech la consuma sin cambios. Recon web de SPAs / single-page applications con HTML inicial vacio.
recon
web-recon
browser
cdp
fingerprint
spa
wappalyzer
javascript
react
vue
angular
cdp_open_url_and_wait_py_pipelines
cdp_eval_py_browser
false error_py_core
name desc
url URL objetivo del fingerprint (sitio a inspeccionar).
name desc
port Puerto de remote debugging del Chrome a usar. Default 9222 (navegador diario, activado global). Para aislamiento de recon de terceros, apuntar a 9333 (Chrome aislado del browser_mcp).
name desc
wait_render_s Segundos extra de espera tras el load event para que el JS de la SPA pinte el DOM (el load NO garantiza render completo). Default 2.0.
name desc
timeout_s Timeout de la navegacion en segundos. Default 30.0.
name desc
close_tab Si True, cierra el tab al terminar (best-effort via window.close()) para no dejar pestanas abiertas. Default True.
dict siempre (nunca lanza). En exito: {status:'ok', url, final_url, title, status_code:None, headers:{}, cookies:[solo nombres no-httponly], html:<RENDERIZADO post-JS>, html_len, rendered:True, raw}. En error: {status:'error', error:<mensaje claro>, url}. status_code/headers quedan vacios porque CDP no expone la capa de red; esta funcion aporta el HTML renderizado, que es lo que detect_web_tech necesita para una SPA. true
test_sin_chrome_devuelve_error_sin_lanzar
test_url_vacia_devuelve_error
test_happy_path_monkeypatch
test_happy_path_eval_falla_devuelve_error
python/functions/browser/fetch_http_fingerprint_cdp_test.py python/functions/browser/fetch_http_fingerprint_cdp.py

Ejemplo

import sys, os, json
sys.path.insert(0, os.path.join("python", "functions"))
from browser.fetch_http_fingerprint_cdp import fetch_http_fingerprint_cdp
from cybersecurity.detect_web_tech import detect_web_tech

# Recoge el HTML RENDERIZADO (post-JS) de una SPA via el Chrome diario (9222).
res = fetch_http_fingerprint_cdp("https://react.dev/", port=9222)
if res["status"] == "ok":
    # detect_web_tech (PURA) consume las mismas senales que fetch_http_fingerprint.
    tech = detect_web_tech(
        res["headers"],            # {} con CDP — usa el fetch estatico para headers
        html=res["html"],          # el HTML RENDERIZADO post-JS: aqui esta la clave
        cookies=res["cookies"],    # solo nombres
        final_url=res["final_url"],
    )
    print(json.dumps(tech, ensure_ascii=False, indent=2))
else:
    print("error:", res["error"])

Cuando usarla

Cuando el fetch estatico (fetch_http_fingerprint) NO detecta el framework porque el sitio es una SPA que monta el DOM con JavaScript (HTML inicial casi vacio: <div id="root"> o <div id="__next"> sin contenido). Esta funcion recoge el HTML DESPUES de que el JS pinte, de modo que detect_web_tech ve React / Vue / Angular / Next igual que un Wappalyzer dinamico. Requiere un Chrome con remote debugging. Combina ambas capas para fingerprint completo: estatico para headers + status + cookies httponly; CDP para el HTML renderizado.

Gotchas

  • Requiere un Chrome con remote debugging escuchando en port: 9222 (navegador diario, ya activado global) o 9333 (Chrome aislado del browser_mcp). Sin Chrome vivo devuelve {status:"error", error:"no hay Chrome en el puerto N (¿remote debugging activo?)"} — no lanza.
  • Abre un tab en ESE navegador. Con port=9222 mezcla la sesion de tu navegador PERSONAL (cookies de tu sesion, historial). Para recon de TERCEROS prefiere port=9333 (aislado) para no contaminar ni filtrar tu sesion.
  • document.cookie NO ve cookies httponly (las de sesion casi siempre lo son): esas y los headers de respuesta vienen mejor del fetch estatico fetch_http_fingerprint.
  • headers y status_code quedan vacios/None: CDP no expone la capa de red sin el dominio Network. Esta funcion aporta el HTML renderizado, no la red. Si necesitas el status real o headers, usa el fetch estatico en paralelo.
  • wait_render_s puede ser insuficiente para SPAs lentas (mucho data-fetching tras el load). Si el html sale incompleto, sube wait_render_s (ej. 4.0-6.0).
  • Respeta scope y autorizacion legal: solo inspecciona sitios que tengas permiso para analizar.