claw-code/rust/clawcode/claw/skills/chrome-devtools-mcp/SKILL.md

541 lines
19 KiB
Markdown

---
name: chrome-devtools-mcp
description: Use when browsing web pages, extracting content from restricted sites (login walls, paywalls), debugging JS errors, analyzing network requests, or running performance audits via browser DevTools.
---
# Chrome DevTools MCP — Web Browsing & Debugging Skill
Operation guide for the `chrome-devtools-mcp` toolset covering web browsing, interactive debugging, content extraction, and performance analysis.
## When to Use
Use this skill when **any** of the following apply:
1. **Browsing** — need to navigate web pages, extract content, bypass login walls/paywalls
2. **Debugging** — need to inspect console errors, network requests, DOM elements, or page performance
3. **Content extraction** — need to extract article text from restricted pages (Zhihu, CSDN, etc.)
4. **Interaction** — need to fill forms, click elements, handle dialogs on web pages
5. **Performance** — need to run Lighthouse audits, trace performance, or capture heap snapshots
## Core Workflow
```
1. new_page(url) / navigate_page(url) → Open/navigate to page
2. wait_for(["keyword"]) → Wait for content to load
3. take_snapshot() → Get element structure (uid)
4. take_screenshot() → Confirm visual state
5. evaluate_script(() => ...) → Execute JS / extract data
6. list_console_messages() → Check console errors
```
## Key Capabilities
- **Bypass restrictions**: Remove login/paywall overlays, unlock copy restrictions, expand truncated articles
- **Debug JS errors**: List and inspect console messages, identify uncaught exceptions
- **Network analysis**: List network requests, inspect request/response bodies
- **DOM interaction**: Click, fill, type, hover, drag — all via accessibility tree (uid)
- **Performance**: Lighthouse audits, performance traces, memory heap snapshots
- **Device emulation**: Mobile viewport, user agent switching
---
# Part 1 — Browsing & Restriction Bypass
Based on `chrome-devtools-mcp` toolset for bypassing login walls, copy restrictions, and paywall overlays on sites like Zhihu, CSDN.
## Standard Browsing Flow
```
Step 1: new_page(url) → Open page
Step 2: wait_for(["keyword"]) → Wait for content load
Step 3: take_snapshot() → Get accessibility tree (text structure)
Step 4: take_screenshot() → Confirm visual state (optional)
Step 5: evaluate_script() → Extract specific data
```
## Restriction Bypass Guide
### 0. Standard Detect-Remove-Extract Pattern
```javascript
// Step 1: Detect
evaluate_script(() => {
JSON.stringify({
hasMask: !!document.querySelector('[class*="mask"], [class*="overlay"], [class*="passport"]'),
hasReadMore: !!document.querySelector('.btn-readmore, [class*="readmore"], [class*="expand"]'),
articleLen: document.querySelector('article')?.innerText.length || 0,
title: document.title
})
})
// Step 2: Remove mask
evaluate_script(() => {
document.querySelectorAll('[class*="mask"], [class*="overlay"], [class*="passport"], [class*="login"], [class*="modal"], .hide-article-box')
.forEach(el => el.remove());
document.body.style.overflow = 'auto';
document.body.style.position = '';
const a = document.querySelector('article');
if (a) { a.style.height = 'auto'; a.style.maxHeight = 'none'; }
})
// Step 3: Extract content
evaluate_script(() => {
const a = document.querySelector('article') || document.querySelector('[class*="content"]') || document.querySelector('[class*="article"]');
return a?.innerText || 'not found';
})
```
### 1. Bypass Login Wall / Paywall Overlay
```javascript
// Remove overlay elements
evaluate_script(() => {
document.querySelectorAll('.login-guard, .pay-wall, .modal-mask, [class*="mask"], [class*="overlay"]')
.forEach(el => el.remove());
})
```
```javascript
// Remove body scroll lock and show content
evaluate_script(() => {
document.body.style.overflow = 'auto';
document.querySelectorAll('.login-guard, .pay-wall, .sign-in, .modal, .overlay')
.forEach(el => el.remove());
// Restore hidden content
document.querySelectorAll('[class*="content"], [class*="article"], [class*="main"]')
.forEach(el => el.style.display = 'block');
})
```
### 2. Unlock Copy Restrictions
```javascript
evaluate_script(() => {
document.addEventListener('copy', e => e.stopPropagation(), true);
document.addEventListener('selectstart', e => e.stopPropagation(), true);
document.body.style.userSelect = 'auto';
document.querySelectorAll('*').forEach(el => el.style.userSelect = 'auto');
})
```
### 3. Extract Truncated Full Text
```javascript
// Standard flow: detect → remove mask → extract
evaluate_script(() => {
const hasMask = !!document.querySelector('[class*="mask"], [class*="overlay"], [class*="passport"]');
const hasReadMore = !!document.querySelector('.btn-readmore, [class*="readmore"], [class*="expand"]');
return JSON.stringify({hasMask, hasReadMore, articleLen: document.querySelector('article')?.innerText.length || 0});
})
// If read-more button exists, click it first
evaluate_script(() => {
const btn = [...document.querySelectorAll('button, a, span, div')]
.find(el => el.textContent.includes('展开阅读全文') || el.textContent.includes('全文'));
btn?.click();
})
```
```javascript
// Zhihu — expand full text
evaluate_script(() => {
const btn = [...document.querySelectorAll('button, a, span')]
.find(el => el.textContent.includes('展开阅读全文') || el.textContent.includes('全文'));
if (btn) btn.click();
})
```
```javascript
// CSDN — remove login overlay + extract full text (verified 2026)
evaluate_script(() => {
document.querySelectorAll('.mask, .mask-dark, .passport-login-tip-container, .passport-login-container, .passport-login-box, .passport-login-mark, .hide-article-box')
.forEach(el => el.remove());
document.body.style.overflow = 'auto';
document.body.style.position = '';
const article = document.querySelector('article') || document.querySelector('.article_content');
if (article) {
article.style.setProperty('height', 'auto', 'important');
article.style.setProperty('max-height', 'none', 'important');
}
})
// Extract content
evaluate_script(() => {
const art = document.querySelector('article') || document.querySelector('.article_content') || document.querySelector('#article_content');
return 'Title: ' + document.title + '\n\n' + art.innerText;
})
```
### 4. Extract Page Text
```javascript
// Get article plain text
evaluate_script(() => {
const article = document.querySelector('article') ||
document.querySelector('[class*="content"]') ||
document.querySelector('[class*="article"]') ||
document.querySelector('main');
return article ? article.innerText : document.body.innerText;
})
```
```javascript
// Get all page text (preserving structure)
evaluate_script(() => {
return [...document.querySelectorAll('h1, h2, h3, p, li, pre, code')]
.map(el => el.tagName + ': ' + el.innerText.trim())
.filter(s => s.length > 3)
.join('\n---\n');
})
```
### 5. Zhihu-Specific Bypass
```javascript
evaluate_script(() => {
// Close dialog
document.querySelector('.Modal-closeButton, button[class*="close"]')?.click();
document.querySelector('[class*="signIn"], [class*="Modal"]')?.remove();
// Expand all collapsed answers
document.querySelectorAll('.RichContent.is-collapsed').forEach(el => {
el.classList.remove('is-collapsed');
el.style.height = 'auto';
el.style.maxHeight = 'none';
el.style.overflow = 'visible';
});
document.body.style.overflow = 'auto';
})
```
### 6. WeChat Public Account Articles (Sogou Gateway)
WeChat public account articles are normally login-gated in browsers, but Sogou WeChat Search (the official content index) allows direct access.
```javascript
// Step 1: Search for articles
navigate_page('https://weixin.sogou.com/weixin?type=2&s_from=input&query=' + encodeURIComponent('search keyword'))
// Step 2: Get result list
evaluate_script(() => {
const items = [...document.querySelectorAll('.news-list2 .wx-rb, .news-list2 li')].filter(el => el.querySelector('h3 a'));
return items.slice(0, 10).map(el => ({
title: el.querySelector('h3 a')?.textContent?.trim(),
link: el.querySelector('h3 a')?.href,
source: el.querySelector('.account')?.textContent?.trim(),
date: el.querySelector('.time')?.textContent?.trim(),
summary: el.querySelector('.txt-info')?.textContent?.trim()?.slice(0, 80)
}));
})
// Step 3: Open article link (no login required)
navigate_page('result-link')
// Step 4: Extract content
evaluate_script(() => document.body.innerText)
```
**Verified (2026):** Sogou WeChat Search for `chrome devtools` returns 634 results. Opening the link gives full 2856-character article with no restrictions.
### 7. Mobile Emulation (some sites have fewer restrictions on mobile)
```javascript
emulate({
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
viewport: '375x667x2,mobile,touch'
})
```
## Quick Command Reference
| Operation | Tool | Description |
|-----------|------|-------------|
| Open page | `new_page(url)` | Open in new tab |
| Navigate | `navigate_page(url)` | Navigate current tab |
| Wait for content | `wait_for(["text"])` | Wait for text to appear |
| Screenshot | `take_screenshot()` | Full-page screenshot |
| DOM snapshot | `take_snapshot()` | Accessibility tree text structure |
| Execute JS | `evaluate_script(fn)` | Arbitrary JS operations |
| JS with args | `evaluate_script(fn, args)` | Execute with parameters |
| Extract content | `evaluate_script(() => document.body.innerText)` | Plain text extraction |
| Remove element | `evaluate_script(() => el.remove())` | Remove overlay/popup |
| Click element | `click(uid)` | Click by snapshot uid |
| Emulate device | `emulate({userAgent, viewport})` | Switch UA/viewport |
| Scroll | `press_key({key: "Space"})` | Simulate key press |
## FAQ (Practical Experience)
### 1. Popup class names don't match?
First inspect the actual overlay elements:
```javascript
evaluate_script(() => {
[...document.querySelectorAll('div[style*="fixed"], div[style*="absolute"], [class*="overlay"], [class*="modal"], [class*="mask"], [class*="popup"]')]
.map(el => ({tag: el.tagName, cls: el.className.slice(0,80), visible: el.offsetParent !== null}))
})
```
### 2. How to tell if content is complete or truncated?
```javascript
evaluate_script(() => {
const a = document.querySelector('article') || document.querySelector('.Post-RichText');
const ratio = a.scrollHeight / a.clientHeight;
JSON.stringify({
textLen: a.innerText.length,
scrollH: a.scrollHeight, clientH: a.clientHeight,
ratio: ratio.toFixed(2), // > 1.2 means overflow hidden
endText: a.innerText.slice(-100)
})
})
```
If it ends with `-- The End --`, copyright notice, or a natural ending, it's complete.
### 3. CSDN overlay class names (verified 2026)
| CSDN Class | Description |
|------------|-------------|
| `.mask` + `.mask-dark` | Background overlay |
| `.passport-login-tip-container` | Login prompt bar |
| `.passport-login-container` | Login dialog container |
| `.passport-login-box` / `.passport-login-mark` | Login box and overlay |
| `.hide-article-box` | Article collapse bar |
### 4. Zhihu overlay class names (verified 2026)
| Zhihu Class | Description |
|-------------|-------------|
| `.Modal.Modal--default.signFlowModal` | Login dialog |
| `.signFlowModal-container` | Login container |
| Content selector: `.Post-RichText` or `.RichText` | |
### 5. Short article vs truncated article
- Some articles are genuinely short (many images/code, few words) — e.g., 2081 chars but scrollHeight = 8550px
- Verification: check end for natural termination, or confirm via `document.title`
- Zhihu columns without login may redirect to search page — check `location.href`
### 6. What can vs cannot be bypassed
| Type | Principle | Bypassable? | Example |
|------|-----------|-------------|---------|
| DOM overlay | Content in DOM, hidden behind a div | Yes — just remove it | CSDN, Zhihu columns |
| Lazy load | Content loaded on scroll | Yes — trigger scroll | Most comment sections |
| API auth | Content fetched via cookie-authenticated API | No — no cookie = no data | Bilibili comments, Weibo |
| SSR hidden | Server-rendered but hidden via class | Yes — change style | Juejin paid articles |
### 7. Chrome restart / disconnect handling
MCP mode manages browser lifecycle automatically. CLI mode:
```bash
chrome-devtools stop # Stop background process
chrome-devtools status # Check status
```
---
# Part 2 — Debugging Guide
Based on `chrome-devtools-mcp` toolset for debugging web pages, inspecting errors, and analyzing performance.
## Tool Overview
```
Category Tool Purpose
────── ─── ───
Navigation new_page / navigate_page Open/navigate pages
close_page / select_page Close/switch tabs
list_pages List all tabs
wait_for Wait for text
Debugging evaluate_script Execute JS in page
take_snapshot Get accessibility tree (uid)
take_screenshot Screenshot
list_console_messages List console logs
get_console_message(msgid) View specific log details
lighthouse_audit Lighthouse audit
Interaction click(uid) Click element
fill(uid, value) Fill input field
fill_form([{uid,value}]) Batch form fill
type_text(text) Keyboard input
press_key(key) Key press (Enter/Tab/Ctrl+A)
hover(uid) Hover
drag(from_uid, to_uid) Drag
handle_dialog(action) Handle browser dialogs
upload_file(path, uid) Upload file
Network list_network_requests List network requests
get_network_request(reqid) View request details/response
Performance performance_start_trace Start performance recording
performance_stop_trace Stop + analyze
performance_analyze_insight Analyze specific metric
take_memory_snapshot Heap snapshot
Emulation emulate({userAgent, viewport}) Simulate device
resize_page(width, height) Resize window
```
## Standard Debugging Flows
### Flow 1: JS Error Investigation
```
1. navigate_page(url) → Enter page
2. list_console_messages() → View errors
3. get_console_message(msgid) → View error details
4. evaluate_script(() => { /* fix */ }) → Fix the issue
5. verify
```
### Flow 2: Network Request Analysis
```
1. navigate_page(url) → Load page
2. list_network_requests() → List all requests
3. get_network_request(reqid) → View request/response body
4. Identify 404s, CORS errors, slow requests
```
### Flow 3: DOM / Style Debugging
```
1. take_snapshot() → Get element structure (with uid)
2. click(uid) / fill(uid, value) → Interact
3. evaluate_script(() => getComputedStyle(el)) → Check styles
4. evaluate_script(() => { el.style.color = 'red' }) → Temporary modification
5. take_screenshot() → Confirm visually
```
### Flow 4: Performance Analysis
```
1. performance_start_trace({reload: true}) → Start recording + reload
2. (wait for page to load)
3. performance_stop_trace() → Stop and analyze
4. performance_analyze_insight({insightName, insightSetId}) → Deep dive
```
## Debugging Quick Reference
### Console
```javascript
// View all console messages
list_console_messages({includePreservedMessages: true})
// View specific message
get_console_message({msgid: 0})
```
### Element Inspection
```javascript
// Get interactive elements list (with uid)
take_snapshot()
// Verbose version (more properties)
take_snapshot({verbose: true})
// Inspect element styles
evaluate_script(() => {
const el = document.querySelector('h1');
return getComputedStyle(el);
})
// Get element dimensions / position
evaluate_script(() => {
const el = document.querySelector('h1');
return el.getBoundingClientRect();
})
```
### Page Interaction
```javascript
// Click (get uid via take_snapshot first)
click({uid: "element-123"})
// Fill input
fill({uid: "input-456", value: "search text"})
// Fill + Enter
fill({uid: "input-456", value: "search text"})
press_key({key: "Enter"})
// Keyboard shortcuts
press_key({key: "Control+A"})
press_key({key: "Control+C"})
// Handle browser dialogs (alert/confirm)
handle_dialog({action: "accept"})
handle_dialog({action: "dismiss"})
```
### Network
```javascript
// View all network requests
list_network_requests({pageSize: 50, resourceTypes: ["XHR", "Fetch", "Document"]})
// View request details
get_network_request({reqid: 0})
// Save response body to file
get_network_request({reqid: 0, responseFilePath: "response.json"})
```
### Memory Debugging
```javascript
// Capture heap snapshot (for memory leak analysis)
take_memory_snapshot({filePath: "heap.heapsnapshot"})
```
### Lighthouse Audit
```javascript
// Accessibility + SEO + Best Practices
lighthouse_audit({device: "desktop"})
lighthouse_audit({device: "mobile"})
lighthouse_audit({mode: "snapshot"}) // No reload, analyze current state
```
## Typical Scenarios
### Scenario A: White Screen / JS Error Fix
```
1. list_console_messages() → Check for JS errors
2. get_console_message(0) → View first error details
3. evaluate_script(() => { ... }) → Temporary fix in page
4. Fix in source code, reload, verify
```
### Scenario B: API Endpoint Debugging
```
1. navigate_page('https://example.com')
2. list_network_requests({resourceTypes: ["XHR", "Fetch"]}) → Filter API calls
3. get_network_request(0) → View request params + response data
```
### Scenario C: Form Submission Verification
```
1. take_snapshot() → Get form element uids
2. fill({uid, value}) → Fill each field
3. click({uid}) → Click submit button
4. list_network_requests() → Check if request was sent
5. list_console_messages() → Check for errors
```
### Scenario D: Responsive Layout Debugging
```
1. emulate({viewport: '375x667x2,mobile,touch'}) → Switch to mobile
2. take_screenshot() → Screenshot for review
3. emulate({viewport: '1280x720'}) → Switch back to desktop
4. take_screenshot() → Compare results
```