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:
- Browser Use will Chromium herunterladen — du hast aber Brave und willst den nutzen
- Die Config-Datei ignoriert den Parameter für den Browser-Pfad
- 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) |
|---|---|
| Playwright | Rust-Core + CDP (cdp_use) |
langchain ChatModels | Eigene ChatAnthropic / ChatOpenAI Wrapper |
pip install browser-use | pip 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
| Pfad | Zweck |
|---|---|
~/browser-use-venv/ | Python venv mit browser-use |
~/browser-use-venv/.env | API Key (nicht committen!) |
~/browser-use-venv/mcp_brave.py | MCP Wrapper mit Brave-Patch |
~/.config/browseruse/config.json | Browser 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.