---
title: "Browser Use con proxy: cómo configurar el agente de IA"
description: "Browser Use permite que un LLM maneje un navegador real desde Python. Configura el agente con proxy autenticado, comprueba su IP de salida y limita los sitios."
url: https://proxynet.io/es/blog/browser-use-proxy
date: 2026-10-05
author: "Acar Diveroli"
category: "Integración, IA"
lang: es
---

# Browser Use con proxy: cómo configurar el agente de IA

En tu equipo, tu agente de Browser Use hace sin problemas un pedido de prueba en la tienda de tu entorno de pruebas (staging). En un servidor en la nube, la misma tarea abre el sitio desde una dirección de centro de datos en otro país: la tienda muestra otra moneda, y el firewall de tu entorno de pruebas, que solo deja entrar IP conocidas, rechaza al agente. Añades un proxy como `http://user:pass@pr.proxynet.io:8000` y, a partir de ese momento, todas las páginas fallan con `net::ERR_NO_SUPPORTED_PROXIES`.

Esta guía explica cómo funciona Browser Use, la instalación, un proxy con usuario y contraseña, la comprobación de la IP de salida, las sesiones fijas y rotativas, los límites de dominio, los secretos y un paso de aprobación humana. Probamos todos los scripts con browser-use 0.13.10 y Python 3.13 a través de un proxy de prueba local que pide contraseña. Como no había ninguna clave de API de un LLM en el equipo de prueba, un script escrito de antemano dio las respuestas del modelo; el navegador, el proxy, el filtro de dominios y el enmascaramiento de secretos sí funcionaron de verdad.

> **Nota: Respuesta breve**
>
> Browser Use es una biblioteca de Python de código abierto (licencia MIT) que permite a un modelo de lenguaje manejar un navegador Chromium: el modelo lee la página, elige acciones como hacer clic o escribir, y la biblioteca las ejecuta. Se instala con `uv pip install browser-use`, y Chromium se descarga con `uvx browser-use install`. El proxy pertenece al navegador: `Browser(proxy=ProxySettings(server="http://pr.proxynet.io:8000", username="user", password="pass"))`. Las credenciales dentro de la dirección del servidor fallan, igual que SOCKS5 con contraseña. Usa una sesión fija para tareas de varios pasos y marcadores de posición en `sensitive_data` para que las contraseñas nunca lleguen al modelo.

## ¿Qué es Browser Use?

Browser Use es una biblioteca de Python que convierte un modelo de lenguaje en un agente de navegador. Describes la tarea con palabras sencillas, y el modelo decide los clics, lo que se escribe y el desplazamiento por la página. El [repositorio de GitHub](https://github.com/browser-use/browser-use) lo describe como «Agents that use the browser» (agentes que usan el navegador); tiene licencia MIT, y la última versión en [PyPI](https://pypi.org/project/browser-use/) es hoy la 0.13.10, publicada el 4 de septiembre de 2026, para Python 3.11 o posterior.

La versión 0.13.10 se comunica con Chromium directamente mediante el Chrome DevTools Protocol (CDP); Playwright no figura entre sus dependencias. El modelo puede venir de OpenAI, Anthropic, Google, un servidor local de Ollama o los modelos alojados del propio Browser Use. Browser Use Cloud, un servicio de pago aparte con navegadores alojados, no forma parte de esta guía.

Cómo planifica un agente y cómo usa herramientas en general se explica en [Agentes de IA: planificación, herramientas y memoria](/es/blog/how-ai-agents-work); los navegadores con un agente integrado, en [¿Qué es un navegador con IA?](/es/blog/what-is-an-ai-browser).

## ¿Cómo funciona un agente de Browser Use?

Una ejecución de `agent.run()` pasa por estos pasos:

1. **El navegador arranca** con un perfil temporal nuevo. El proxy se pasa a Chromium como parámetro de inicio.
2. **Una URL incluida en la tarea se abre directamente**, sin llamar al modelo.
3. **La página se convierte en texto.** Cada elemento que el agente puede usar recibe un número, acompañado del texto visible. Con `use_vision=True` (el valor predeterminado) se añade una captura de pantalla.
4. **El modelo responde en JSON:** una evaluación del último paso, una memoria breve, el siguiente objetivo y hasta cinco acciones, como `navigate`, `click`, `input`, `scroll`, `extract` o `done`.
5. **La biblioteca ejecuta las acciones,** comprueba cada URL nueva con tus reglas de dominio y rellena los secretos donde el modelo escribió un marcador de posición.
6. **El ciclo se repite** hasta que el modelo llama a `done` o se agota `max_steps`.

En una librería de práctica, el estado del navegador que recibió nuestro modelo de prueba contenía líneas como estas:

```text
[587]<a title=It's Only the Himalayas />
	It's Only the Himalayas
£45.17
[597]<i />
In stock
[604]<button type=submit />
	Add to basket
```

Para añadir este libro a la cesta, el modelo respondería `{"click": {"index": 604}}`. Como la página llega en forma de texto, `use_vision=False` también funciona y evita que las capturas de páginas sensibles lleguen al proveedor del modelo.

## ¿Cómo se instala Browser Use?

La guía de inicio rápido oficial usa uv:

```bash
pip install uv
uv venv --python 3.12
source .venv/bin/activate        # Windows: .venv\Scripts\activate
uv pip install browser-use
uvx browser-use install          # descarga Chromium
```

Nosotros instalamos con un simple `pip install browser-use==0.13.10` en un entorno virtual de Python 3.13, y también funcionó. Después, pon las claves en un archivo `.env` junto a tu script:

```bash
OPENAI_API_KEY=...
PROXY_SERVER=http://pr.proxynet.io:8000
PROXY_USERNAME=user
PROXY_PASSWORD=pass
ANONYMIZED_TELEMETRY=false
```

La última línea importa. Browser Use envía telemetría de uso de forma predeterminada, y su [página de telemetría](https://docs.browser-use.com/open-source/development/monitoring/telemetry) indica que puede incluir las instrucciones de la tarea, las URL visitadas, el registro de acciones y los resultados finales. Si tus tareas mencionan clientes o sitios internos, desactívala.

Dos cosas nos sorprendieron en el equipo de prueba con Windows. Sin `executable_path`, Browser Use eligió el Google Chrome instalado, aunque con un perfil temporal nuevo y no con el de uso diario. En el primer arranque también descargó tres extensiones, entre ellas un bloqueador de anuncios, directamente de Chrome Web Store y por fuera del proxy; `enable_default_extensions=False` las desactiva.

## ¿Cómo se ejecuta un agente a través de un proxy?

El proxy es un ajuste del `Browser`, y el agente recibe ese navegador. Este script abre una página de categoría y lee tres libros, saliendo solo por el proxy y solo hacia un dominio:

```python
"""Ejecuta un agente de Browser Use a través de un proxy autenticado, limitado a un solo sitio."""
import asyncio
import os

from dotenv import load_dotenv

load_dotenv()  # lee OPENAI_API_KEY, PROXY_* y ANONYMIZED_TELEMETRY de .env

from browser_use import Agent, Browser, ChatOpenAI
from browser_use.browser import ProxySettings

browser = Browser(
    headless=True,
    proxy=ProxySettings(
        server=os.environ["PROXY_SERVER"],  # http://pr.proxynet.io:8000
        username=os.environ["PROXY_USERNAME"],
        password=os.environ["PROXY_PASSWORD"],
    ),
    allowed_domains=["books.toscrape.com"],
    enable_default_extensions=False,
)

agent = Agent(
    task=(
        "Abre https://books.toscrape.com/catalogue/category/books/travel_2/index.html "
        "y enumera el título y el precio de los tres primeros libros."
    ),
    llm=ChatOpenAI(model="gpt-4.1-mini"),
    browser=browser,
    use_vision=False,
)

async def main():
    history = await agent.run(max_steps=10)
    print("result:", history.final_result())
    print("pages: ", [u for u in history.urls() if u])
    print("steps: ", history.number_of_steps())

asyncio.run(main())
```

`ProxySettings` se importa desde `browser_use.browser`, no desde el paquete principal. La [página de parámetros del navegador](https://docs.browser-use.com/open-source/customize/browser/all-parameters) enumera cuatro campos:

| Campo | Qué recibe |
|---|---|
| `server` | `http://host:port` o `socks5://host:port`, sin credenciales |
| `username` | Usuario del proxy, por ejemplo el que da el Generador de endpoints |
| `password` | Contraseña del proxy |
| `bypass` | Hosts que no pasan por el proxy, separados por comas |

Internamente, Browser Use inicia Chromium con `--proxy-server` y responde él mismo al desafío `407` del proxy mediante CDP. Nuestro proxy de prueba registró exactamente eso para la página del libro (abreviado, sin marcas de tiempo):

```text
407 CONNECT books.toscrape.com:443 (no credentials)
200 CONNECT books.toscrape.com:443 user=user
```

El usuario y la contraseña del proxy no aparecieron en nada de lo que recibió el modelo.

## ¿Por qué falla user:pass en la URL del proxy?

Porque Chromium ignora las credenciales escritas dentro de su ajuste de proxy. Según la [documentación de proxies de Chromium](https://chromium.googlesource.com/chromium/src/+/HEAD/net/docs/proxy.md), Chrome no usa ninguna credencial incrustada en la configuración del proxy. Con `server="http://user:pass@…"` y sin campos aparte, cada navegación de nuestra prueba terminó con `net::ERR_NO_SUPPORTED_PROXIES`. Pon las credenciales en `username` y `password`.

SOCKS5 tiene otro límite: Chromium no admite ningún método de autenticación para SOCKS5. Nuestro servidor SOCKS5 de prueba vio que el navegador solo ofrecía «no authentication» (sin autenticación), y la página falló con `ERR_SOCKS_CONNECTION_FAILED`. Para SOCKS5, añade la IP de tu servidor a la lista de IP autorizadas del panel (hasta 10 direcciones) y usa, sin usuario, el puerto SOCKS5 que muestra el Generador de endpoints. Así el DNS se resuelve del lado del proxy. Los dos métodos de acceso se comparan en [Autenticación de proxy: user:pass o lista blanca de IP](/es/blog/proxy-authentication-methods), y los protocolos, en [Diferencia entre SOCKS y HTTP](/es/blog/socks-vs-http-proxy).

## ¿Cómo se comprueba la IP de salida del agente?

Compruébala antes de la primera tarea real, sin ningún modelo en el ciclo. Este script usa los mismos `ProxySettings`, abre una página que devuelve la IP del visitante e imprime lo que vio el sitio:

```python
"""Abre una página de eco de IP a través del proxy antes de ejecutar cualquier agente."""
import asyncio
import os

from browser_use import Browser
from browser_use.browser import ProxySettings

async def main():
    browser = Browser(
        headless=True,
        proxy=ProxySettings(
            server=os.environ["PROXY_SERVER"],
            username=os.environ["PROXY_USERNAME"],
            password=os.environ["PROXY_PASSWORD"],
        ),
    )
    await browser.start()
    try:
        page = await browser.new_page("https://httpbin.org/ip")
        await asyncio.sleep(2)  # deja que la página cargue
        print(await page.evaluate("() => document.body.innerText"))
    finally:
        await browser.kill()

asyncio.run(main())
```

Imprime el JSON de httpbin con un campo `origin`. A través de un endpoint de Proxynet, esa es la IP de salida, no la tuya. Ejecútalo dos veces: un usuario rotativo puede mostrar dos direcciones distintas, y uno de sesión fija, la misma dirección las dos veces.

El registro de nuestro proxy también mostró las peticiones propias de Chrome a servicios de Google y la carga del logotipo de Browser Use en la página de inicio en blanco; si pagas el tráfico del proxy por GB, también cuentan.

## Rotativa o fija: ¿qué sesión necesita un agente?

El proxy pertenece al navegador, así que cada paso de una tarea sale por la misma dirección de proxy. Lo que cambia es la IP de salida detrás de esa dirección.

| Tarea | Sesión | Por qué |
|---|---|---|
| Iniciar sesión y luego actuar en varias páginas | Fija, 10-30 minutos | Muchos sitios vinculan la sesión a una IP; una dirección nueva a mitad de la tarea puede obligar a iniciar sesión otra vez |
| Leer una página independiente en cada ejecución | Rotativa | Cada ejecución puede recibir una salida nueva; nada pasa de una a otra |
| Varios agentes en paralelo | Un `Browser` por agente | Cada navegador tiene su propia configuración de proxy y su propia sesión |
| Una dirección que tus propios sistemas tienen en una lista de permitidos | ISP estático | La IP se mantiene igual durante días |

En Proxynet eliges sesión rotativa o fija, país y ciudad en el Generador de endpoints, con una duración de sesión fija de 1 a 60 minutos; el usuario que genera ya incluye esas opciones, así que pégalo tal cual en `PROXY_USERNAME`. Elige una duración un poco mayor que tu tarea más larga. Productos: [Proxies de sesión fija](https://proxynet.io/es/sticky-proxy), [Proxies rotativos](https://proxynet.io/es/rotating-proxy), [Proxies ISP](https://proxynet.io/es/static-isp-residential-proxy) y, cuando una comprobación necesita una conexión doméstica en un país concreto, [Proxies residenciales](https://proxynet.io/es/residential-proxy). Cómo funciona la rotación se explica en [Qué es la rotación de IP y cómo funciona](/es/blog/ip-rotation-explained).

## ¿Cómo se limita adónde puede ir el agente?

`allowed_domains` recibe una lista de patrones: `example.com`, `*.example.com` para subdominios y `http*://example.com` para ambos esquemas. Los comodines en el dominio de nivel superior se rechazan. `prohibited_domains` funciona al revés; si se definen los dos, gana la lista de permitidos.

Permitimos solo nuestra tienda local e hicimos que el modelo de prueba intentara salir por dos vías. Un `navigate` directo a otro host le devolvió esto al modelo, con `about:blank` como página actual:

```text
Navigation failed: Navigation to http://partner.test:28140/ blocked by security policy
```

Un enlace de la tienda que redirigía a ese mismo host también terminó en `about:blank`, y el modelo nunca vio el texto de esa página. Pero el registro del propio sitio de prueba mostró que el navegador había solicitado ambas páginas fuera de la lista antes de que la comprobación las reemplazara, y una imagen del host no permitido se cargó con normalidad dentro de una página permitida. En la 0.13.10, el filtro controla lo que el agente lee y sobre lo que actúa, no lo que envía el navegador.

Para un límite real, restringe el tráfico saliente fuera del agente: un firewall o una lista de permitidos en el lado del proxy, un contenedor o una cuenta de usuario aparte, y ningún acceso a direcciones internas. Playwright MCP tiene la misma salvedad con sus flags de origen, como se explica en [Qué es Playwright MCP](/es/blog/playwright-mcp). El patrón general está en [Acceso web seguro para LLM](/es/blog/llm-safe-web-access).

## ¿Cómo se mantienen las credenciales lejos del modelo?

Nunca escribas una contraseña en la tarea. La tarea va al proveedor del modelo en cada paso y, salvo que la desactives, a la telemetría. Browser Use tiene un mecanismo de marcadores de posición para esto, `sensitive_data`: pasas los valores reales en el código, el modelo solo ve nombres como `x_user` y `x_pass`, y la biblioteca escribe el valor real en el campo después de que el modelo responde.

En nuestra prueba, la acción del modelo fue `<secret>x_pass</secret>`, el registro mostró «Typed <sensitive>» y, cuando la página repitió el nombre de usuario, el modelo recibió `Signed in as <secret>x_user</secret>`. Los valores reales no aparecieron en ninguna entrada del modelo. Tres hábitos completan la protección:

- **Asocia los secretos a un dominio**, para que un marcador solo se rellene en el sitio al que pertenece.
- **Usa `use_vision=False`** en las páginas donde una captura podría mostrar el valor.
- **No le des al agente tu perfil de Chrome de uso diario** (`Browser.from_system_chrome()`) para tareas que leen páginas externas: cualquier sesión iniciada en él queda a su alcance.

## ¿Cómo se añade un paso de aprobación humana?

La inyección de prompts indirecta es un texto de una página que el modelo toma como instrucción. La [entrada LLM01 de OWASP](https://genai.owasp.org/llmrisk/llm01-prompt-injection/) incluye la aprobación humana para acciones de alto riesgo entre las defensas. Browser Use llama a `register_new_step_callback` después de que el modelo elige sus acciones y antes de ejecutarlas, así que el callback puede detener al agente:

```python
"""Agente de Browser Use con lista de permitidos, marcadores para secretos y aprobación humana."""
import asyncio
import os

from dotenv import load_dotenv

load_dotenv()

from browser_use import Agent, Browser, ChatOpenAI
from browser_use.browser import ProxySettings

SITE = "https://shop.example.com"
READ_ONLY = {"navigate", "scroll", "find_text", "extract", "screenshot", "go_back", "wait", "done"}

browser = Browser(
    headless=True,
    proxy=ProxySettings(
        server=os.environ["PROXY_SERVER"],
        username=os.environ["PROXY_USERNAME"],
        password=os.environ["PROXY_PASSWORD"],
    ),
    allowed_domains=["shop.example.com"],
    enable_default_extensions=False,
)

def approve(browser_state, model_output, step):
    """Se ejecuta después de que el modelo elige sus acciones y antes de que se ejecuten."""
    planned = [action.model_dump(exclude_none=True) for action in model_output.action]
    if all(next(iter(a)) in READ_ONLY for a in planned):
        return
    print(f"Step {step} wants to run: {planned}")
    if input("Allow? [y/N] ").strip().lower() != "y":
        agent.stop()

agent = Agent(
    task=f"Inicia sesión en {SITE}/login con el usuario x_user y la contraseña x_pass y luego abre la oferta del socio.",
    llm=ChatOpenAI(model="gpt-4.1-mini"),
    browser=browser,
    sensitive_data={"http*://shop.example.com": {"x_user": os.environ["SHOP_USER"], "x_pass": os.environ["SHOP_PASS"]}},
    use_vision=False,
    register_new_step_callback=approve,
)

async def main():
    history = await agent.run(max_steps=8)
    print("done:  ", history.is_done())
    print("errors:", [e for e in history.errors() if e])

asyncio.run(main())
```

Lo ejecutamos contra nuestra tienda local, con el dominio cambiado. El paso de inicio de sesión pidió confirmación primero; tras «y», el agente escribió ambos valores e hizo clic. Un clic posterior volvió a preguntar y, tras «n», el registro mostró «Agent stopping», el clic no se ejecutó y la llamada `is_done()` devolvió `False`. Cualquier acción fuera del conjunto de solo lectura, incluida la escritura de texto, ahora espera a una persona.

## ¿Browser Use o Playwright MCP?

Ambos permiten que un modelo use un navegador; se diferencian en quién ejecuta el ciclo.

| | Browser Use | Playwright MCP |
|---|---|---|
| Quién ejecuta el ciclo del agente | La biblioteca, en tu código Python | El asistente que ya usas (Claude Code, Cursor) |
| Proxy con contraseña | Campos de `ProxySettings` | `launchOptions.proxy` en un archivo de configuración |
| Límite de dominios | `allowed_domains` | `--allowed-origins` |
| Adecuado para | Agentes dentro de tu propio servicio | Trabajo puntual desde un asistente de programación |

La instalación y los flags de Playwright MCP están en [Qué es Playwright MCP](/es/blog/playwright-mcp).

## Casos de uso

- **Comprobaciones de localización en tu propio sitio:** qué idioma, moneda y aviso de cookies recibe un visitante de un país concreto ([pruebas de localización](/es/localization)).
- **Pruebas exploratorias de tu propia aplicación:** recorrer un flujo de registro o de pago en el entorno de pruebas desde distintas ubicaciones ([pruebas de aplicaciones](/es/app-testing)).
- **Lecturas puntuales de una página con JavaScript:** algunos valores de una página pública que se renderiza en el navegador ([páginas estáticas y dinámicas](/es/blog/static-vs-dynamic-pages)). Para trabajos periódicos, un script normal sale más barato ([Playwright con un proxy](/es/blog/playwright-proxy)).
- **Texto limpio para un modelo en lugar de un navegador:** si el agente solo necesita leer, consulta [Qué es Crawl4AI](/es/blog/crawl4ai-proxy).

Un agente que navega por ti sigue generando tráfico automatizado. Browser Use 0.13.10 no lee robots.txt (no encontramos código para ello en el paquete), así que lee tú mismo el [robots.txt](/es/blog/robots-txt) y las condiciones del sitio, usa una API oficial cuando exista, limítate a unas pocas páginas a ritmo humano y detente cuando un sitio diga que no. Por qué los sitios distinguen a los visitantes automatizados se explica en [¿Por qué los sitios bloquean a los agentes de compra con IA?](/es/blog/ai-shopping-agents-blocked). Las funciones stealth y de CAPTCHA que se anuncian para Browser Use Cloud quedan fuera de esta guía, y no las recomendamos.

## Errores comunes

| Lo que ves | Por qué | Qué hacer |
|---|---|---|
| `net::ERR_NO_SUPPORTED_PROXIES` | Credenciales escritas en `server` | Pásalas a `username` y `password` |
| `net::ERR_TOO_MANY_RETRIES` | Usuario o contraseña del proxy incorrectos; el proxy sigue respondiendo `407` | Vuelve a copiar las credenciales desde el panel |
| `net::ERR_PROXY_CONNECTION_FAILED` | Host o puerto incorrectos, o tráfico saliente bloqueado | Prueba la misma dirección con cURL |
| `ERR_SOCKS_CONNECTION_FAILED` | `socks5://` con contraseña | Usa el endpoint HTTP, o SOCKS5 con lista de IP autorizadas |
| `blocked by security policy` | La URL está fuera de `allowed_domains` | Añade el dominio o déjalo bloqueado |
| El agente vuelve a iniciar sesión a mitad de la tarea | Una salida rotativa cambió la IP durante la tarea | Usa una sesión fija |

Dos hábitos causan problemas sin mostrar ningún error: tratar `allowed_domains` como un firewall y usar una versión sin fijar. La API ha cambiado entre versiones, así que fija la que probaste (`browser-use==0.13.10`) y lee las notas de la versión antes de actualizar.

## Guía de decisión

| Necesidad | Recomendación |
|---|---|
| Una primera ejecución del agente a través de un proxy | `ProxySettings` con el endpoint HTTP, usuario y contraseña; después, el script de eco de IP |
| Una tarea de varios pasos con inicio de sesión | Sesión fija más larga que la tarea |
| Ejecuciones independientes de una sola página | Sesión rotativa |
| Mantener al agente en un solo sitio | `allowed_domains`, más una lista de permitidos para el tráfico saliente fuera del agente |
| Acciones que cambian algo | Un callback de aprobación que pueda llamar a `agent.stop()` |

## Preguntas frecuentes

### ¿Browser Use es gratis?

La biblioteca es gratuita con licencia MIT. Pagas las llamadas al modelo, al menos una por paso, y el tráfico del proxy. Browser Use Cloud y sus modelos alojados se facturan aparte.

### ¿Browser Use sigue usando Playwright?

No para manejar el navegador. La versión 0.13.10 controla Chromium mediante el Chrome DevTools Protocol; el comando de instalación usa el descargador de Playwright para obtener Chromium, y el estado de sesión guardado usa el formato de archivo de Playwright.

### ¿Puedo usar un modelo local en lugar de una API?

La página de modelos compatibles muestra `ChatOllama(model="llama3.1:8b")` para un servidor local de Ollama. No probamos ningún modelo local.

### ¿Pueden dos agentes usar países distintos al mismo tiempo?

Sí, con dos objetos `Browser`, cada uno con sus propios `ProxySettings`. Un navegador tiene un solo proxy para todas sus pestañas.

### ¿Browser Use respeta robots.txt?

No por sí solo; la versión 0.13.10 no comprueba robots.txt. Lee el archivo antes de darle un sitio al agente.

### ¿Un proxy evita que los sitios bloqueen a mi agente?

No. Un proxy cambia la dirección desde la que sale una petición; el comportamiento del navegador y el ritmo siguen igual. Un ritmo lento, las páginas permitidas y la API oficial son el camino duradero.

## En resumen

Browser Use le da a un modelo de lenguaje un navegador Chromium real y ejecuta el ciclo del agente en tu propio código Python. Configura el proxy en el navegador con `ProxySettings` y los campos `username` y `password` por separado; tanto las credenciales en la URL como SOCKS5 con contraseña fallan en Chromium. Comprueba la IP de salida antes de la primera tarea, usa una sesión fija para todo lo que tenga inicio de sesión y trata `allowed_domains` como un filtro para el agente, no como un límite de red. Guarda los secretos en `sensitive_data`, desactiva la telemetría y haz que una persona apruebe las acciones que cambian algo. Tienes salidas adecuadas para tu agente en [nuestros servicios de proxy](/es/proxy).
