Browser-use Tutorial: Build an AI Agent That Drives a Real Browser
This Browser-use tutorial shows you how to point an AI agent at a live browser and have it get real work done. Browser-use is the leading open-source library for giving LLM agents browser control – MIT-licensed, with over 110k GitHub stars. By the end, you'll have an agent scraping product data, working through multi-step flows, and handling failures.
Dominykas Niaura
Last updated: Sep 01, 2026
10 min read

TL;DR
- Browser-use lets an LLM control a real Chrome browser directly through the Chrome DevTools Protocol
- To get started, you need Python 3.11 or newer, a Chromium-based browser, and a supported LLM API key
- It can navigate dynamic pages and complete multi-step workflows without relying on fixed CSS selectors for every interaction
- At scale, route every session through rotating residential proxies for a fresh IP and location-accurate results
What is Browser-use, and how do AI browser agents work?
Browser-use is an open-source Python library that lets a large language model (LLM) operate a real Chromium browser. During a run, the agent reads the current page, chooses an action, checks the result, and repeats the loop until it finishes the task or reaches a limit.
Traditional browser automation works from instructions defined in advance. A Playwright or Selenium script usually locates elements with CSS or XPath selectors, clicks them, waits for a response, and extracts text.
This approach is fast and predictable when the page structure is stable, until there's a mere class rename and the whole flow breaks.
In contrast to the traditional automation workflow, an AI browser agent works from meaning and context. It interprets the page using visible text, labels, DOM context, and optional vision, which makes it useful on JavaScript-heavy pages and multi-step web flows where maintaining selectors becomes time-consuming.
Earlier Browser-use versions routed browser actions through Playwright. The current architecture talks to Chromium directly over CDP, the low-level protocol Chrome exposes for inspection and control.
Here's a quick comparison of the 2 approaches:
Selector-based script (Playwright / Selenium)
AI browser agent (Browser-use)
How it finds elements
CSS selectors or XPath you write by hand
The LLM reads the rendered page and picks the element
What happens on a layout change
Breaks until you rewrite the selector
Usually adapts, because nothing is hard-coded
Setup effort
High (1 script per target)
Low (natural language task description)
Cost per run
Compute only, fractions of a cent
Compute plus LLM tokens for every step
Best suited to
Stable, repetitive, high-volume workflows
Dynamic pages, multi-step flows, and targets that change often
For a closer look at the selector-based options, read Playwright vs. Selenium in 2026.
Browser-use supports more than 15 LLM providers, including Anthropic, OpenAI, Gemini, and OpenRouter. Each provider uses its own Chat integration and API key, so check the current supported models list before choosing a model.
ChatBrowserUse is the project's hosted model interface and uses a Browser Use API key. Provider-specific integrations such as ChatAnthropic, ChatOpenAI, and ChatGoogle let you connect your own provider account instead. The AI agent enablement page explains the web data infrastructure that supports these agent workflows.
Prerequisites and project setup
Before writing any agent logic, you need a working environment with the right Python version, dependencies, and project structure in place.
Environment setup
Browser-use requires Python 3.11 or higher. If you're on an older version, we recommend you upgrade before continuing. Once you're on 3.11+, create a virtual environment to keep your dependencies isolated:
Then install the core dependencies:
If you use uv, which is what the official docs now lead with, the same install is:
Browser-use drives a real Chrome installation. If you don't already have one on the machine, fetch a Chromium binary:
The older playwright install chromium shortcut still works if you already have Playwright in the environment – it's only a way to download a browser binary, not a dependency of Browser-use itself.
LLM API key
Browser-use needs an LLM to drive the agent's decisions. The examples in this guide use Anthropic Claude. Head to platform.claude.com, generate an API key, and store it in a .env file at the root of your project:
Boilerplate script structure
Every Browser-use agent follows the same minimal pattern. Here's the starting point:
The Agent class takes a task string and an LLM instance. Meanwhile, asyncio.run() handles the async execution. That's the entire skeleton – everything else builds on top of it.
Browser customization
Browser settings live on BrowserProfile, and the running browser is a BrowserSession (Browser is an alias for the same class). The most useful options during development are pointing the agent at your own Chrome installation, toggling headless mode, and setting the viewport:
Using your local Chrome instance is worth doing early on – it already has saved sessions and cookies, which makes testing against login-gated pages much smoother. Rather than hardcoding an executable path, let Browser-use find Chrome for you:
Run headless in production once your tasks are reliable.
Suggested project structure
Keeping configuration and task logic separate from the start saves time later.
If you hit setup issues along the way, the Python errors and exceptions guide covers the most common failure patterns, the headless browser explainer is useful background if you're new to running Chrome without a UI, and the guide to running Python in the terminal is a useful reference if you're newer to the command line.
Setting up and using the Browser-use web UI
Browser-use ships with an official web UI – a Gradio-based interface that lets you run agent tasks without writing any Python. It's useful for rapid prompt prototyping and accessible to non-developers who want to test automation tasks without touching code.
There's a second no-Python route worth knowing about: the Browser-use CLI. Install it with uv tool install browser-use, run browser-use skill install, and the skill registers with Claude Code, Codex, and other coding agents, so your coding agent drives the browser for you through the CLI. It connects to your local Chrome over CDP or to a cloud browser when you're running headless. If you arrived here from an AI-agent search rather than a scraping one, this is probably the path you want.
Installation
Start by cloning the web UI repository:
Install the requirements:
Then copy the example environment file and add your API key:
Open .env and add your ANTHROPIC_API_KEY.
Configuration options
The UI exposes several settings directly in the interface.
- Maximum steps – the number of actions the agent will attempt before stopping. Start high during testing, tighten once your prompt is reliable.
- LLM model and temperature – select your model and adjust how deterministic the agent's decisions are. Lower temperature produces more consistent behavior.
- Browser visibility – toggle between headed and headless mode directly from the UI.
- Session recording – the agent saves a GIF of every session to agent_history.gif in the project root. This is the fastest way to diagnose unexpected behavior.
Running a task
Start the server with the following command:
Navigate to http://127.0.0.1:7788 in your browser, and you'll see this:

Open the Run Agent tab, enter your prompt, and click Submit Task.

To see it in action, try a simple public example: ask the agent to find the current price of a specific product on books.toscrape.com and return a formatted summary. It requires no login, produces a clear output, and gives you an immediate sense of how the agent interprets and executes a natural language instruction.
Once the task completes, review the output in the UI and open agent_history.gif to watch a replay of every action the agent took.

Running a task through the UI quickly reveals how much prompt quality matters. Let's see how to write prompts that produce reliable, consistent output.
Writing effective prompts for AI browser agents
Prompt quality has a bigger impact on Browser-use reliability than most developers expect. A traditional script is explicit by design – every step is hard-coded. A Browser-use agent infers what you mean from natural language, which means a vague instruction produces inconsistent behavior. The agent's decisions are only as good as the information it's given.
Structural principles
How you structure a prompt determines how reliably the agent executes, because vague instructions get interpreted while precise ones get followed. The following principles apply whether you're scraping a single page or chaining a multi-step workflow.
- Start with a named objective. Before listing steps, state what the task is meant to accomplish. This gives the agent a goal to orient toward if it gets confused mid-task.
- Break complex tasks into numbered steps. Each step should correspond to 1 discrete browser action: navigate, find an element, click, extract, verify. Combining multiple actions into a single step increases the chance of the agent skipping one.
- Add verification checkpoints. After critical actions, tell the agent to confirm the result before continuing. "Verify that at least 1 product listing is visible before extracting data" prevents the agent from running extraction logic against an empty page.
- Define failure behavior explicitly. Left without instructions, the agent will improvise when something goes wrong. Specify what it should do instead: log an error and stop, retry up to N times, or skip the step and continue.
- Be precise about element references. "The search box" is ambiguous. "The search input in the top navigation bar with a magnifying glass icon" isn't. The more specific your reference, the less room there's for misinterpretation.
The principles above are easier to apply with a consistent structure to build from. Not every task needs every field, but starting with all of them and removing what's unnecessary is faster than debugging a prompt that was missing something from the start.
The template below covers the 5 components a reliable Browser-use prompt needs – objective, context, steps, error handling, and output format:
Before and after
Let's look at some practical examples. Here's a vague prompt:
This gives the agent no guidance on how many books to extract, what fields to include, how to handle pagination, or what to do if the page structure changes. The output will vary between runs.
Now here's what a revised prompt would look like:
The difference isn't just length. The objective gives the agent something to recover toward if it loses its place. The numbered steps eliminate ambiguity about sequencing. The null instruction means a missing field produces clean data rather than a crashed run. And the error handling clauses mean the agent stops predictably when something goes wrong, rather than improvising in ways you can't anticipate. Every addition removes a decision the agent would otherwise make on its own – and those improvised decisions are where inconsistent output comes from.
For readers interested in LLM-assisted scraping more broadly, the guides to Claude web scraping or ChatGPT web scraping cover complementary approaches, and the LangChain end-to-end workflows article goes deeper on building LangChain-based automation pipelines.
Practical use cases: Step-by-step examples
With the prompt principles in place, the examples below apply them to 3 distinct tasks – product data extraction, multi-step web app interaction, and stock monitoring. Each includes a full prompt and the code to run it.
Scraping product listings and saving to JSON
The target here is books.toscrape.com, a public sandbox e-commerce site built for scraping practice. The task is to extract title, price, star rating, and availability for the first 10 results, then write the output to a local JSON file:
books.json holds all 10 records. Here are the first 3 from an actual run:
For more on handling and storing scraped output, the guide to saving scraped data covers the main storage patterns in depth, and How to scrape JSON data in Python goes deeper on parsing the output.
Single-site extraction is a good starting point, but Browser-use's real advantage shows up when a task spans multiple sites and requires the agent to carry state between them.
Summarizing content and creating a task card
Task: Visit a public GitHub issues list, summarize the 3 most recent open issues, then log into a project management tool and create a card with the summary.
This is where Browser-use is ahead of traditional scraping most clearly. A CSS-selector script would require separate, site-specific logic for each site – and would break independently whenever either site updates its layout. A Browser-use agent handles both in a single task description:
Note: Store credentials in your .env file and load them with python-dotenv. Never hardcode login details in the task string or script.
The previous 2 use cases run once and return a result. The monitoring pattern below is designed to run repeatedly, checking for a condition and acting on it when it's met.
Stock monitoring and alerting
Task: Check a product page for stock status. If the item is in stock, write a formatted alert to a local file.
Run this on a schedule using cron or a task scheduler to build a basic restock monitor. The same pattern applies to price tracking – adjust the extracted field and alert condition accordingly. For sites with aggressive bot detection, routing the agent through a residential proxy is the most reliable way to keep sessions running cleanly – more on that in the next section.
For combining Browser-use with traditional extraction logic, our AI web scraping with Python guide covers the overlap in detail.
Managing errors and agent failures
The use cases above assume clean runs. In practice, pages change, networks drop, and agents occasionally misread what's in front of them. Building in error handling from the start is what separates a demo from something you can actually run on a schedule.
Browser-use agents fail for 4 predictable reasons, and each one has a different fix:
Failure mode
What you see in the log
Usual cause
What to change
LLM misreads an element reference
The agent clicks or types into the wrong element, then continues as if it worked
An ambiguous element description in the prompt
Describe the element by its position and visible label, not its role alone
Page shifts between perception and action
"Element not found" or a click that lands on nothing
Lazy-loaded content or a banner appearing after the state capture
Add a verification step before the action, and raise wait_for_network_idle_page_load_time
Network timeout
The run stalls, then the session ends mid-task
A slow target, or an IP that's being throttled
Set a page-load timeout on the profile, add a retry clause, and route through a proxy
Max steps exhausted
The run stops with the task unfinished and no error
max_steps set too low, or the agent looping on 1 screen
Raise max_steps, then split the task into smaller prompts
Model can't hold the output format
Every step fails validation with a pydantic error, and the agent gives up before acting
A smaller or non-frontier model that can't reliably fill Browser-use's response schema
Try a stronger model first; if you're on an OpenAI-compatible endpoint, ChatOpenAI(add_schema_to_system_prompt=True, dont_force_structured_output=True) asks for plain JSON instead of a forced tool call
Prompt-level error handling
Always include explicit failure instructions in your prompt. Left without them, the agent will improvise – and the improvised behavior is rarely what you want.
- Tell the agent what to do when an element isn't found: "if the element isn't found, log an error and stop execution."
- Add retry instructions for expected transient failures: "if the page fails to load, retry up to 3 times before stopping."
- Verify critical actions before moving on: "confirm that the form was submitted successfully before proceeding to the next step."
Code-level error handling
Wrap agent.run() in a try/except block so unexpected exceptions don't crash your process silently. Note that max_steps is an argument to run(), not to the Agent constructor:
The max_steps parameter caps how many actions the agent can take before stopping. Set it generously during development, then tighten it once the task is reliable. Without it, a confused agent can run for far longer than you intended.
To prevent hung sessions, set the page-load timing on the BrowserProfile.
Browser-use records the agent's full action history internally. Logging it after a failure gives you a step-by-step trace of what the agent did before things went wrong:
Practical debugging tips
Run new tasks in headed mode first. Watching the agent navigate in a visible browser window makes it immediately obvious when it clicks the wrong element or gets stuck on a banner. It's the fastest debugging tool available.
Start with a high max_steps value – 50 or more – during development. Once the task completes reliably, reduce it to something tighter. Test prompts incrementally too: verify each step works before adding the next one.
The Python errors and exceptions guide covers exception handling patterns in more depth, and the Python requests retry guide is a useful background for the retry logic pattern.
Using proxies with Browser-use for scalable automation
Solid error handling keeps your agent running cleanly on a single site. Proxies are what keep it running cleanly at scale – across many sessions, against sites that actively look for bot traffic, or when you need results from specific geographic locations.
Running Browser-use locally against a single target site works well for one-off tasks. At scale – multiple sessions, high-frequency monitoring, or sites with active bot detection – running from a single IP will eventually trigger rate limits or blocks. Residential proxies solve this by routing each session through a different IP associated with a real consumer device, which is far less likely to be flagged than a datacenter IP.
Geo-targeted proxies add another dimension: they let you pull region-specific prices, availability, and content that wouldn't be visible from a single fixed location. For retail, travel, and SERP monitoring use cases, this is often essential.
Configuring Decodo residential proxies in Browser-use
Residential proxies work because each IP is tied to a real consumer device – the kind of traffic that looks identical to an ordinary user visiting a site. Datacenter IPs, by contrast, are easy to fingerprint and block in bulk. For Browser-use specifically, where sessions are already designed to mimic human behavior, pairing the agent with Decodo residential proxies closes the last gap (the IP layer) that bot detection systems look for.
Decodo's network covers 195+ countries with ethically-sourced IPs, which matters when your use case requires geo-specific data. Retail prices, travel availability, and SERP results all vary by location – a single fixed IP only ever shows you one version of that data. With Decodo, you target the exact location you need and get the results that a real user in that region would see.
Here's how easy it is to set up Decodo residential proxies:
- Register or log in to the Decodo dashboard.
- Navigate to find residential proxies and choose a subscription that suits your needs or start with a 3-day free trial.
- Go to Proxy setup.
- Select a location or choose Random.
- Set the rotating session type and choose a protocol (HTTP(S) or SOCKS5).
- Choose the authentication type.
- Copy the generated endpoint and credentials, or download them.
Get residential proxies for scraping text
Unlock superior scraping performance with a free 3-day trial of Decodo's residential proxy network.
The configuration passes proxy settings through a BrowserProfile and BrowserSession. Store credentials in .env and load them at runtime:
Load these variables into Python and pass them into the ProxySettings, which will then be attached to your browser profile:
Rotating proxies for multi-session tasks
For tasks that run across multiple regions or require a fresh IP per session, Decodo's rotating residential proxies handle IP rotation automatically. Each new session gets a different IP without any manual pool management on your end – which matters at scale, where manually cycling IPs becomes a maintenance burden faster than most teams expect.
Create a new BrowserSession per run with the proxy settings you need:
Add a randomized delay between sessions to avoid predictable timing patterns. Even behind residential IPs, machine-speed intervals are a detectable signal:
Full project
Want to skip setup and run everything right away? Download the complete project with all files included – main.py, config.py, prompts.py, and the .env template – ready to run locally.
After downloading, just install the dependencies, add your API key and proxy credentials to the .env file, and run the script.
Final thoughts
Browser-use is a practical option for automating dynamic pages and multi-step workflows without relying on fixed selectors. However, production use still requires clear prompts, reasonable run limits, error handling, and human review for critical tasks.
Browser agents should become more reliable as models are better trained. For now, test each workflow carefully and use dependable proxy infrastructure when scaling.
Try Decodo’s residential proxies free for 3 days with full access and no restrictions.
Access residential proxies now
Try residential proxies free for 3 days – full access, zero restrictions.
About the author

Dominykas Niaura
Technical Copywriter
Dominykas brings a unique blend of philosophical insight and technical expertise to his writing. Starting his career as a film critic and music industry copywriter, he's now an expert in making complex proxy and web scraping concepts accessible to everyone.
Connect with Dominykas via LinkedIn
All information on Decodo Blog is provided on an as is basis and for informational purposes only. We make no representation and disclaim all liability with respect to your use of any information contained on Decodo Blog or any third-party websites that may belinked therein.


