---
name: qqbrowser-skill
description: Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, or automating any browser task.
source: https://pypi.org/project/qqbrowser-skill/
homepage: https://browser.qq.com/
permissions:
  - network: Required for browser navigation and web page interaction
  - filesystem: Required for downloading files and saving screenshots to temporary directories
---

# qqbrowser-skill

## Installation

```bash
# Linux / macOS
pipx install qqbrowser-skill && qqbrowser-skill install
# Windows
pip install qqbrowser-skill && qqbrowser-skill install
```

## Key Concepts

- **Element Index**: Encoded string like `2_sfli_qp0u` (`highlightIndex_attrHash_xpathHash`). Generated by `browser_snapshot`, used to target elements.
- **Snapshot**: Returns page content with indexed elements. Re-snapshot after any DOM change.
- **Task Recording**: All manual browser tasks MUST be wrapped with `task_begin`/`task_end`.

---

## ⚠️ Task Execution Priority (MANDATORY)

> **CRITICAL: You MUST run `playbook_list` BEFORE any `task_begin` or `browser_go_to_url`. NEVER start manual automation without first checking for existing playbooks.**

```
User task → playbook_list (MANDATORY) → Match? → YES → browser_replay
                                                → NO  → Manual automation
```

### Step 0: Check Playbooks (DO NOT SKIP)

```bash
qqbrowser-skill playbook_list
```

1. Match returned playbooks against user's task by `name`, `description`, keywords, target URL
2. If matched (even partially): `browser_replay --script <path> --variables '{...}'`
3. Only if NO match: proceed to manual automation

### Step 1: Composite Task — Multi-Playbook Orchestration

For tasks spanning multiple domains (e.g., "从知乎获取文章然后发到小红书"):

```
Composite task → Decompose into sub-tasks → Match EACH against playbook_list
→ Execute pipeline: playbook₁ → AI mediation → playbook₂ → ...
```

**Rules:**
1. Break request into atomic browser operations, match each independently
2. AI mediates BETWEEN playbooks (summarize, rewrite, transform format) — no browser commands needed
3. Each playbook runs independently — never chain inside a single `task_begin`/`task_end`
4. If a sub-task has no playbook, fall back to manual for that sub-task only
5. Report progress after each stage

**Example:**
```bash
# Sub-task A: playbook exists
qqbrowser-skill browser_replay --script ~/.qqbrowser-skill/playbooks/zhihu-article-extractor.json \
  --variables '{"topic": "人工智能", "count": "3"}'
# AI mediation: transform extracted content to target platform style
# Sub-task B: playbook exists
qqbrowser-skill browser_replay --script ~/.qqbrowser-skill/playbooks/xiaohongshu-publish.json \
  --variables '{"notes_title": "AI生成标题", "notes_content": "转换后内容"}'
```

### Step 2: Fallback to Manual Automation

Only when: no matching playbook / replay failed after retry / task requires dynamic AI decisions.

### Step 3: Save as Playbook (explicit user request only)

Trigger words: "save this", "make reusable", "保存为脚本", "下次还要用"
→ Load `qqbrowser-playbook` skill → `task_latest` → generate → save

---

## Core Workflow (Manual Automation)

```bash
qqbrowser-skill task_begin --description "描述任务"
qqbrowser-skill browser_go_to_url --url <url>
qqbrowser-skill browser_snapshot                    # Get element indices
# ... interact using indices ...
qqbrowser-skill browser_snapshot                    # Re-snapshot after DOM changes
qqbrowser-skill task_end
```

---

## Command Reference

### Navigation
```bash
browser_go_to_url --url <url>
browser_go_back
browser_wait --seconds <n>              # Default 3s
```

### Snapshot & Screenshot
```bash
browser_snapshot                        # Element indices (for interaction)
browser_snapshot --markdown             # Markdown (for reading)
browser_screenshot [--full] [--annotate]
```

### Click & Input
```bash
browser_click_element --index <id>
browser_dblclick_element --index <id>
browser_focus_element --index <id>
browser_input_text --index <id> --text "<content>"
```

### Scroll
```bash
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>
```

### Keyboard
```bash
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>
```

### Dropdown & Checkbox
```bash
browser_get_dropdown_options --index <id>
browser_select_dropdown_option --index <id> --text "<option>"
browser_check_op --index <id> --value / --no-value
```

### Find and Act (Semantic Locators)
```bash
browser_find_and_act --by <role|text|label|placeholder|testid|css> --value "<v>" --action <click|fill|type> [--actionValue "<v>"] [--name "<n>"] [--nth <n>]
```
> `--nth`: 0-based index for list iteration. Use `by: "css"` + `--nth` for loops.

### Get Information & State
```bash
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": [...]}`. Use the returned selector in `find_and_act --by css --value <selector> --nth N`.

### JavaScript Evaluation
```bash
browser_eval_content_js --script "<js_code>"
browser_eval_content_js --script "<base64>" --base64
```

### Download
```bash
browser_download_file --index <id>
browser_download_url
```

### Tab Management
```bash
browser_tab_open --url <url>
browser_tab_list
browser_tab_switch --tabId <n>
browser_tab_close --tabId <n>
```

### Dialog
```bash
browser_dialog --action <accept|dismiss> [--text "<input>"]
```

### Replay & Playbook
```bash
playbook_list                              # List available playbooks
browser_replay --script <path> [--variables '{"key":"value"}']
browser_replay --script_content '<json>'
```
> ⚠️ `browser_replay` can take **up to 10 minutes**. Wait patiently — do NOT interrupt.

**`browser_replay` Output Format:**
```json
{
  "success": true,
  "total_steps": 5,
  "completed_steps": 5,
  "step_results": [
    {"index": 0, "action": "browser_go_to_url", "description": "...", "success": true, "result": "Success! Navigated to ..."},
    {"index": 1, "action": "browser_eval_content_js", "description": "提取数据", "success": true, "result": "{\"title\":\"...\",\"content\":\"...\"}"}
  ],
  "duration_ms": 12345,
  "summary": "Replay completed successfully: 5/5 steps in 12345ms."
}
```

**How to use the output (especially for composite tasks):**
- `success`: Check overall success/failure. If `false`, check `failed_step` for error details.
- `step_results[N].result`: Contains the return value of each step. **For `browser_eval_content_js` steps, this is the extracted data (usually JSON string)** — parse it for use in subsequent AI processing or next playbook's variables.
- For composite pipelines: find all `eval_content_js` steps in `step_results`, parse their `result` field to get structured data for AI mediation.

### Task Recording
```bash
task_begin --description "<desc>"
task_end
task_latest                                # Get most recent recording
```
> After `task_end`, raw recordings are NOT replay-ready. Must generate proper playbook.

### Utility
```bash
browser_done --success --text "<msg>"
status
list
```

---

## Replay-Friendly Execution Rules

### Rule 1: Task Classification

| Category | Replayable? | Strategy |
|----------|-------------|----------|
| **A: Fixed-path** (navigate, click, fill) | ✅ | Standard commands |
| **B: Data extraction** | ⚠️ | Use `browser_eval_content_js`, NOT `snapshot --markdown` |
| **C: Content understanding** | ❌ | Mark `"requires_ai": true` |
| **D: Dynamic iteration** | ⚠️ | Fixed operation count |

### Rule 2: Data Extraction — Always Prefer JS

```bash
# ✅ Replayable
browser_eval_content_js --script "JSON.stringify(Array.from(document.querySelectorAll('.item')).slice(0,10).map(el=>({title:el.querySelector('.title')?.textContent?.trim()})))"
# ❌ Non-replayable
browser_snapshot --markdown  # then AI summarizes
```

### Rule 3: Analyze First, Execute Once

Do NOT trial-and-error during recorded tasks. Use `browser_snapshot` to analyze, then write ONE definitive script. If it fails, `task_end` → discard → re-record.

**PROHIBITED:**
- ❌ Multiple `eval_content_js` with different selectors
- ❌ Hardcoding element index in JS scripts
- ❌ Using regex on page text as selector strategy

### Rule 4: JS Selector Priority

`id` > `data-*` > ARIA > semantic class > structural path. ❌ NEVER use dynamic/hash classes (`.css-1a2b3c`).

### Rule 5: Loop Recording

Record **at least 2 iterations** using `browser_find_and_act --by css --nth`:

```bash
# ★ MANDATORY: Discover selector first
browser_get_info --type list_selector --index "3_abc1_def2"
# Record probe for playbook generator:
browser_eval_content_js --script "JSON.stringify({__list_probe__: true, selector: '.result-item h2 a', count: document.querySelectorAll('.result-item h2 a').length, samples: Array.from(document.querySelectorAll('.result-item h2 a')).slice(0,3).map(e=>e.textContent.trim())})"
# Iteration 1:
browser_find_and_act --by css --value ".result-item h2 a" --action click --nth 1
# ... extract, go back ...
# Iteration 2:
browser_find_and_act --by css --value ".result-item h2 a" --action click --nth 2
# ... extract, go back ...
```

**Key:** Use `list_selector` to discover CSS selector (NEVER guess). Use `find_and_act --nth` (not `click_element` with hardcoded index).

### Rule 6: Multi-Tab Recording

When links open new tabs:
1. After click, `browser_tab_list` to detect new tab
2. `browser_tab_switch` → extract → `browser_tab_close` → `browser_tab_switch` back
3. Do NOT use `browser_go_back` for cross-tab navigation
4. Record 2+ iterations for loop detection

### Rule 7: Fixed vs Variable Parameters

| Fixed (never parameterize) | Variable (→ `{{param}}`) |
|---|---|
| `index`, `action`, base URLs, `settings` | `text`, query params, `actionValue`, count in scripts |

### Rule 8: Non-Replayable Commands (filtered during replay)

`browser_snapshot`, `browser_screenshot`, `browser_get_info`, `browser_check_state`, `browser_get_dropdown_options`, `browser_tab_list`

### Rule 9: Prefer `browser_find_and_act` for Dynamic Content

```bash
# ✅ Stable across page changes
browser_find_and_act --by text --value "{{target}}" --action click
# ⚠️ Only for stable structures
browser_click_element --index 15_abc1_def2
```

---

## Generating Playbooks

After `task_end`, if task is replayable:

1. Load `qqbrowser-playbook` skill
2. `task_latest` → get raw recording
3. Generate clean playbook (filter AI-only commands, parameterize user data)
4. Save to `~/.qqbrowser-skill/playbooks/<name>.json`

**Rules:**
- MUST base on `task_latest` — never fabricate steps
- MUST filter excluded commands
- MUST use `qqbrowser-playbook` skill JSON format
- Raw recordings are NOT replay-ready — always generate proper playbook
