Das Problem

Du willst einen AI-Agent der für dich Webseiten bedient — Formulare ausfüllen, Preise vergleichen, Lieferfenster checken. Browser Use (98k GitHub Stars, MIT-Lizenz) macht genau das: Claude oder GPT steuert einen echten Browser via CDP.

Aber:

  1. Browser Use will Chromium herunterladen — du hast aber Brave und willst den nutzen
  2. Die Config-Datei ignoriert den Parameter für den Browser-Pfad
  3. Die MCP-Integration in Claude Code braucht einen Workaround

TL;DR

Browser Use 0.13 nutzt einen Rust-Core mit CDP statt Playwright. Die Config-Schema-Migration wirft executable_path raus. Lösung: Wrapper-Script mit Monkey-Patch für den MCP Server, das Brave als Browser erzwingt.

Was sich in v0.13 geändert hat

Falls du ältere Tutorials findest die Playwright erwähnen — vergiss sie. Version 0.13 hat den Stack umgebaut:

Alt (< 0.13)Neu (0.13)
PlaywrightRust-Core + CDP (cdp_use)
langchain ChatModelsEigene ChatAnthropic / ChatOpenAI Wrapper
pip install browser-usepip install "browser-use[core]"

Der eigene ChatAnthropic Wrapper bedeutet auch: kein langchain nötig. Installierst du es trotzdem, bekommst du einen Dependency-Konflikt bei der anthropic-Library-Version.

Installation

Python 3.11+ in einem venv (Ubuntu/Debian erzwingt das seit PEP 668):

python3 -m venv ~/browser-use-venv
~/browser-use-venv/bin/pip install "browser-use[core]"

API Key als .env:

echo "ANTHROPIC_API_KEY=sk-ant-..." > ~/browser-use-venv/.env

Brave statt Chromium

Im Python-Code: Kein Problem

from browser_use.beta import Agent, BrowserProfile, ChatAnthropic
from dotenv import load_dotenv
load_dotenv()

profile = BrowserProfile(
    executable_path="/usr/bin/brave-browser",
    headless=False,
)

llm = ChatAnthropic("claude-sonnet-4-20250514")

agent = Agent(
    task="Öffne https://example.com und sag mir die Überschrift.",
    llm=llm,
    browser_profile=profile,
)

BrowserProfile akzeptiert executable_path als Parameter. Brave öffnet sich, der Agent steuert ihn. Fertig.

In der Config-Datei: Die Falle

Browser Use speichert seine Konfiguration in ~/.config/browseruse/config.json. Beim ersten Start wird eine Migration ausgeführt, die ein Pydantic-Schema (BrowserProfileEntry) anwendet. Dieses Schema kennt genau diese Felder:

headless, user_data_dir, allowed_domains, downloads_path

executable_path ist nicht dabei. Die Migration wirft es kommentarlos raus. Du schreibst es rein, startest den MCP Server, und er öffnet trotzdem Chromium.

Der Fix: Wrapper-Script

Für den MCP Server (der die Config liest, nicht deinen Python-Code) brauchst du einen Monkey-Patch:

# mcp_brave.py
"""Browser Use MCP Server wrapper that forces Brave as browser."""
import browser_use.mcp.server as mcp_server
import asyncio

_orig_init = mcp_server.BrowserUseServer._init_browser_session

async def _patched_init(self, allowed_domains=None, **kwargs):
    kwargs.setdefault("executable_path", "/usr/bin/brave-browser")
    await _orig_init(self, allowed_domains=allowed_domains, **kwargs)

mcp_server.BrowserUseServer._init_browser_session = _patched_init

if __name__ == "__main__":
    asyncio.run(mcp_server.main())

Das patcht _init_browser_session bevor der Server startet. kwargs werden an BrowserProfile() durchgereicht — und da wird executable_path akzeptiert. Der Umweg über die Config-Datei wird umgangen.

MCP-Integration in Claude Code

Der MCP Server gibt dir Tools wie navigate, click, type_text, screenshot, extract_content und scroll direkt in Claude Code.

Registrierung

claude mcp add browser-use \
    -e ANTHROPIC_API_KEY="<DEIN-KEY>" \
    -- ~/browser-use-venv/bin/python ~/browser-use-venv/mcp_brave.py

Verifikation

claude mcp list
# browser-use: ... - ✔ Connected

Die Tools sind erst nach einem Neustart von Claude Code verfügbar (MCP-Server werden bei Session-Start initialisiert).

Was du damit machen kannst

Claude Code wird zum Browser-Agent. Statt manuell durch Webseiten zu klicken:

  • “Öffne <SHOP-URL> und sag mir das günstigste Angebot für X”
  • “Logge dich bei <SERVICE> ein und lies das nächste Lieferfenster aus”
  • “Füll das Formular auf <SEITE> mit diesen Daten aus”

Claude entscheidet selbst welche MCP-Tools er in welcher Reihenfolge aufruft — navigate, screenshot, extract, click, type. Du siehst den Brave-Browser live.

Sicherheit: Allowed Domains

Wenn der Agent auf internen Systemen arbeitet, willst du einschränken wo er surfen darf:

profile = BrowserProfile(
    executable_path="/usr/bin/brave-browser",
    allowed_domains=["*.darkside.local", "*.deathstar.lan"],
)

Ohne diese Einschränkung kann der Agent jede URL öffnen. Bei internen Diensten mit Session-Cookies willst du das nicht.

Headless auf einem Server

Für einen Server ohne Display (z.B. einen dedizierten Automations-Host):

profile = BrowserProfile(
    executable_path="/usr/bin/brave-browser",
    headless=True,
)

Der Browser läuft unsichtbar im Hintergrund. Nützlich für Cronjobs oder geplante Automationen — der Agent bestellt dir um 7 Uhr morgens Kaffee nach, ohne dass du am Bildschirm sitzen musst.

Dateien im Überblick

PfadZweck
~/browser-use-venv/Python venv mit browser-use
~/browser-use-venv/.envAPI Key (nicht committen!)
~/browser-use-venv/mcp_brave.pyMCP Wrapper mit Brave-Patch
~/.config/browseruse/config.jsonBrowser Use Config (Finger weg von executable_path)

Lessons Learned

  • Browser Use 0.13 ist ein Breaking Change. Alte Tutorials mit Playwright-Setup funktionieren nicht mehr. Der Rust-Core mit CDP ist schneller, aber die Doku hinkt hinterher.
  • Pydantic-Schema-Migrationen sind unsichtbare Fallen. Du schreibst was in die Config, die Migration wirft es raus, kein Fehler, kein Log. Klassischer “es funktioniert einfach nicht”-Moment.
  • Monkey-Patching ist manchmal die pragmatischste Lösung. Upstream-PR wäre sauberer, aber der Wrapper-Dreizeiler löst das Problem in 30 Sekunden.
  • MCP-Server brauchen einen Session-Neustart. Nicht offensichtlich wenn du den Server hinzufügst und dich wunderst warum keine Tools da sind.