Loading...
Loading...
Use Chrome DevTools MCP to obtain and analyze web page data. This skill is used when users need to crawl web content, analyze web page structure, extract data, take screenshots, monitor network requests, or perform web automation tasks.
npx skill4agent add steelan9199/wechat-publisher chrome-devtools-skillstart chrome --remote-debugging-port=9222 --user-data-dir="%TEMP%\chrome-devtools-profile" [URL]Important Note: Use a fixed(e.g.,--user-data-dir) instead of a different folder each time. This way Chrome will remember login states, cookies, and cache, making subsequent starts faster.chrome-devtools-profile
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir="$TMPDIR/chrome-profile-stable" [URL]google-chrome --remote-debugging-port=9222 --user-data-dir="/tmp/chrome-profile-stable" [URL]npx -y chrome-devtools-mcp@latest --browser-url=http://127.0.0.1:9222mcp__chrome-devtools__navigate_pagemcp__chrome-devtools__wait_formcp__chrome-devtools__take_snapshotmcp__chrome-devtools__evaluate_scriptmcp__chrome-devtools__screenshotmcp__chrome-devtools__list_network_requests1. Start Chrome (in debugging mode)
2. Start MCP server
3. Navigate to the target URL
4. Wait for page loading
5. Perform the operation requested by the user (screenshot/data extraction/network monitoring, etc.)
6. Return results to the user() => {
const items = document.querySelectorAll(".item");
return Array.from(items).map((item) => ({
title: item.querySelector(".title")?.innerText,
link: item.querySelector("a")?.href,
}));
};() => {
const rows = document.querySelectorAll("table tr");
return Array.from(rows).map((row) =>
Array.from(row.querySelectorAll("td, th")).map((cell) => cell.innerText)
);
};--user-data-dirtake_snapshotevaluate_scriptwait_for| Method | Protocol | Usage |
|---|---|---|
| HTTP | | Get page list and basic information |
| WebSocket | | Real-time page control and script execution |
import asyncio
import websockets
import json
async def cdp_example():
# 1. Connect to Chrome DevTools WebSocket
ws_url = "ws://127.0.0.1:9222/devtools/page/{pageId}"
async with websockets.connect(ws_url) as ws:
# 2. Enable Runtime domain
await ws.send(json.dumps({
"id": 1,
"method": "Runtime.enable"
}))
# 3. Execute JavaScript
await ws.send(json.dumps({
"id": 2,
"method": "Runtime.evaluate",
"params": {
"expression": "document.title",
"returnByValue": True
}
}))
# 4. Loop to receive responses and match id
while True:
msg = await ws.recv()
data = json.loads(msg)
if data.get('id') == 2: # Match request id
return data['result']['result']['value']consoleAPICalledexecutionContextCreatedidawait asyncio.sleep(2)sys.stdout.reconfigure(encoding='utf-8')UnicodeEncodeError: 'gbk' codec can't encode characterimport sys
sys.stdout.reconfigure(encoding='utf-8')baidu_search_example.pycdp_helper.py=>=>import codecs
decoded = codecs.decode(string, 'unicode_escape')curl -s http://127.0.0.1:9222/json/listwebSocketDebuggerUrlimport urllib.request
import json
def get_ws_url():
req = urllib.request.Request('http://127.0.0.1:9222/json/list')
with urllib.request.urlopen(req) as response:
pages = json.loads(response.read().decode())
return pages[0]['webSocketDebuggerUrl'] if pages else Nonetimeout /t 3 /nobreakinvalid time intervaltimeout# Windows CMD
timeout /t 3 /nobreak >nul
# Git Bash / Linux
sleep 3
# Cross-platform universal (Windows)
ping -n 4 127.0.0.1 > nulechocatconst abstract = item.querySelector('.c-abstract, .abstract, [class*="abstract"]')?.innerText;window.scrollTo(0, document.body.scrollHeight);# Directly set the value of the input box (users cannot see the input process)
await ws.send(json.dumps({
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').value = '美女';"
}
}))# 1. First focus on the input box
await ws.send(json.dumps({
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').focus();"
}
}))
# 2. Simulate keyboard input (users can see character-by-character input)
for char in "美女":
await ws.send(json.dumps({
"method": "Input.dispatchKeyEvent",
"params": {
"type": "char",
"text": char
}
}))
await asyncio.sleep(0.1) # Simulate real typing interval
# 3. Simulate clicking the search button (users can see the click effect)
await ws.send(json.dumps({
"method": "Input.dispatchMouseEvent",
"params": {
"type": "mousePressed",
"x": 100,
"y": 200,
"button": "left"
}
}))| Scenario | Recommended Mode | Reason |
|---|---|---|
| Data crawling | Background | Fast, no visualization required |
| Automated testing | Background | Stable and reliable, not affected by UI |
| Search tasks | Background | Directly constructing URLs is simpler and more reliable |
| Operation demonstration | Foreground | Users can see the complete process |
| Teaching demonstration | Foreground | Easy to observe and understand |
| Form filling | Either | Background is faster, foreground is more intuitive |
https://www.baidu.com/s?wd=keyword| Solution | Implementation | Advantages | Disadvantages | Recommendation |
|---|---|---|---|---|
| A | Directly access the search URL in the background | Simple, fast, stable | Users cannot see the process | ⭐⭐⭐⭐⭐ |
| B | Simulate input and click in the foreground | Visual, with feedback | Complex, slow, need to handle coordinates | ⭐⭐⭐ |
# Directly construct the search URL in one step
url = f"https://www.baidu.com/s?wd={urllib.parse.quote(keyword)}"
await client.navigate(url)
await asyncio.sleep(3) # Wait for loading
results = await client.evaluate(extract_script)focus()Input.enable# Step 1: Enable Input domain (must be enabled first to send keyboard events)
await ws.send(json.dumps({
"id": 1,
"method": "Input.enable"
}))
# Step 2: Focus on the input box (key step, otherwise keyboard events may be invalid)
await ws.send(json.dumps({
"id": 2,
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').focus();", # '#kw' is the ID of Baidu's search box
"returnByValue": True
}
}))
await asyncio.sleep(0.5) # Wait for focusing to complete
# Step 3: Clear the input box (optional, ensure it is empty)
await ws.send(json.dumps({
"id": 3,
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').value = '';",
"returnByValue": True
}
}))
# Step 4: Input text character by character (users can see the typing animation)
text = "hello 你好呀"
for i, char in enumerate(text):
await ws.send(json.dumps({
"id": 10 + i,
"method": "Input.dispatchKeyEvent",
"params": {
"type": "char", # For inputting ordinary characters
"text": char # Character to input
}
}))
await asyncio.sleep(0.15) # Typing interval, allowing users to see the animationtype: "char"focus()# 1. Fill in search term
await ws.send(json.dumps({
"id": 2,
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').value = '搜索词';",
"returnByValue": True
}
}))
# 2. Click search button
await ws.send(json.dumps({
"id": 3,
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#su').click();",
"returnByValue": True
}
}))
# 3. Wait for loading
await asyncio.sleep(3)
# 4. Extract results
await ws.send(json.dumps({
"id": 4,
"method": "Runtime.evaluate",
"params": {
"expression": """
(() => {
const items = document.querySelectorAll('.result');
return Array.from(items).map(item => ({
title: item.querySelector('h3')?.innerText,
link: item.querySelector('a')?.href
}));
})()
""",
"returnByValue": True
}
}))/chrome-devtools-skillOpen https://www.example.com and take a screenshotCrawl the content of https://www.example.comAnalyze this web page: https://github.com/xxx/xxxOpen https://www.jd.com and extract all product titles and prices on the homepageVisit https://www.zhihu.com/explore and get the list of popular questionsCrawl all links on https://www.example.comOpen https://www.example.com and monitor all API requests loaded by the pageAnalyze the page performance of https://www.example.comVisit https://www.example.com and extract all image URLs on the pageOpen https://www.example.com, enter "keyword" in the search box and searchVisit https://www.example.com, click the "Load More" button, and crawl all list datascripts/baidu_search_example.pycdp_helper.pyREADME.mdchrome-devtools MCP{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"chrome-devtools-mcp@latest",
"--browser-url=http://127.0.0.1:9222"
]
}
}
}