Install
openclaw skills install anemone-browserManaged headful Chrome browser for OpenClaw agents with anti-bot-detection, human-in-the-loop VNC takeover, and multi-session window isolation. Use when: (1)...
openclaw skills install anemone-browserHeadful Chrome with anti-detection, VNC takeover, and multi-session isolation. Works on Mac, Linux, Docker — anywhere OpenClaw runs.
bash scripts/setup-mac.sh
Detects Chrome, configures OpenClaw browser profile. After setup:
openclaw browser start
# Agent's browser tool works automatically
Note: macOS setup does NOT include VNC/noVNC. The user is expected to access the Mac via their own remote desktop solution (e.g. macOS Screen Sharing, Tailscale, or physical access). VNC takeover with noVNC links is only available on Linux.
# Install deps (once)
bash scripts/setup.sh
# Start browser + VNC environment
bash scripts/start.sh [password] [novnc_port] [cdp_port] [resolution]
start.sh outputs the noVNC URL, password, and CDP port. Safe to re-run.
Setup scripts configure this automatically. Manual reference:
macOS:
{
"browser": {
"enabled": true,
"defaultProfile": "openclaw",
"headless": false,
"executablePath": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
}
}
Linux:
{
"browser": {
"enabled": true,
"headless": false,
"noSandbox": true,
"executablePath": "/usr/bin/google-chrome-stable"
}
}
Multiple sessions share one Chrome (same cookies/logins) but each gets its own window.
On session start — open your own tab, save the targetId:
browser action=open targetUrl="https://example.com" profile=openclaw
# Returns targetId — THIS IS YOURS, save it
ALL subsequent calls — always include your targetId:
browser action=snapshot profile=openclaw targetId="<your-targetId>"
browser action=navigate profile=openclaw targetId="<your-targetId>" targetUrl="..."
browser action=act profile=openclaw targetId="<your-targetId>" ...
On session end — close your tab:
browser action=close targetId="<your-targetId>"
NEVER operate without targetId — you'll land on another session's tab.
NEVER pick another session's tab from browser action=tabs.
import json, asyncio, websockets, urllib.request
async def open_new_window(cdp_port, url):
version = json.loads(urllib.request.urlopen(f"http://127.0.0.1:{cdp_port}/json/version").read())
async with websockets.connect(version["webSocketDebuggerUrl"]) as ws:
await ws.send(json.dumps({
"id": 1, "method": "Target.createTarget",
"params": {"url": url, "newWindow": True}
}))
resp = json.loads(await ws.recv())
return resp["result"]["targetId"]
Chrome (one instance, one profile, shared cookies)
├── Window targetId=AAA → Session A
├── Window targetId=BBB → Session B
└── Window targetId=CCC → Session C
When hitting a CAPTCHA, login wall, or any blocker, send the user a noVNC link:
https://<IP>:<NOVNC_PORT>/vnc.html?password=<PASSWORD>&autoconnect=true&resize=scale
Linux/Docker (from start.sh output):
https://57.129.90.145:10150/vnc.html?password=e0GGP4xeMUL5ga&autoconnect=true&resize=scale
macOS: VNC takeover is NOT available. The user must access the Mac directly (physical access, macOS Screen Sharing, or their own remote desktop solution).
HeadlessChrome in UA--disable-blink-features=AutomationControlled — no navigator.webdriver=true{"method": "Network.setUserAgentOverride", "params": {
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/131.0.0.0 Safari/537.36"
}}
file://, javascript:, data:text/html blocked; extensions blocked; DevTools disabledDo NOT use Chrome's --kiosk flag. It hides the tab bar and address bar, making multi-window unusable via VNC. Use --start-maximized instead.