---
name: agent-browser
description: >
  Herramienta de scraping web que permite al agente controlar un navegador Chrome
  real para extraer contenido de páginas dinámicas, detrás de login, con JavaScript
  pesado o con lazy loading. Usa 82% menos tokens que Playwright MCP y permite
  5-6x más páginas por sesión. Parte del stack de investigador-swl como fallback
  cuando WebFetch devuelve contenido incompleto. También alimenta directamente
  el wiki de proyecto (raw/) con fuentes verificadas.
user-invocable: false
version: "1.2.0"
herramientasPermitidas: [Read, Bash, WebFetch, Skill]
skillsInvocables: [browser-interaction-patterns, browser-research-domains]
evolved: true
evolved-from: "1.6.3"
evolved-at: "2026-05-18"
evolved-by: "aprender"
evolved-note: "Adoptar patrones CDP de browser-harness (MIT) — coordinate clicks, wait_for_network_idle, dialogs auto-detect; añadir skillsInvocables a 2 skills nuevos consolidados"
fuente: "Vercel Labs agent-browser — 26K+ GitHub stars (2026-04); patrones CDP avanzados adaptados de browser-use/browser-harness (MIT, 2026)"
evolvable: true  # default para skill estandar
exclusiones:
  - "No cargar para scraping de páginas estáticas simples — usar WebFetch directamente, es más rápido y sin overhead."
  - "No cargar para descarga de PDFs desde URLs directas — usar WebFetch o Read tool según el caso."
  - "No cargar para automatización de UI (formularios, clicks, flujos de usuario) — para automatización cargar `playwright-testing` o equivalente."
  - "No cargar para integración de OCR sobre imágenes — agent-browser no tiene capacidad de reconocimiento de texto en imágenes."
---
# Skill: agent-browser

Proporciona al agente capacidad de scraping web mediante un navegador Chrome real
controlado desde CLI. Diseñado para ser el fallback de WebFetch cuando el contenido
requiere JavaScript, interacción o autenticación.

## Cuándo NO cargar

- La página es estática (HTML simple sin JS): usar `WebFetch` — es más rápido y sin overhead.
- Se descarga un PDF desde una URL directa: usar `WebFetch` con la URL del PDF.
- La tarea es automatización de UI (formularios, flujos, clicks programáticos): cargar `playwright-testing`.
- La tarea requiere OCR sobre capturas de pantalla: agent-browser no reconoce texto en imágenes.

## Cuándo usar este skill vs WebFetch

| Situación | Usar |
|-----------|------|
| Página estática (HTML simple) | `WebFetch` — más rápido y sin overhead |
| Página con JS dinámico (React, Vue, Angular) | `agent-browser` |
| Contenido detrás de login o paywall | `agent-browser` |
| Lazy loading / infinite scroll | `agent-browser` |
| WebFetch devuelve HTML vacío o parcial | `agent-browser` como fallback |
| Research intensivo (5+ páginas seguidas) | `agent-browser` — 82% menos tokens |
| PDF descargable desde URL | `WebFetch` con la URL directa del PDF |

**Regla de decisión rápida**: si `WebFetch` devuelve menos de 500 palabras de contenido
real en una página que visualmente tiene más contenido, usar `agent-browser`.

## Paso 0 — Verificar disponibilidad

```bash
agent-browser --version 2>/dev/null || echo "NOT_INSTALLED"
```

Si devuelve `NOT_INSTALLED`:

### Instalación (una vez por máquina)

```bash
# Instalar CLI global
npm install -g agent-browser

# Descargar Chrome dedicado (requiere ~300MB de espacio)
agent-browser install
```

Verificar instalación:
```bash
agent-browser --version
# Esperado: agent-browser/X.Y.Z
```

Si npm no está disponible, reportar al usuario:
```
⚠ agent-browser requiere npm (Node.js). Si no tienes Node instalado:
  Windows: winget install OpenJS.NodeJS.LTS
  macOS:   brew install node
  Linux:   apt install nodejs npm

Alternativa inmediata: usa WebFetch con la URL y acepta que el contenido
puede estar incompleto en páginas dinámicas.
```

## Paso 1 — Scraping básico

### Extraer texto de un artículo

```bash
# Abrir la página en el navegador controlado
agent-browser open https://url-del-articulo.com

# Extraer el texto del contenido principal
agent-browser get text "article"

# Alternativa si "article" no funciona (selector más amplio)
agent-browser get text "main"
agent-browser get text "body"
```

### Guardar directamente a un archivo

```bash
agent-browser open https://url.com
agent-browser get text "article" > .planning/knowledge/raw/$(date +%Y%m%d)-nombre-fuente.md
```

### Páginas con navegación requerida

```bash
# Abrir y esperar a que cargue
agent-browser open https://url.com
agent-browser wait 2000   # esperar 2 segundos para JS

# Hacer scroll para cargar contenido lazy
agent-browser scroll down 3

# Extraer después del scroll
agent-browser get text "main"
```

## Paso 2 — Patrones de uso frecuentes

### Patrón A: Investigación de documentación técnica

```bash
# Para cada URL en la lista de investigación:
for URL in "https://docs.fastapi.tiangolo.com/async/" "https://docs.python.org/3/library/asyncio.html"; do
  agent-browser open "$URL"
  FILENAME=$(echo "$URL" | sed 's|https://||' | sed 's|[/.]|-|g' | cut -c1-60)
  agent-browser get text "main" > ".planning/knowledge/raw/${FILENAME}.md"
  echo "✓ Guardado: $FILENAME.md"
done
```

### Patrón B: Scraping de página con login (manual)

```bash
# 1. Abrir en modo visible (el usuario puede hacer login manual)
agent-browser open https://sitio-con-login.com --headed

# 2. El agente espera a que el usuario complete el login
# (Pausar y pedir confirmación al usuario antes de continuar)

# 3. Navegar a la página deseada
agent-browser navigate https://sitio-con-login.com/docs/pagina-privada

# 4. Extraer contenido
agent-browser get text "article"
```

### Patrón C: Comparar múltiples páginas (benchmark de librerías)

```bash
LIBBRERIAS=("fastapi" "flask" "django")
for LIB in "${LIBBRERIAS[@]}"; do
  agent-browser open "https://pypi.org/project/${LIB}/"
  agent-browser get text ".package-description" > ".planning/knowledge/raw/${LIB}-pypi.md"
done
```

## Paso 3 — Integración con el wiki de proyecto

Después de scrapear fuentes, ingerir al wiki:

```bash
# 1. Scrapear y guardar en raw/
agent-browser open https://url.com
agent-browser get text "article" > .planning/knowledge/raw/$(date +%Y%m%d)-fuente.md

# 2. Decirle al agente que ingiera en el wiki
# (El agente lee raw/, extrae knowledge, actualiza wiki/)
```

Luego ejecutar `/swl:wiki ingest .planning/knowledge/raw/YYYY-MM-DD-fuente.md`
para integrar la fuente al wiki del proyecto.

## Paso 4 — Limitaciones y workarounds

| Limitación | Workaround |
|-----------|------------|
| Páginas con captcha | No automatizable — usar WebFetch o copiar manualmente |
| Sitios que bloquean headless browsers | Agregar `--headed` para abrir Chrome visible |
| Contenido en iframes | `agent-browser get text "iframe"` o navegar directamente al src del iframe |
| PDFs embebidos | Descargar el PDF con su URL directa y leer con Read tool |
| Imágenes con texto (OCR) | agent-browser no tiene OCR — capturar con `agent-browser screenshot` y procesar aparte |

## Eficiencia de tokens

agent-browser usa **82% menos tokens que Playwright MCP** porque:
- No transmite el árbol DOM completo entre el navegador y el agente
- Solo extrae el selector solicitado, no toda la página
- No requiere que el agente genere código de automatización

**Implicación práctica**: Con Playwright MCP, una sesión de investigación de 10 páginas
puede consumir 50K tokens solo en overhead de scraping. Con agent-browser: ~9K tokens.

## Señales de que agent-browser completó correctamente

✓ Output tiene >200 palabras de contenido real (no solo tags HTML)
✓ El contenido incluye el texto principal del artículo/documentación
✓ No hay mensajes de error como "ERR_CONNECTION_REFUSED" o "Navigation timeout"

## Señales de problema

- Output vacío o <50 palabras → la página puede tener captcha o bloqueo activo
- Mensaje "Navigation timeout" → la URL no carga; verificar la URL
- Contenido solo de navegación (menús, headers) → el selector es incorrecto; probar "body" o "main"

## Gotchas / Errores comunes no obvios

**`agent-browser get text "article"` devuelve vacío aunque la página tenga contenido visible**: el selector CSS apunta a un elemento que no existe en el DOM real de la página. Causa: la página puede usar `<main>`, `<section>`, o un div con clase en lugar de `<article>` semántico. Fix: intentar selectores alternativos en orden: `"article"` → `"main"` → `".content"` → `"body"`. Si ninguno funciona, usar `agent-browser get text "body"` para capturar todo y filtrar manualmente.

**`agent-browser open` completa sin error pero el contenido todavía está cargando cuando se llama `get text`**: algunas SPAs cargan el contenido principal de forma asíncrona después del evento DOMContentLoaded. Causa: `open` espera el evento de carga inicial, no la hidratación completa de React/Vue/Angular. Fix: agregar `agent-browser wait 2000` entre `open` y `get text` para dar tiempo al JS de renderizar el contenido. Para páginas con lazy loading, combinar con `agent-browser scroll down 3` antes de extraer.

**Usar `agent-browser` en un loop con 10+ URLs causa que el proceso Chrome se quede sin memoria y falle silenciosamente**: el Chrome controlado no libera memoria entre páginas del mismo proceso. Causa: cada `open` reutiliza el mismo proceso Chrome sin reiniciarlo. Fix: para loops de investigación intensiva (>10 URLs), dividir en sub-lotes y reiniciar `agent-browser` entre grupos, o procesar en secuencia con pausa de 500ms entre páginas.

**`agent-browser navigate` a una página de login redirecciona a la URL original sin error**: si el sitio detecta el browser headless y redirecciona al login, el agente no recibe señal de fallo — simplemente extrae el contenido del formulario de login en lugar de la página deseada. Causa: sites como LinkedIn, Cloudflare-protected pages bloquean headless browsers. Fix: verificar que el output extraído contiene el contenido esperado (>200 palabras reales), no un formulario. Usar `--headed` para hacer el login visible y manual cuando el sitio requiere autenticación humana.

## Patrones avanzados de CDP (adoptados de browser-harness MIT)

Cuatro patrones que mejoran robustez y reducen tokens, adaptados del runtime
`browser-use/browser-harness`. Aplican aunque agent-browser sea otra
implementación (npm CLI vs Python CDP) — son patrones agnósticos al runtime.

### 1. Coordinate clicks > selector clicks

Cuando la página tiene iframes cross-origin, shadow DOM, o componentes
complejos, los selectors CSS son frágiles. La alternativa robusta es operar
a nivel **compositor** de Chrome con eventos de mouse por coordenadas.

```bash
# MAL — selector frágil cuando hay iframe o shadow DOM
agent-browser click "button.submit-btn"

# BIEN — leer coordenadas del screenshot y click por XY
agent-browser screenshot /tmp/page.png
# (visual: el botón está en ~ x=420, y=380)
agent-browser click-xy 420 380
agent-browser screenshot /tmp/after.png  # verificar
```

El click coordinate atraviesa iframes cross-origin y shadow DOM sin trabajo
extra porque sucede en el compositor antes de llegar al árbol DOM. Solo bajar
a DOM-level cuando el elemento NO tiene geometría visible.

### 2. `wait_for_network_idle` > `wait` fijo

Esperar timeouts fijos (`wait 2000`) es ciego — desperdicia tiempo en páginas
rápidas y falla en páginas lentas. El patrón correcto es esperar evento-driven
hasta que NO haya requests pendientes por N ms.

```bash
# MAL — timeout ciego
agent-browser open https://app-spa.com
agent-browser wait 2000
agent-browser get text "main"

# BIEN — esperar idle de red (event-driven)
agent-browser open https://app-spa.com
agent-browser wait-network-idle --timeout 10000 --idle-ms 500
agent-browser get text "main"
```

Si tu agent-browser CLI no expone este helper, fallback razonable: `wait` con
verificación posterior (screenshot + assert que el contenido renderizó).

### 3. Screenshots primero para verificación

Tras CUALQUIER acción que modifica estado (click, navigate, form submit), la
única señal confiable de éxito es re-capturar screenshot. El DOM puede
mentir durante transiciones; `page_info()` puede tener race conditions.

```bash
# MAL — asumir que el click funcionó
agent-browser click-xy 420 380
agent-browser get text ".confirmation-msg"  # puede estar vacío

# BIEN — screenshot intermedio verifica visualmente
agent-browser click-xy 420 380
agent-browser screenshot /tmp/after-click.png
# Inspeccionar visualmente o cargar a vision LLM para verificar
agent-browser get text ".confirmation-msg"
```

### 4. Auto-detección de dialogs antes de actuar

Los dialogs nativos (`alert`, `confirm`, `prompt`, `beforeunload`) **congelan
el thread de JS** del page. Cualquier acción siguiente cuelga hasta que el
dialog se resuelva. Patrón seguro: verificar `page_info()` antes de cada
acción tras navegación o form submit.

```bash
agent-browser open https://site.com/form
agent-browser submit-form
# Antes del siguiente click, verificar
agent-browser page-info
# Si retorna {"dialog": {"type": "beforeunload", "message": "..."}},
# dismissar con accept o cancel antes de continuar
agent-browser dismiss-dialog --accept
```

Si el CLI de agent-browser no expone helper de dialog, la opción CDP raw es
`Page.handleJavaScriptDialog`. Inyectar stubs JS (`window.alert = ...`) es
alternativa solo cuando NO hay `beforeunload` involucrado.

## Cuándo cargar skills complementarios

Cuando este skill base no resuelve el caso:

- **`browser-interaction-patterns`** — escalas a un tropiezo específico:
  iframes cross-origin, shadow DOM, dropdown que no responde, upload bloqueado,
  cookies HttpOnly, network requests que no producen DOM change. 14 patrones
  con código MAL/BIEN.
- **`browser-research-domains`** — el research toca github, arxiv, hackernews,
  stackoverflow, pubmed, openalex o sec edgar. Para esos dominios, **NUNCA
  abras un browser** — todo está en API. Reduce tokens 20-50× y latencia 5-20×.

Cargar con `Skill("browser-interaction-patterns")` o
`Skill("browser-research-domains")` según necesidad.
