Using residential proxies with browser-use

Published: 23 July 2026 · 6 min read

TL;DR: browser-use lets an LLM drive a real Chromium browser to complete tasks, so its fingerprint already looks human - but it still exits from your server's datacenter IP, which anti-bot systems flag on sight. Pass a residential proxy through the Playwright proxy config: {"server": "http://gw.roamproxy.com:41080", "username": ..., "password": ...}. When you run many agents at once, give each one its own sticky residential IP so they are not linked together.

The agent has a real browser but a fake-looking network

browser-use hands control of a real Chromium browser to an LLM, which clicks, types and reads pages to complete a task you describe in plain language. Because it is a genuine browser, the fingerprint - the TLS handshake, the JavaScript environment, the rendering - is real. That is a big head start over a raw HTTP scraper.

But the browser runs somewhere, and that somewhere is usually a cloud VM on a datacenter IP. Anti-bot systems score the exit IP's ASN before they evaluate anything the browser does, so a perfect browser coming out of an AWS or Hetzner range is flagged anyway. The one layer browser-use cannot fix for you is the network it exits from. That is the proxy's job.

Install

pip install browser-use
playwright install chromium

Route the agent through a residential proxy

browser-use passes proxy settings straight through to Playwright, so the value is Playwright's proxy dict: a bare server URL plus separate username and password keys. Do not embed credentials in the server URL - Playwright reads them from the separate fields.

from browser_use import Agent, Browser, BrowserConfig
from langchain_openai import ChatOpenAI

browser = Browser(
    config=BrowserConfig(
        proxy={
            "server": "http://gw.roamproxy.com:41080",
            "username": "YOUR_USERNAME",
            "password": "YOUR_PASSWORD",
        }
    )
)

agent = Agent(
    task="Open example.com and summarize what the company does",
    llm=ChatOpenAI(model="gpt-4o"),
    browser=browser,
)

await agent.run()

Now the agent's browser exits from a real home-broadband IP. The LLM still decides what to do; the proxy decides how the traffic looks on the wire, and the two are configured independently.

The wrapper class name moves between browser-use versions (BrowserConfig, BrowserProfile, BrowserSession). The part that never changes is the proxy dict shape shown above - server / username / password. If a new version renames the wrapper, keep the dict and check the current docs for where it now lives.

One IP per agent when you run many

The interesting use of browser-use is running a fleet of agents - one per account, one per task, one per market. If they all share a single exit IP, the sites they visit can link them, and you have rebuilt the exact footprint you were trying to avoid. Give each agent its own sticky residential session so its exit IP is stable and distinct for the life of the task.

The session is selected in the proxy username; see what are rotating proxies for how the session string controls a rotating versus sticky IP. Assign a different sticky session per agent and no two agents will ever share an exit.

Verify the exit before you trust it

Point the agent's first task at an IP-check page and read back the result:

agent = Agent(
    task="Go to https://ip.sb and tell me the IP address and country shown",
    llm=ChatOpenAI(model="gpt-4o"),
    browser=browser,
)
print(await agent.run())

It should report the Roam residential exit IP and the country you targeted, not your server's real address. If it reports your real IP, the proxy config did not reach Playwright - re-check the dict shape and which object you attached it to.

When the browser alone is not enough

browser-use handles the fingerprint by using a real browser, and a residential proxy handles the IP. For scripted (non-agent) scraping where you are not using a real browser - plain Python HTTP requests - you lose the fingerprint advantage and need to restore it another way; see bypassing TLS/JA3 fingerprinting with curl_cffi. For the wider set of reasons requests get blocked, see how to avoid getting blocked while web scraping.

FAQ

Doesn't browser-use already look human - why add a proxy?

Its browser looks human because it drives a real Chromium instance, so the fingerprint is genuine. But the network is not: the request still exits from wherever you run the agent, which is usually a cloud server on a datacenter ASN that anti-bot systems flag before they look at anything else. The proxy fixes the layer the browser cannot - the exit IP. Real fingerprint plus real residential IP is what actually passes.

I'm running 20 agents in parallel - do they need different IPs?

Yes, if the sites should not connect them. Twenty agents behind one IP look like twenty sessions from one machine, which is exactly the pattern that links accounts or triggers rate limits. Give each agent its own sticky residential session so each has a stable, distinct exit IP for the life of its task. Roam bills by the gigabyte, not per IP or per agent, so scaling out the agent count does not multiply a subscription.

Does the proxy work the same on any LLM backend?

Yes. The proxy sits at the browser layer, so it is completely independent of which model drives the agent - OpenAI, Anthropic, a local model, whatever you pass as the llm. The LLM decides what to do; the browser (and its proxy) decides how the traffic looks on the wire. You configure them separately.

My agent's proxy config is ignored - what's wrong?

The most common cause is passing the proxy to the wrong object. browser-use's wrapper API has changed across versions (BrowserConfig, BrowserProfile, BrowserSession), but the value you pass is always Playwright's proxy dict - server, username, password as separate keys, with the server as a bare http://host:port and no credentials embedded in the URL. If you put user:pass@host in the server string, Playwright ignores the auth. Check the current browser-use docs for the exact wrapper, but keep the dict shape shown here.

browser-use gives your agent a real browser; Roam gives it a real network identity. Rotating residential IPs at $2/GB and static residential at $4/IP per month, over HTTP and SOCKS5, drop straight into the Playwright proxy config below. Create an account and get 300MB of free trial traffic to run your first agent through a residential exit.