| name | drissionpage-cli |
| description | Automate browser interactions, scrape web pages and test with DrissionPage. |
| allowed-tools | Bash(drissionpage-cli:*) Bash(python:*) Bash(pip:*) |
Browser Automation with drissionpage-cli
How this works: agent drives, human assists
drissionpage-cli opens a visible (headed) browser by default. The human can see the browser window and step in whenever needed — to log in, solve a CAPTCHA, complete a 2FA prompt, or accept a cookie banner. Once the human is done, the agent continues from where it left off.
Login state persists permanently in ~/.drissionpage-cli/profile. After the human logs in once, every future session is already authenticated — the agent never needs to ask again.
Typical flow
Agent: drissionpage-cli open https://some-site.com/dashboard
→ browser opens visibly; site redirects to login page
→ "I need you to log in — complete it in the browser window, then let me know"
Human: [logs in, handles any CAPTCHA or 2FA in the browser window]
Human: "done"
Agent: drissionpage-cli snapshot
→ now sees the dashboard; continues autonomously
→ next run: already logged in, skips this entirely
When to ask the human for help:
- Login / sign-in pages
- CAPTCHA or bot-detection challenges
- Two-factor authentication prompts
- OAuth / SSO flows that open popup windows
- Cookie consent dialogs that block interaction
Quick start
drissionpage-cli open
drissionpage-cli goto https://example.com
drissionpage-cli click "#submit-button"
drissionpage-cli type "search query"
drissionpage-cli press Enter
drissionpage-cli screenshot
drissionpage-cli close
Commands
Core
drissionpage-cli open
drissionpage-cli open https://example.com/
drissionpage-cli goto https://example.com
drissionpage-cli type "search query"
drissionpage-cli click "#submit"
drissionpage-cli dblclick "@id=item"
drissionpage-cli right-click "tag:div"
drissionpage-cli fill "css:input[name=email]" "user@example.com" --submit
drissionpage-cli drag "@id=source" "@id=target"
drissionpage-cli hover "tag:button"
drissionpage-cli select "tag:select" "option-text"
drissionpage-cli upload "css:input[type=file]" ./document.pdf
drissionpage-cli check "@type=checkbox"
drissionpage-cli uncheck "@type=checkbox"
drissionpage-cli snapshot
drissionpage-cli eval "document.title"
drissionpage-cli eval "return this.id" "#element"
drissionpage-cli dialog-accept
drissionpage-cli dialog-accept "confirmation text"
drissionpage-cli dialog-dismiss
drissionpage-cli resize 1920 1080
drissionpage-cli close
Navigation
drissionpage-cli go-back
drissionpage-cli go-forward
drissionpage-cli reload
Keyboard
drissionpage-cli press Enter
drissionpage-cli press ArrowDown
drissionpage-cli press Tab
Mouse
drissionpage-cli mousemove 150 300
drissionpage-cli mousedown
drissionpage-cli mousedown right
drissionpage-cli mouseup
drissionpage-cli scroll 0 100
Save as
drissionpage-cli screenshot
drissionpage-cli screenshot "#element"
drissionpage-cli screenshot --filename=page.png
drissionpage-cli pdf --filename=page.pdf
Tabs
drissionpage-cli tab-list
drissionpage-cli tab-new
drissionpage-cli tab-new https://example.com/page
drissionpage-cli tab-close
drissionpage-cli tab-close 2
drissionpage-cli tab-select 0
Storage
drissionpage-cli state-save
drissionpage-cli state-save auth.json
drissionpage-cli state-load auth.json
drissionpage-cli cookie-list
drissionpage-cli cookie-list --domain=example.com
drissionpage-cli cookie-get session_id
drissionpage-cli cookie-set session_id abc123
drissionpage-cli cookie-set session_id abc123 --domain=example.com --httpOnly --secure
drissionpage-cli cookie-delete session_id
drissionpage-cli cookie-clear
drissionpage-cli localstorage-list
drissionpage-cli localstorage-get theme
drissionpage-cli localstorage-set theme dark
drissionpage-cli localstorage-delete theme
drissionpage-cli localstorage-clear
drissionpage-cli sessionstorage-list
drissionpage-cli sessionstorage-get step
drissionpage-cli sessionstorage-set step 3
drissionpage-cli sessionstorage-delete step
drissionpage-cli sessionstorage-clear
DevTools
drissionpage-cli console
drissionpage-cli console warning
drissionpage-cli network
drissionpage-cli run-code "result = page.title"
drissionpage-cli run-code --filename=script.py
Open parameters
drissionpage-cli open
drissionpage-cli open --headless
drissionpage-cli open --sandbox
drissionpage-cli open --profile=/path/to/profile
drissionpage-cli open --port=9333
drissionpage-cli close
drissionpage-cli delete-data --reset-profile
--capture (network traffic recording)
Append --capture to any interaction command to record all network traffic triggered by that action.
Supported commands: open, goto, click, dblclick, right-click, type, fill, hover, drag, select, check, uncheck.
drissionpage-cli open https://example.com --capture
drissionpage-cli goto https://example.com --capture
drissionpage-cli click "#submit" --capture
drissionpage-cli fill "css:input[name=q]" "search term" --submit --capture
drissionpage-cli hover "@id=lazy-load-trigger" --capture
Creates a timestamped folder capture-<ts>/ in the current working directory:
capture-2026-04-14T16-06-30/
snapshot.html ← page HTML after the action completes
traffic.json ← manifest: [{url, method, status, content_type, file}, ...]
0001_index.html ← each network response body as its own file
0002_styles.css
0004_logo.png
0017_hero.jpg
0063_promo.mp4
...
Saves all response types: HTML, CSS, JS, JSON, images (jpg/png/webp/gif/svg/avif/bmp/ico), audio (mp3/ogg/wav/aac/flac), video (mp4/webm/ogv/mov).
Output:
[capture] folder → /project/capture-2026-04-14T16-06-30
[capture] snapshot → snapshot.html
[capture] traffic → traffic.json (125 requests)
[capture] media → 63 files (images/audio/video)
Snapshots
After each command, drissionpage-cli provides a snapshot of the current page state.
> drissionpage-cli goto https://example.com
- Page URL: https://example.com/
- Page Title: Example Domain
[Snapshot](~/.drissionpage-cli/snapshots/page-2026-02-14T19-22-42.html)
Targeting elements
DrissionPage supports multiple locator strategies:
drissionpage-cli click "css:#main > button.submit"
drissionpage-cli click "xpath://button[@id='submit']"
drissionpage-cli click "text:Submit"
drissionpage-cli click "tag:button"
drissionpage-cli click "@id=submit"
drissionpage-cli click "@class:btn"
drissionpage-cli click "@name^=user"
drissionpage-cli click "@data-testid=login"
drissionpage-cli click "@@tag()=button@@text()=Submit"
drissionpage-cli click "@|id=btn1@id=btn2"
Browser Sessions
drissionpage-cli -s=mysession open https://example.com
drissionpage-cli -s=mysession click "#button"
drissionpage-cli -s=mysession close
drissionpage-cli list
drissionpage-cli close-all
drissionpage-cli kill-all
Running custom code
Use run-code to execute arbitrary DrissionPage Python code:
drissionpage-cli run-code "result = page.title"
drissionpage-cli run-code "page.get('https://example.com'); result = page.html[:100]"
drissionpage-cli run-code --filename=myscript.py
The page variable is the active ChromiumPage instance. Set result to output a value.
Installation
pip install drissionpage-cli
Or install skills for Claude Code:
drissionpage-cli install --skills
Specific tasks
Web Page → Markdown (md command)
The md command converts a web page to a self-contained Markdown file with
locally saved images. The URL is auto-detected to choose the right converter.
Omit the URL to convert the page currently open in the browser.
drissionpage-cli md https://<company>.feishu.cn/docx/<token>
drissionpage-cli md https://<company>.feishu.cn/wiki/<token> -o ./output
drissionpage-cli md https://www.xiaohongshu.com/explore/<note_id> -o ./output
drissionpage-cli md
drissionpage-cli md <url> --save-html
Output layout (both sites):
out_dir/
Title/
Title.md ← Markdown with local image references
images/
img_001.png
img_002.jpg
...
Supported sites
| Site | URL pattern | Converter |
|---|
| Feishu | *.feishu.cn/wiki/* or *.feishu.cn/docx/* | Network-capture: extracts block_map from SSR HTML |
| Xiaohongshu | xiaohongshu.com/explore/* | DOM extraction: reads rendered page content |
Options:
url — page URL (optional; uses current browser page if omitted)
out_dir — output directory (default: .)
--save-html — also save the raw HTML alongside the Markdown
Feishu details
Captures full network traffic on page load — the complete document block tree
is embedded in Feishu's SSR HTML as window.DATA.clientVars.data.block_map.
No scrolling or DOM scraping needed.
Supported block types
| Block | Feishu name | Markdown output |
|---|
heading1–heading9 | 标题1–9 | #–###### (H7–H9 map to H6) |
text | 正文 | paragraph |
bullet | 无序列表 | - item |
ordered | 有序列表 | 1. item |
todo | 任务列表 | - [ ] item / - [x] item |
code | 代码块 | fenced ``` block |
quote_container | 引用块 | > blockquote |
callout | 高亮块 | > highlighted text |
divider | 分隔线 | --- |
image | 图片 |  — saved locally |
file | 文件 | > 📎 [name](files/name) if captured; metadata + cover thumbnail if not |
table | 表格 | GFM pipe table |
grid / grid_column | 分栏 | columns rendered inline (no visual columns) |
bookmark | 链接 | [title](url) inline link |
synced_source | 同步块 | content rendered inline (same as regular blocks) |
whiteboard | 绘图/思维导图/流程图/UML图 |  — screenshot of rendered canvas |
page | 子页面引用 | > 📄 title |
Inline formatting
bold, italic, bold italic, code, strikethrough, links — all decoded from Quill/Etherpad attributed text.
Known limitations
| Block | Feishu name | Reason |
|---|
whiteboard | 绘图/思维导图/流程图/UML | Screenshotted via live browser (WASM renderer). Fallback if not rendered. |
equation / formula | 公式 | LaTeX math; not yet implemented |
button | 按钮 | Interactive UI element; no text equivalent |
comment | 评论/划线 | Annotation layer; not in block_map |
| Old DOC format | wikcn… wiki URLs | Different flat-text structure; not supported |
| Large docs (>239 blocks) | — | Feishu SSR caps initial payload; truncation warning added |
File attachments
Files in traffic are saved to files/. Cover thumbnails (PNG previews) are
always captured and shown as inline images. The actual file is only captured
if the browser downloaded it.
Xiaohongshu (RedNote) details
Extracts note content from the rendered DOM of a note detail page. Because
Xiaohongshu blocks direct URL navigation (anti-bot), the typical workflow is:
- Open the search page or home feed in the browser
- Click on a note card — this opens the note with valid auth tokens
- Run
drissionpage-cli md (no URL needed — uses the current page)
Extracted fields
| Field | Markdown output |
|---|
| Title | # Title heading |
| Author, location, date | > Author: … | Location: … | Date: … blockquote |
| Likes, collects, comments | appended to metadata blockquote |
| Description / body text | paragraph text with proper line breaks |
| Images |  — downloaded locally |
| Hashtags | Tags: #tag1 #tag2 … at the bottom |
Known limitations
- Direct navigation blocked: XHS requires
xsec_token in the URL, which
is only present when clicking through from search or feed. Always click into
a note rather than pasting a bare /explore/<id> URL.
- Video content: video notes include a
video_id reference but the video
file is not downloaded.
- Comments: only the note body is extracted; comments are not included.