/install browser-playwright-bridge
Browser ↔ Playwright Bridge
OpenClaw's browser tool and external Playwright scripts cannot share the same CDP connection simultaneously. This skill provides a lock-based bridge: stop OpenClaw browser → run Playwright with the same Chrome profile (cookies/login intact) → release for OpenClaw to reconnect.
Architecture
Chrome (CDP port) ← shared user-data-dir (~/.openclaw/browser/openclaw/user-data)
↕ mutually exclusive
┌──────────────┐ ┌──────────────────┐
│ OpenClaw │ OR │ Playwright script │
│ browser tool │ │ (zero token cost) │
└──────────────┘ └──────────────────┘
↕ managed by browser-lock.sh
Setup
- Install Playwright in the workspace (once):
cd \x3Cworkspace> && npm install playwright
Note:
npx playwright installis NOT needed. Playwright connects to the existing Chrome via CDP — no local browser download required.
- Copy
scripts/browser-lock.shto your workspacescripts/directory:
chmod +x scripts/browser-lock.sh
Discovering the CDP Port
The CDP port is dynamically assigned. Never hardcode it. Use discoverCdpUrl() (see below) or the shell equivalent in browser-lock.sh.
Shell one-liner:
ps aux | grep 'remote-debugging-port=' | grep -v grep | grep -o 'remote-debugging-port=[0-9]*' | head -1 | cut -d= -f2
Verify CDP is responding:
curl -s --max-time 1 http://127.0.0.1:\x3Cport>/json/version
Usage
Run a Playwright script (recommended)
./scripts/browser-lock.sh run scripts/my-task.js [args...]
./scripts/browser-lock.sh run --timeout 120 scripts/my-task.js # custom timeout
Default timeout: 300s. If the script exceeds it, the watchdog kills it and releases the lock.
This automatically: checks lock → stops OpenClaw browser → starts Chrome with CDP → runs script → cleans up → releases lock.
Manual acquire/release
./scripts/browser-lock.sh acquire # stop OpenClaw browser, start Chrome
node scripts/my-task.js # run script(s)
./scripts/browser-lock.sh release # kill Chrome, release lock
Check status
./scripts/browser-lock.sh status
Writing Playwright Scripts
Use scripts/playwright-template.js as starting point.
CDP Discovery Helper
All scripts should use discoverCdpUrl() instead of hardcoding a port:
const { execSync } = require('child_process');
/**
* Discover the CDP URL by inspecting Chrome process args.
* Falls back to CDP_PORT env var, then probes common ports.
*/
function discoverCdpUrl() {
// Method 1: extract from running Chrome process
try {
const ps = execSync(
"ps aux | grep 'remote-debugging-port=' | grep -v grep",
{ encoding: 'utf8', timeout: 3000 }
);
const match = ps.match(/remote-debugging-port=(\d+)/);
if (match) return `http://127.0.0.1:${match[1]}`;
} catch {}
// Method 2: CDP_PORT env var
if (process.env.CDP_PORT) {
return `http://127.0.0.1:${process.env.CDP_PORT}`;
}
// Method 3: probe common ports
// 18800 is the typical OpenClaw default; others are common CDP conventions
const { execSync: probe } = require('child_process');
for (const port of [18800, 9222, 9229]) {
try {
probe(`curl -s --max-time 1 http://127.0.0.1:${port}/json/version`, {
encoding: 'utf8', timeout: 2000
});
return `http://127.0.0.1:${port}`;
} catch {}
}
throw new Error('CDP port not found. Is Chrome running with --remote-debugging-port?');
}
Script Pattern
const { chromium } = require('playwright');
async function main() {
let browser;
try {
browser = await chromium.connectOverCDP(discoverCdpUrl());
} catch (e) {
console.error('❌ Cannot connect to Chrome CDP:', e.message);
console.error(' Ensure browser-lock.sh acquire was called, or Chrome is running with --remote-debugging-port');
process.exit(1);
}
const context = browser.contexts()[0]; // reuse existing context (cookies!)
const page = await context.newPage();
try {
// ====== Your automation here ======
await page.goto('https://example.com');
console.log('Title:', await page.title());
// ==================================
} catch (e) {
console.error('❌ Script error:', e.message);
throw e;
} finally {
await page.close(); // close only your tab
// NEVER call browser.close() — it kills the entire Chrome
}
}
main().then(() => process.exit(0)).catch(e => {
console.error('❌', e.message);
process.exit(1);
});
Critical rules:
browser.contexts()[0]— reuse the existing context to inherit cookies/loginpage.close()only — neverbrowser.close()- Always
process.exit(0)on success — Playwright keeps event loops alive otherwise - Wrap
connectOverCDPin try-catch — fail fast with a clear message
Workflow: Explore → Record → Replay
- Explore — Use OpenClaw browser tool (snapshot/act) to figure out a new workflow
- Record — Ask the agent to convert the steps into a Playwright script
- Replay — Run via
browser-lock.sh run— zero token cost, deterministic
Cron / Scheduled Tasks
In cron tasks, call browser-lock.sh directly:
cd /path/to/workspace && ./scripts/browser-lock.sh run scripts/publish-task.js
The lock file (/tmp/openclaw-browser.lock) prevents concurrent browser access. If a lock is stale (owner process dead), it auto-recovers.
Troubleshooting
| Problem | Fix |
|---|---|
Lock held by PID xxx |
./scripts/browser-lock.sh release to force-release |
| Playwright connectOverCDP timeout | Ensure OpenClaw browser is stopped first (acquire does this) |
CDP port not found |
Chrome isn't running; call browser-lock.sh acquire first |
openclaw browser stop doesn't kill Chrome |
Known issue; browser-lock.sh kills the process directly |
| Script hangs after completion | Add process.exit(0) at the end |
| Login expired | Use OpenClaw browser tool to re-login, then run scripts again |
Environment Variables
| Var | Default | Description |
|---|---|---|
CDP_PORT |
auto-discover | Override CDP port (skips process detection) |
CHROME_BIN |
auto-detect | Path to Chrome/Chromium binary |
HEADLESS |
auto | Set true/1 to force headless; false/0 to force headed. Auto-detects on Linux without DISPLAY |
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install browser-playwright-bridge - After installation, invoke the skill by name or use
/browser-playwright-bridge - Provide required inputs per the skill's parameter spec and get structured output
What is Browser Playwright Bridge?
Run Playwright scripts that reuse OpenClaw browser's login state via CDP with automatic lock-based conflict prevention. It is an AI Agent Skill for Claude Code / OpenClaw, with 590 downloads so far.
How do I install Browser Playwright Bridge?
Run "/install browser-playwright-bridge" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Browser Playwright Bridge free?
Yes, Browser Playwright Bridge is completely free (open-source). You can download, install and use it at no cost.
Which platforms does Browser Playwright Bridge support?
Browser Playwright Bridge is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Browser Playwright Bridge?
It is built and maintained by Sway Liu (@swaylq); the current version is v1.1.0.