Install
openclaw skills install @tangjing/page-js-operation-enOperate web page elements via CDP and Page JS Extension, save 95% Token (for UI automation testing ONLY, NOT a web browsing tool)
openclaw skills install @tangjing/page-js-operation-enThis Skill is designed EXCLUSIVELY for browser automation testing scenarios.
This is NOT a tool for daily website browsing or general web access.
✅ Designed for:
❌ NOT Designed for:
Strict Rules for Sensitive Fields (password, hidden, file):
| Action | Allowed? | Condition |
|---|---|---|
| Read value | ❌ NEVER | Extension code skips these fields during collection |
| Write value | ⚠️ User instruction ONLY | Requires EXPLICIT user command, never auto-collected |
Technical Guarantee:
// In collectAllElements() - sensitive fields are NEVER collected
const sensitiveTypes = ['password', 'hidden', 'file'];
if (element.tagName === 'INPUT' && sensitiveTypes.includes(element.type)) {
return; // Skipped - not indexed, not searchable
}
What this means:
searchElementsByKey()document.querySelector('input[type="password"]').value = 'xxx' requires user-provided selectorThis Skill must be used with the following components:
Page JS Extension - Chrome Extension (manual installation required)
chrome://extensions/ → Developer mode → Load unpackedCDP Environment - Chrome DevTools Protocol access
http://127.0.0.1:9222ElementCollector is injected (first time only)exportData() to get element key list (non-sensitive)DO NOT use this Skill on:
DO NOT read or modify:
type="password")This Skill is suitable for:
typeof ElementCollector !== 'undefined'
// Returns true if extension is installed
ElementCollector.exportData()
// Returns: { elements: [...keys], keywords: [...], elementCount: N }
// Note: Only returns element key list, not actual DOM content
const results = ElementCollector.searchElementsByKey('{button-keyword}');
const element = Object.values(results)[0];
if (element) element.click();
const inputs = ElementCollector.searchElementsByKey('{search-box/input}');
const input = Object.values(inputs)[0];
if (input) {
input.value = '{value}';
input.dispatchEvent(new Event('input', { bubbles: true }));
}
const selects = ElementCollector.searchElementsByKey('{selector-keyword}');
const select = Object.values(selects)[0];
if (select) {
select.value = '{option-value}';
select.dispatchEvent(new Event('change', { bubbles: true }));
}
| Operation | CDP Runtime.evaluate Expression |
|---|---|
| Check extension | typeof ElementCollector !== 'undefined' |
| Get index | ElementCollector.exportData() |
| Click | ElementCollector.searchElementsByKey('btn')[0].click() |
| Fill | ElementCollector.searchElementsByKey('input')[0].value = 'text' |
| Select | ElementCollector.searchElementsByKey('select')[0].value = 'option' |
| Operation | Recommended Keywords |
|---|---|
| Search | '搜索', 'search' |
| Submit | '提交', 'submit' |
| Cancel | '取消', 'cancel' |
| Confirm | '确定', 'confirm' |
| Delete | '删除', 'delete' |
| Edit | '编辑', 'edit' |
| Save | '保存', 'save' |
Browser DOM → ElementCollector (Memory Index) → CDP → Local AI Agent
↑
(Key list only, no sensitive content)
Extension Level:
Agent Level:
User Responsibility:
| Data Type | Collected | Operable | Description |
|---|---|---|---|
| Element id | ✅ Yes | - | For indexing |
| Element class | ✅ Yes | - | For indexing |
| Element title | ✅ Yes | - | For indexing |
| Element innerText | ✅ Yes | - | For indexing (max 100 chars) |
| Regular inputs | ✅ Yes | ✅ Read/Write | Searchable, fillable, readable |
| Password fields | ❌ Not collected | ⚠️ Write via explicit user command ONLY | Never indexed, never readable, can only write with explicit user DOM command |
| Hidden fields | ❌ Not collected | ⚠️ Write via explicit user command ONLY | Never indexed, never readable, can only write with explicit user DOM command |
| File uploads | ❌ Not collected | ⚠️ Write via explicit user command ONLY | Never indexed, never readable, can only write with explicit user DOM command |
| Cookie/Storage | ❌ No | ❌ Inaccessible | Extension has no such permission |
Key Points:
exportData() resultsTechnical Implementation:
// Automatically skip sensitive fields in collectAllElements()
const sensitiveTypes = ['password', 'hidden', 'file'];
if (element.tagName === 'INPUT' && sensitiveTypes.includes(element.type)) {
return; // Not collected to index, cannot search via searchElementsByKey
}
Note: Sensitive fields are not indexed but can still be operated via native DOM API with explicit user command (e.g., document.querySelector('input[type="password"]').value = 'xxx'). This extension does not proactively read values from these fields.
# 1. Download source code
git clone https://github.com/TangJing/openclaw_access_web_page_js.git
cd openclaw_access_web_page_js
# 2. Review source code (recommended)
# Check for:
# - Network request code
# - Data exfiltration logic
# - manifest.json permissions
# 3. Install extension
# Open chrome://extensions/
# Enable "Developer mode"
# Click "Load unpacked", select project directory
# 1. Create Skill directory
mkdir -p ~/.openclaw/workspace/skills/page-js-operation
# 2. Save this SKILL.md to the directory
# Path: ~/.openclaw/workspace/skills/page-js-operation/SKILL.md
# 3. Refresh Skills
openclaw agent --message "refresh skills"
# On search engine page
openclaw agent --message "use page_js_operation to fill search box with 'keyword'"
openclaw agent --message "use page_js_operation to click search button"
# On content page
openclaw agent --message "use page_js_operation to click next page button"
openclaw agent --message "use page_js_operation to select category from dropdown"
# DO NOT use on login pages
# openclaw agent --message "fill username and password and click login"
# Reason: Involves password fields
Use Dedicated Browser Profile
Limit Accessible Domains
User Confirmation Mechanism
Regular Review
// Collection phase
elementMap = Map<key, Element> // key → DOM reference
keywordMap = Map<keyword, Set<keys>> // keyword → key set
// key format: id|class|title|innerText
// Example: "login-btn|btn primary||Login"
By using this Skill, you agree:
Intended Use: This Skill is designed exclusively for automated UI testing in development and CI/CD environments. It is NOT a general-purpose web automation tool for personal use.