Install
openclaw skills install @qqbrowserteam/qqbrowser-skillBrowser automation CLI for AI agents. Use when: (1) the user asks to open, navigate, or interact with a website; (2) the user needs to fill forms, click buttons, take screenshots, download files, or inspect page state; (3) the user asks to extract structured data from web pages; (4) the user asks to
openclaw skills install @qqbrowserteam/qqbrowser-skillBrowser automation CLI for AI agents. Wraps every task in an isolated Chrome Tab Group, supports both live automation and reusable playbook replay.
Linux x86_64, Windows, macOS. Other Linux architectures (ARM, etc.) are not supported.
# Linux / macOS
pipx install qqbrowser-skill
qqbrowser-skill install # Download and install QQ Browser
# Windows
pip install qqbrowser-skill
qqbrowser-skill install
qqbrowser-skill browser_start_session --sessionId task-demo-001 --initialUrl https://example.com
qqbrowser-skill playbook_list # Check existing playbooks first
qqbrowser-skill browser_snapshot # Get elements with encoded indices
qqbrowser-skill browser_click_element --index "<index-from-snapshot>"
qqbrowser-skill browser_end_session --sessionId task-demo-001
browser_start_session --sessionId <id> [--title "<title>"] [--color <color>] [--initialUrl <url>]
browser_end_session --sessionId <id>
--initialUrl: 启动会话时直接导航到指定 URL,省去单独调用browser_go_to_url的步骤。如果提供了该参数,会话创建后会自动打开对应页面。Isolation mode is fixed to
enforce—browser_start_sessiondoes not accept an--isolationflag.
browser_go_to_url --url <url>
browser_go_back
browser_wait --seconds <n> # Default 3s
browser_snapshot # Element indices (for interaction)
browser_snapshot --markdown # Markdown (for reading)
browser_screenshot [--full] [--annotate]
browser_snapshot --markdown returns clean Markdown of the page (ads/nav/scripts stripped, no element indices). Use it when AI needs to read/summarize page content in one-off tasks (Branch C). Do NOT use it inside task_begin/task_end (Branch B) or when you need structured data — use browser_eval_content_js instead.
browser_click_element --index <id>
browser_dblclick_element --index <id>
browser_focus_element --index <id>
browser_input_text --index <id> --text "<content>"
browser_scroll_down [--amount <px>]
browser_scroll_up [--amount <px>]
browser_scroll_to_text --text "<text>"
browser_scroll_to_top
browser_scroll_to_bottom
browser_scroll_by --direction <dir> --pixels <n> [--index <id>]
browser_scroll_into_view --index <id>
browser_keypress --key <key>
browser_keyboard_op --action type --text "<content>"
browser_keyboard_op --action inserttext --text "<content>"
browser_keydown --key <key>
browser_keyup --key <key>
browser_get_dropdown_options --index <id>
browser_select_dropdown_option --index <id> --text "<option>"
browser_check_op --index <id> --value / --no-value
browser_find_and_act --by <role|text|label|placeholder|testid|css> --value "<v>" --action <click|fill|type> [--actionValue "<v>"] [--name "<n>"] [--nth <n>]
--nth: 1-based index for list iteration (--nth 1= first match). Useby: "css"+--nthfor loops.
browser_get_info --type <text|url|title|html|value|attr|count|box|styles|list_selector> [--index <id>] [--attribute <name>]
browser_check_state --state <visible|enabled|checked> --index <id>
list_selector: Auto-detect CSS selector for list iteration. Pass any list item's index → returns{"selector": "...", "count": N, "samples": [...]}.
browser_eval_content_js --script "<js_code>"
browser_eval_content_js --script "<base64>" --base64
browser_download_file --index <id>
After a download succeeds, return the saved file path to the user or the next processing step. If the user asked to analyze the downloaded file, treat that path as the output of the browser sub-task and continue outside the browser workflow.
browser_tab_open --url <url>
browser_tab_list
browser_tab_switch --tabId <n>
browser_tab_close --tabId <n>
browser_dialog --action <accept|dismiss> [--text "<input>"]
task_begin --description "<desc>"
task_end
task_latest # Get most recent recording
When to use: Only when user explicitly asks to record/save/reuse (trigger words: "record this", "save this", "保存为脚本", "录一下", "下次还要用"). Without explicit request, do NOT use these commands.
Before calling
task_begin: MUST read references/playbook.md for recording quality rules — they are required to make the recording reusable.After
task_end: Raw recordings are NOT replay-ready. Calltask_latest, then follow references/playbook.md → From Recording to Playbook to generate, save, and verify the playbook JSON.
playbook_list # List available playbooks
browser_replay --script <path> [--variables '{"key":"value"}']
How to use:
playbook_listreturns available playbooks withpath,name,description, andparams(required variables).- Match the user's task against returned playbooks by name/description/URL.
- Read the matched playbook's
paramsto know which--variableskeys are required.- Pass variables as JSON:
--variables '{"param1": "value1", "param2": "value2"}'⚠️
browser_replaycan take up to 10 minutes. Wait patiently — do NOT interrupt, retry, or fall back to manual mode.For full output format (success/failure/step_results), see references/commands-extended.md.
browser_done --success --text "<msg>"
status
list
browser_doneis a status/reporting utility only. It does not replacebrowser_end_session, and it does not release the session mapping.
Every automation MUST be wrapped in
browser_start_session/browser_end_session, and you MUST runplaybook_listbefore anytask_beginorbrowser_go_to_url. Never start manual automation without first checking for existing playbooks.
Step 0: Composite request? ← Multiple browser sub-tasks or browser → AI → browser flow?
├── YES → See references/session-lifecycle.md → Handling Composite Tasks.
│ Start ONE session for the whole composite task,
│ then run each sub-task through Step 2-3 independently,
│ and call browser_end_session once after all sub-tasks.
└── NO → Continue as a single task ↓
Step 1: browser_start_session ← ⛔ MANDATORY: first command, no exceptions
Step 2: playbook_list ← ⛔ MANDATORY: ALWAYS call before any navigation, even if you think no playbook exists
Step 3: Match?
├── YES → browser_replay ← Branch A: Replay
└── NO → Manual automation
├── Recording mode ← Branch B: user explicitly asks to record
│ task_begin
│ browser_* operations...
│ task_end
│ → then continue with references/playbook.md
└── Non-recording mode ← Branch C: one-off task
browser_* operations...
Step 4: browser_end_session ← ⛔ MANDATORY: ALWAYS execute, even on failure or early exit
⛔ Non-Negotiable Rules:
playbook_listMUST be called every time afterbrowser_start_session, before anybrowser_go_to_urlor other browser commands — no exceptions, no shortcuts.browser_end_sessionMUST be called at the end regardless of outcome (success, failure, error, early exit, user interrupt). Think of it as afinallyblock — it always runs.
Recording (Branch B) triggers only on explicit user request. Trigger words: "record this", "save this", "make reusable", "保存为脚本", "录一下", "下次还要用". Without an explicit request, use Branch C (non-recording) — do not wrap the operations in task_begin / task_end.
If the site requires CAPTCHA, SMS code, email code, MFA/2FA, QR login, device confirmation, or any other human verification step:
Do not blindly retry replay or switch branches just because a human verification wall appears.
qqbrowser-skill browser_start_session --sessionId task-<purpose>-<counter> [--initialUrl <url>]
sessionId must be unique per task (e.g. task-form-001). Use --initialUrl to navigate directly on session start, combining session creation and navigation into one step. Full flags and idempotency rules: references/session-lifecycle.md.
qqbrowser-skill playbook_list
This step is non-negotiable. You MUST call playbook_list every single time, even if:
Match returned playbooks against the user's task by name, description, keywords, target URL, and side-effect profile.
⚠️
browser_replaymay run for up to 10 minutes. Wait for it to return — NEVER interrupt, retry, or fall back to manual mode while it is still running. Replayed operations are usually not idempotent (posting, submitting, messaging), so a premature retry will cause duplicate side effects.
qqbrowser-skill browser_replay --script <path> --variables '{...}'
Before replaying a playbook that may cause real-world side effects — such as posting, submitting, sending messages, purchasing, deleting, or publishing — verify all of the following:
If any of the above is uncertain, do not replay blindly. Prefer draft mode, test data, manual review, or explicit user confirmation.
browser_replay Returns FailureWhen replay finishes with success: false:
Before calling
task_begin, MUST read references/playbook.md. These rules are required to make the recording reusable; do not start recording from the short example alone.
qqbrowser-skill task_begin --description "描述任务"
qqbrowser-skill browser_go_to_url --url <url>
qqbrowser-skill browser_snapshot
# ... interact using indices ...
qqbrowser-skill task_end
After task_end, continue following references/playbook.md to generate the playbook JSON.
Default fallback for one-off tasks. Do not call task_begin / task_end. Still call playbook_list first (Step 2 is mandatory for all branches).
qqbrowser-skill playbook_list # ⛔ MANDATORY — do not skip
qqbrowser-skill browser_go_to_url --url <url>
qqbrowser-skill browser_snapshot
# ... interact using indices ...
finally block)qqbrowser-skill browser_end_session --sessionId task-<purpose>-<counter>
This step is non-negotiable. browser_end_session MUST be called at the end of every task, regardless of outcome:
browser_end_sessionbrowser_end_sessionbrowser_end_sessionbrowser_end_session afterNever leave a session dangling. If you called browser_start_session, you MUST call browser_end_session before finishing.
qqbrowser-skill browser_start_session --sessionId task-form-001 --initialUrl https://example.com/signup
qqbrowser-skill playbook_list
qqbrowser-skill browser_snapshot
qqbrowser-skill browser_input_text --index "<name-index>" --text "Jane Doe"
qqbrowser-skill browser_input_text --index "<email-index>" --text "jane@example.com"
qqbrowser-skill browser_select_dropdown_option --index "<state-index>" --text "California"
qqbrowser-skill browser_click_element --index "<submit-index>"
qqbrowser-skill browser_wait --seconds 2
qqbrowser-skill browser_snapshot # Verify result
qqbrowser-skill browser_end_session --sessionId task-form-001
| Approach | When | Replayable? |
|---|---|---|
browser_snapshot --markdown | AI reads/summarizes a page once (Branch C only) | ❌ |
browser_snapshot + browser_get_info | Read one specific element's text/attribute | ❌ |
browser_eval_content_js | Structured JSON / multiple items / only safe option in Branch B | ✅ |
qqbrowser-skill browser_start_session --sessionId task-extract-001 --initialUrl https://example.com/products
qqbrowser-skill playbook_list
qqbrowser-skill browser_eval_content_js --script "JSON.stringify(Array.from(document.querySelectorAll('.product-item')).slice(0,10).map(el=>({name:el.querySelector('.name')?.textContent?.trim(), price:el.querySelector('.price')?.textContent?.trim()})))"
qqbrowser-skill browser_end_session --sessionId task-extract-001
qqbrowser-skill browser_start_session --sessionId task-feed-001 --initialUrl https://example.com/feed
qqbrowser-skill playbook_list
qqbrowser-skill browser_scroll_to_bottom
qqbrowser-skill browser_wait --seconds 2
qqbrowser-skill browser_snapshot
qqbrowser-skill browser_end_session --sessionId task-feed-001
2_sfli_qp0u (highlightIndex_attrHash_xpathHash). Generated by browser_snapshot, used to target elements. Indices are regenerated on every snapshot — always re-snapshot before reusing indices. Never invent numeric indices like 1 or 2; always copy the encoded index exactly from the latest browser_snapshot output.browser_* commands executed inside an active session already return updated page state in their response. Use standalone browser_snapshot only when you truly need a fresh interactive view or the previous response is not sufficient.browser_start_session / browser_end_session for tab group isolation.task_begin / task_end for playbook generation.| Reference | Load when… |
|---|---|
| references/commands-extended.md | You need extended details on browser_snapshot --markdown usage, browser_replay output format, or advanced flag semantics |
| references/session-lifecycle.md | You need full session rules, or the user's request is a composite task with multiple browser sub-tasks or browser → AI → browser flow |
| references/playbook.md | User asks to record/save/reuse, generate/edit a playbook JSON, or run a reusable browser task |
browser_input_text for form fields to ensure existing text is cleared.browser_find_and_act with semantic locators when element indices are unstable across sessions.browser_replay output format and consumption guide, see references/commands-extended.md.See the full skill evaluation report: QQBrowserUse