PageAgent Browser Enhancement
by @dongdongbear
Enhanced browser DOM manipulation using PageAgent's page-controller. Injects into any web page to provide precise DOM extraction, interactive element detecti...
clawhub install page-agent📖 About This Skill
name: page-agent license: MIT description: Enhanced browser DOM manipulation using PageAgent's page-controller. Injects into any web page to provide precise DOM extraction, interactive element detection (cursor:pointer heuristic), and robust interaction (full event chain simulation, React-compatible input). Use when you need to operate on web pages with precision — clicking, typing, scrolling, form filling, or reading page structure. Combines with frontend-design skill for full design→code→browser-operate workflow.
PageAgent Browser Enhancement Skill
Injects alibaba/page-agent v1.5.6 PageController into web pages via the browser tool's evaluate action. Gives you superior DOM manipulation compared to basic browser actions.
Key Advantages Over Basic Browser Tool
1. cursor:pointer heuristic — detects clickable elements even without semantic tags
2. Full event chain — mouseenter→mouseover→mousedown→focus→mouseup→click (not just .click())
3. React/Vue compatible input — uses native value setter to bypass framework interception
4. contenteditable support — proper beforeinput/input event dispatch
5. Indexed elements — [N] format for precise LLM-directed operations
6. Incremental change detection — *[N] marks new elements since last step
Usage Flow
Step 1: Inject PageController into the page
Use the CDP injection script (handles the 72KB library injection):
node ~/.openclaw/workspace/skills/page-agent/scripts/inject-cdp.mjs
Where TARGET_ID is from browser(action="open", ...). The script injects both page-controller-global.js and inject.js via CDP WebSocket, outputting ✅ injected on success.
Step 2: Get page state (DOM extraction)
// Returns { url, title, header, content, footer }
// content is the LLM-readable simplified HTML with indexed interactive elements
const state = await window.__PA__.getState();
return JSON.stringify({ url: state.url, title: state.title, content: state.content, footer: state.footer });
The content field looks like:
[0]
[1]PageAgent />
[2]📋 Tips & Best Practices
Always re-inject after page navigation (SPA route changes are fine, full reloads need re-inject)
The content output is token-efficient — use it instead of screenshots when possible
For long pages, use scroll + getState to see content below the fold
Clean up highlights with window.__PA__.cleanUp() before taking screenshots
Use profile="openclaw" for the isolated browser, or profile="chrome" for the Chrome extension relay