Install
openclaw skills install babata-browserBabata Browser v3.0 — Lightweight Playwright browser automation. Scan-first, act-second. Accessibility Tree preferred, zero extra AI dependencies. Use when: JS-rendered pages, gov sites, form filling, screenshot evidence, interactive web. NOT for: static pages (use web_fetch), API queries (use CLI), text search (use web_search).
openclaw skills install babata-browserLightweight Playwright browser automation. Scan before acting, text before screenshots.
Gov policy sites (JS-rendered) / SPA data collection / Form filling / Screenshot evidence / web_fetch returns <500 chars / WeChat articles
Static pages → web_fetch / API queries → fetch() / Text search → web_search (Tavily)
pip install playwright && python -m playwright install chromium
cd skills/babata-browser && pip install -e .
Never snapshot blindly. Find interactive elements with JS first:
browser.execute_js(page, """
(() => {
const els = document.querySelectorAll('a[href], button, input, select, textarea, [role=button], [onclick]');
return [...els]
.filter(el => { const r = el.getBoundingClientRect(); return r.width > 0 && r.height > 0 && r.top < window.innerHeight; })
.map((el, i) => ({ i, tag: el.tagName.toLowerCase(), text: (el.innerText || el.value || '').trim().slice(0, 50), id: el.id, href: el.href?.slice(0, 80) }));
})()
""")
browser.click(page, text='Latest Policy') # ✅ Stable
# ❌ browser.click(page, selector='#content > div:nth-child(3) > a')
browser.execute_js(page, """
new Promise(resolve => { let tries = 0;
const t = setInterval(() => {
if (document.body.innerText.includes('expected text') || ++tries > 30) { clearInterval(t); resolve(tries < 30 ? 'found' : 'timeout'); }
}, 500);
})
""")
Accessibility Snapshot → find target region → get_text(selector=region)
→ still unclear? → screenshot (last resort)
from scripts.babata_browser import execute_task
result = execute_task('Open https://example.com, search policy, extract top 5 titles')
from scripts.babata_browser import BabataBrowser
browser = BabataBrowser(headless=True); browser.start(); page = browser.new_page()
browser.goto(page, 'https://example.com')
browser.click(page, text='Agree')
browser.fill(page, 'input[name="q"]', 'query')
text = browser.get_text(page)
browser.screenshot(page, path='evidence.png')
browser.stop() # ⚠️ Always close
babata-browser 'Open GitHub Trending, extract top projects' --json
| Action | Description | Use Case |
|---|---|---|
goto(url) | Navigate | Open target page |
get_text(sel?) | Extract text (scoped optional) | Page body |
get_links(limit) | All links | Navigation, search results |
click(text=, sel=) | Click by text or CSS | Pagination, submit, nav |
fill(sel, val) | Fill input | Search box, login form |
screenshot(path) | Full-page screenshot | Evidence, visual verify |
scroll(n) | Scroll | Lazy-loaded content |
execute_js(code) | Run JS | Element scan, smart wait |
extract_table(sel) | Table to dict list | Data tables |
| Error | Fix |
|---|---|
ERR_TIMED_OUT | Increase timeout: goto(page, url, timeout=60000) |
| CloudFlare "Just a moment..." | Blocked — switch data source |
Element not found | Scan first, click by text not CSS |
page.click: Timeout | Use smart wait, not fixed sleep |
| Orphaned browser process | Always call stop() in try/finally |
headless=Truestop() after use| Playwright MCP | babata-browser v3.0 | |
|---|---|---|
| Dependencies | Node + npx + Chromium | Python + Playwright + Chromium |
| AI decisions | MCP client | Babata LLM direct |
| Token efficiency | MCP protocol overhead | CLI, zero protocol cost |
| Best for | Long-running automation | High-frequency interaction, sampling |
| Version | Date | Changes |
|---|---|---|
| v2.1 | 2026-05-11 | Smart scan JS, smart wait, layered extraction, error table, security rules |
| v3.0 | 2026-05-11 | Full English localization, streamlined structure, version bump |