Back to blog

Browser-use Tutorial: Build an AI Agent That Drives a Real Browser

Share article:

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.

Browser window titled 'X Browser' listing profiles with 'Start session' buttons on dark dotted background

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:

python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

Then install the core dependencies:

pip install browser-use anthropic python-dotenv

If you use uv, which is what the official docs now lead with, the same install is:

uv add browser-use

Browser-use drives a real Chrome installation. If you don't already have one on the machine, fetch a Chromium binary:

uvx browser-use install

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:

ANTHROPIC_API_KEY=your_anthropic_api_key

Boilerplate script structure

Every Browser-use agent follows the same minimal pattern. Here's the starting point:

import asyncio
from dotenv import load_dotenv
from browser_use import Agent, ChatAnthropic
load_dotenv()
async def main():
    agent = Agent(
        task="Your task here",
        llm=ChatAnthropic(model="claude-sonnet-4-6"),
    )
    await agent.run()
asyncio.run(main())

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:

from browser_use import Agent, BrowserProfile, BrowserSession, ChatAnthropic
profile = BrowserProfile(
    headless=False,  # Set to True in production
    window_size={"width": 1440, "height": 900},
)
browser_session = BrowserSession(browser_profile=profile)

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:

from browser_use import Browser
browser_session = Browser.from_system_chrome(headless=False)

Run headless in production once your tasks are reliable.

Suggested project structure

Keeping configuration and task logic separate from the start saves time later.

project/
├── main.py      # Entry point and agent execution
├── prompts.py   # Task strings, kept separate from logic
├── config.py    # Browser and agent configuration
└── .env         # Proxy credentials and API key

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:

git clone https://github.com/browser-use/web-ui.git
cd web-ui

Install the requirements:

pip install -r requirements.txt

Then copy the example environment file and add your API key:

cp .env.example .env

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:

python webui.py --ip 127.0.0.1 --port 7788

Navigate to http://127.0.0.1:7788 in your browser, and you'll see this:

Browser Use WebUI showing 'Override system prompt', 'Extend system prompt', and 'Drop File Here' upload in dark web UI with tabs

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

The Browser-use UI showing the Run Agent tab with a button to 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.

Objective: Extract pricing data for the first 10 books listed on books.toscrape.com — white instruction text centered on black background

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:

Objective: [What this task is meant to accomplish]
Context: [Any relevant information the agent needs before starting]
Steps:
1. [Navigate to URL]
2. [Find element -- describe it precisely]
3. [Perform action]
4. [Verify result]
5. [Extract data / perform next action]
Error handling:- If [expected failure], [specific instruction]- If the page fails to load, retry up to 3 times before stopping
Output format: [Describe exactly how the result should be structured]

Before and after

Let's look at some practical examples. Here's a vague prompt:

Go to books.toscrape.com and get the book prices.

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:

Objective: Extract pricing data for the first 10 books listed on books.toscrape.com.
Steps:
1. Navigate to http://books.toscrape.com.
2. Verify that at least 1 book listing is visible before proceeding.
3. For each of the first 10 books, extract: title, price, star rating, and availability status.
4. If a field is missing for a book, record it as null rather than skipping the book.
5. Return the data as a JSON array.
Error handling:
- If the page fails to load, retry up to 3 times before stopping.
- If fewer than 10 books are visible, extract all available books and note the count in the output.

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:

import asyncio
import json
from dotenv import load_dotenv
from browser_use import Agent, ChatAnthropic
load_dotenv()
TASK = """
Objective: Extract data for the first 10 books on books.toscrape.com.
Steps:
1. Navigate to http://books.toscrape.com.
2. Verify that at least 1 book listing is visible before proceeding.
3. For each of the first 10 books, extract: title, price, star rating, and availability status.
4. If a field is missing for a book, record it as null rather than skipping the book.
5. Return the data as a JSON array, and nothing else.
Error handling:
- If the page fails to load, retry up to 3 times before stopping.
- If fewer than 10 books are visible, extract all available books and note the count in the output.
""".strip()
async def main():
    agent = Agent(
        task=TASK,
        llm=ChatAnthropic(model="claude-sonnet-4-6"),
    )
    history = await agent.run(max_steps=30)
    result = history.final_result()
    if not result:
        print("Agent finished without returning data.")
        return
    with open("books.json", "w", encoding="utf-8") as f:
        json.dump(json.loads(result), f, indent=2, ensure_ascii=False)
    print("Saved results to books.json")
asyncio.run(main())

books.json holds all 10 records. Here are the first 3 from an actual run:

[
  {
    "title": "A Light in the Attic",
    "price": "£51.77",
    "star_rating": "Three",
    "availability": "In stock"
  },
  {
    "title": "Tipping the Velvet",
    "price": "£53.74",
    "star_rating": "One",
    "availability": "In stock"
  },
  {
    "title": "Soumission",
    "price": "£50.10",
    "star_rating": "One",
    "availability": "In stock"
  }
]

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:

TASK = """
Objective: Summarize the 3 most recent open issues from a GitHub repo and create a task card.
Steps:
1. Navigate to https://github.com/browser-use/browser-use/issues.
2. Verify that issue listings are visible.
3. Extract the title and URL of the 3 most recently opened issues.
4. Write a brief summary for each (1-2 sentences).
5. Navigate to [your project management tool URL].
6. Log in using the credentials from environment variables TOOL_USERNAME and TOOL_PASSWORD.
7. Create a new card titled "GitHub Issues Summary - [today's date]" with the 3 summaries as the card body.
8. Confirm the card was created successfully before stopping.
Error handling:
- If login fails, stop execution and log the error.
- If fewer than 3 issues are visible, summarize all available issues.
""".strip()

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.

TASK = """
Objective: Check stock status for a product and trigger an alert if it's available.
Steps:
1. Navigate to http://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html.
2. Locate the availability status on the product page.
3. If the status reads "In stock", write the following to a file named alert.txt:
  ALERT: [Product title] is in stock. Price: [price]. Checked at: [current time].
4. If the status reads anything other than "In stock", write: "Out of stock. No action taken."
Error handling:
- If the page fails to load, retry up to 3 times before stopping.
""".strip()

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:

async def main():
    agent = Agent(
        task=TASK,
        llm=ChatAnthropic(model="claude-sonnet-5"),
    )
    try:
        result = await agent.run(max_steps=25)
        print(result)
    except Exception as e:
        print(f"Agent failed: {e}")

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.

from browser_use import Agent, BrowserProfile, BrowserSession, ChatAnthropic
profile = BrowserProfile(
    headless=True,
    wait_for_network_idle_page_load_time=30.0,
)
browser_session = BrowserSession(browser_profile=profile)
agent = Agent(
    task=TASK,
    llm=ChatAnthropic(model="claude-sonnet-4-6"),
    browser_session=browser_session,
)

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:

history = await agent.run(max_steps=25)
print(history)

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:

  1. Register or log in to the Decodo dashboard.
  2. Navigate to find residential proxies and choose a subscription that suits your needs or start with a 3-day free trial.
  3. Go to Proxy setup.
  4. Select a location or choose Random.
  5. Set the rotating session type and choose a protocol (HTTP(S) or SOCKS5).
  6. Choose the authentication type.
  7. 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:

# .env
PROXY_HOST=gate.decodo.com
PROXY_PORT=10001
PROXY_USERNAME=your_username
PROXY_PASSWORD=your_password

Load these variables into Python and pass them into the ProxySettings, which will then be attached to your browser profile:

#proxytest.py
import os
from dotenv import load_dotenv
from browser_use import BrowserProfile
from browser_use.browser import BrowserSession
from browser_use.browser.profile import ProxySettings
load_dotenv()
proxy = ProxySettings(
server=f"http://{os.getenv('PROXY_HOST')}:{os.getenv('PROXY_PORT')}",
username=os.getenv("PROXY_USERNAME"),
password=os.getenv("PROXY_PASSWORD"),
)
profile = BrowserProfile(
headless=True,
proxy=proxy,
)
browser_session = BrowserSession(browser_profile=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:

import asyncio
from browser_use import Agent, BrowserProfile
from browser_use.browser import BrowserSession
from browser_use.browser.profile import ProxySettings
from browser_use.llm import ChatAnthropic
async def run_with_proxy(proxy_config: ProxySettings, task: str):
profile = BrowserProfile(headless=True, proxy=proxy_config)
browser_session = BrowserSession(browser_profile=profile)
agent = Agent(
task=task,
llm=ChatAnthropic(model="claude-sonnet-4-6"),
browser_session=browser_session,
)
return await agent.run(max_steps=30)

Add a randomized delay between sessions to avoid predictable timing patterns. Even behind residential IPs, machine-speed intervals are a detectable signal:

import random
import asyncio
await asyncio.sleep(random.uniform(2, 6))

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.

Share article:

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.

Frequently asked questions

What is Browser-use?

Browser-use is a Python library that connects an LLM to a real Chrome browser over the Chrome DevTools Protocol, enabling AI agents to navigate pages, interact with forms, and extract structured data. Unlike rule-based automation scripts, Browser-use agents adapt to layout changes and handle dynamic content without hard-coded selectors.

Which LLMs does Browser-use support?

Browser-use natively supports 15+ providers, including Anthropic, OpenAI, Google, and Groq, plus any model behind an OpenAI-compatible endpoint and local models through Ollama. It ships its own chat classes rather than depending on LangChain, so switching models is as easy as swapping one class.

How do I avoid getting blocked when using Browser-use?

Routing Browser-use sessions through residential proxies is the most reliable approach. Residential IPs are associated with real consumer devices and are far less likely to trigger bot detection than datacenter IPs. Decodo's rotating residential proxies handle IP rotation automatically, so each new session gets a fresh IP without manual management.

Is Browser-use free?

Yes. Browser-use is MIT-licensed and free to run, including for commercial projects. The only running cost is whichever LLM drives the agent, billed by that provider per token, plus proxy traffic if you're routing sessions through residential IPs.

Does Browser-use still use Playwright?

No. Browser-use moved from Playwright to the Chrome DevTools Protocol in August 2025, and now talks to Chrome directly. Playwright still comes up as a convenient way to download a Chromium binary, but it isn't a dependency, and it no longer handles the browser mechanics.

Playwright logo and title 'Playwright' showing subtitle 'Web Scraping Tutorial' on a dark dotted background

Playwright Web Scraping: A Practical Tutorial

Web scraping can feel like directing a play without a script – unpredictable and chaotic. That’s where Playwright steps in: a powerful, headless browser automation tool that makes scraping modern, dynamic websites smoother than ever. In this practical tutorial, you’ll learn how to use Playwright to reliably extract data from any web page.

Authentication method and Endpoint generator panels showing code snippet and auth options in a dark dotted gradient UI mockup

Playwright vs. Selenium in 2026: Which Browser Automation Tool Should You Choose?

As websites become more dynamic and better at detecting automated traffic, choosing the right automation tool has become more challenging. At the same time, performance, reliability, and anti-detection capabilities matter more than ever. Two tools dominate the space: Selenium, a mature and widely adopted standard, and Playwright, a newer framework built for modern web apps. This guide compares them through practical use cases like web scraping and dynamic content extraction to help you decide which fits your needs best.

Scraping UI showing "Amazon search" query "laptop", "Start scraping" button, and "Response" JSON panel with results

Complete Guide for Building n8n Web Scraping Automations

If you're tired of duct-taping complicated scripts just to grab web data, this n8n web scraping tutorial is for you. You'll see how to use n8n for web scraping, why it beats DIY scrapers, and what you need to get started. Perfect for developers and coding beginners looking to automate data extraction without the headaches.

© 2018-2026 decodo.com (formerly smartproxy.com). All Rights Reserved