TL;DR:
- browser-use is an open-source Python library that gives AI agents real browser control through Playwright — agents can navigate, click, fill forms, extract content, and handle multi-tab workflows
- It works with any LLM that supports tool calling: Claude, GPT-4o, Gemini, Llama, and local models via Ollama
- For text-heavy tasks it extracts structured DOM content rather than screenshotting, which is faster and significantly cheaper
- It handles the messy parts of browser automation: cookie banners, dynamic content, authentication flows, and multi-step processes
AI agents that can operate a web browser have been a consistent topic in 2025 and 2026, but the implementations have varied enormously in how much they ask the developer to wire up manually. browser-use sits at one end of that spectrum: it does the heavy lifting so you can describe what you want rather than writing step-by-step Playwright scripts.
The library is open source (MIT), actively maintained, and has accumulated substantial usage across research and production agent pipelines. It’s worth understanding properly — not just what it does, but where it fits relative to alternatives and where its limits are.
What browser-use Actually Does
At its core, browser-use is a bridge between an LLM and a Playwright browser session. You give the agent a task in plain language, and the library handles:
- Extracting a representation of the current page — either as structured DOM content (faster) or as a screenshot with vision (for complex layouts)
- Presenting that to the LLM as context along with available browser actions
- Executing the LLM’s chosen action — click, type, navigate, scroll, extract, open new tab
- Looping until the task is done or the agent decides it’s stuck
This is different from a traditional Playwright script where you write exact selectors and sequences. With browser-use, the LLM reasons about what to do next based on what it sees, which makes it far more robust when pages change or when the task has branches the developer didn’t anticipate.
Getting Started
Install with pip:
pip install browser-use
playwright install chromium
A minimal agent looks like this:
import asyncio
from browser_use import Agent
from langchain_anthropic import ChatAnthropic
async def main():
agent = Agent(
task="Find the current price of a MacBook Pro 14-inch on apple.com and return it",
llm=ChatAnthropic(model="claude-opus-4-7"),
)
result = await agent.run()
print(result)
asyncio.run(main())
Set your API key in the environment (ANTHROPIC_API_KEY), and this will open a real Chromium window, navigate to apple.com, find the product, and return the price.
The browser is visible by default (not headless), which is useful during development. For production you can set headless=True in the browser configuration.
How It Handles Page Content
This is where browser-use makes a meaningful architectural choice. Most browser agents take a screenshot and send it to a vision model. browser-use does this too, but it also has a DOM extraction mode that produces a structured text representation of the page — all the interactive elements (links, buttons, inputs, dropdowns) with their labels and a reference index.
The structured extraction is much cheaper and faster for the majority of tasks, because:
- You’re sending text rather than image tokens
- The model doesn’t have to infer where clickable elements are — they’re listed explicitly
- The extraction respects the semantic HTML so buttons are buttons and inputs are inputs
Vision mode kicks in when the task genuinely requires understanding a chart, an image, a CAPTCHA, or a page where the visual layout is meaningful. You can set the strategy explicitly or let the agent decide.
Multi-Step and Multi-Tab Workflows
browser-use maintains session state across steps, which means it can handle workflows like:
- Log in, navigate to a dashboard, export a file, confirm the download
- Search across multiple sites and aggregate results in a new tab
- Fill a multi-page form with branching logic depending on earlier answers
- Navigate through paginated results and extract data from each page
Here’s an example of a more involved task:
agent = Agent(
task="""
Go to Linear.app, find all issues assigned to me in the 'Infrastructure' team
that are marked as high priority and haven't been updated in the last 7 days,
and return them as a list with their title and current status.
""",
llm=llm,
)
The agent will handle login (if you pass saved session cookies), navigate the interface, apply filters, and extract the relevant data — without you writing a line of Playwright.
Authentication and Session Management
For authenticated workflows, browser-use supports saved browser state:
from browser_use import BrowserConfig, BrowserContextConfig
browser_config = BrowserConfig(
new_context_config=BrowserContextConfig(
storage_state="auth.json" # Saved Playwright auth state
)
)
agent = Agent(task="...", llm=llm, browser_config=browser_config)
You generate auth.json once with a Playwright login script, then reuse it. The agent starts the session already authenticated. This is the most reliable approach for production agents that need to access authenticated resources.
For OAuth flows and complex SSO, you may need to run the authentication step interactively and save state, since those flows often have bot detection that’s hard to automate fully.
Customising Agent Behaviour
Custom actions
You can extend the agent with your own actions that the LLM can call:
from browser_use import Agent, Controller
controller = Controller()
@controller.action("Save extracted data to database", param_model=DataRecord)
async def save_to_db(record: DataRecord):
await db.insert(record)
return "Saved successfully"
agent = Agent(
task="Extract all product listings and save each one to the database",
llm=llm,
controller=controller,
)
This is how you connect browser-use into a larger workflow — the agent can call your functions when it decides it has data worth saving, rather than returning everything at the end.
System prompt customisation
from browser_use import SystemPrompt
class MyPrompt(SystemPrompt):
def important_rules(self) -> str:
return """
- Always extract prices in GBP
- If a product is out of stock, skip it and move to the next
- Do not click on any advertisement or sponsored content
"""
Output structure
Use Pydantic models to get structured output from the agent:
from pydantic import BaseModel
class ProductListing(BaseModel):
name: str
price: float
currency: str
in_stock: bool
url: str
agent = Agent(
task="Extract all laptop listings from the first page of results",
llm=llm,
output_model=ProductListing,
)
results = await agent.run()
# results is a list of validated ProductListing instances
Model Selection
browser-use works with any LangChain-compatible model. Practical guidance:
Claude (Anthropic): Claude 3.5 Sonnet and Opus perform well on complex multi-step navigation, especially for tasks requiring careful reading of content. Good balance of cost and capability for most workflows.
GPT-4o: Comparable performance on most tasks. The vision mode works well. Higher cost per token than Claude Sonnet.
Gemini: Works well, particularly for tasks that are vision-heavy. The context window is an advantage for pages with lots of content.
Local models (via Ollama): Capable for simple, well-structured tasks but struggle with complex multi-branch navigation that requires sustained reasoning. Useful for development or for high-volume tasks where cost is the constraint.
For most production use, Claude Sonnet 4.6 or GPT-4o is the practical choice. Use Opus or GPT-4o for tasks that require deeper reasoning about complex UIs.
Where It Fits Relative to Alternatives
Stagehand (Browserbase) is a TypeScript-first alternative with a similar philosophy. If your stack is TypeScript, Stagehand is worth comparing directly. browser-use is Python-first and has a larger community footprint in the Python agent ecosystem.
Computer Use (Anthropic/Claude) operates at the OS level — it can use any application, not just a browser. This is more powerful but also significantly more expensive because everything goes through vision. browser-use’s DOM extraction approach is cheaper for web-specific tasks.
Playwright MCP exposes Playwright browser actions as MCP tools that Claude can call directly. This gives you fine-grained control but requires the agent to make correct Playwright calls rather than reasoning at the semantic level. browser-use abstracts this away.
Traditional Playwright/Puppeteer scripts: Still the right choice when the workflow is perfectly predictable and you need deterministic execution. browser-use is for tasks where the path varies or the page structure changes.
Limitations to Know Before You Build
CAPTCHAs: browser-use has no CAPTCHA solving built in. Sites with aggressive bot detection will block the automation. You can integrate third-party CAPTCHA solving services, but this adds complexity and latency.
Rate limits and anti-scraping: browser-use doesn’t add stealth tooling by default. High-volume scraping against sites with bot protection will fail. For those use cases, Browserbase (Stagehand’s backend) offers managed browser infrastructure with fingerprinting protection.
Non-determinism: Because the LLM is making decisions at each step, the same task can take a different number of steps on different runs. Token costs will vary. For cost-sensitive production workloads, set max_steps and monitor average costs per task type.
Complex authentication flows: MFA, SSO with redirects, and OAuth with popups can require manual session setup or intermediate human verification steps. Build these out explicitly rather than expecting the agent to handle them fully autonomously.
A Practical Starting Point
The fastest path to a working agent:
pip install browser-use && playwright install chromium- Write a minimal agent with a clear, specific task description
- Run it with the browser visible (
headless=False) and watch what it does - Iterate on the task description before adding any configuration
- Once the happy path works, add error handling and output structure
Most debugging time in browser-use comes from task descriptions that are too vague. The more precisely you describe what to do and what success looks like, the more reliably the agent executes.