Capture screenshots of web pages running on local or remote servers using Puppeteer in headless Chromium. Use when user asks to screenshot web pages, capture web UI, take website screenshots, or document web application interfaces. Supports login-required SPAs (Vue/React/Angular) by performing form-based authentication before navigating. Generates screenshots and an optional result.json with per-page descriptions.
Capture screenshots of web pages (especially SPA applications) with automatic login handling.
puppeteer-core (npm global)chromium-browser (/usr/bin/chromium-browser)Verify with: which chromium-browser && npm ls -g puppeteer-core
node <skill_dir>/scripts/screenshot.js <config.json>
{
"baseUrl": "http://192.168.7.66:8080",
"outputDir": "/root/screenpics/my-capture",
"resolution": [1920, 1080],
"login": {
"url": "/login",
"usernameSelector": "input[placeholder='请输入用户名']",
"passwordSelector": "input[type='password']",
"submitSelector": "button.el-button--primary",
"credentials": { "username": "admin", "password": "123456" }
},
"pages": [
{ "name": "01_dashboard", "path": "/dashboard", "waitMs": 3000 },
{ "name": "02_project_list", "path": "/project/list", "waitMs": 2000 }
],
"descriptions": {
"01_dashboard": "工作台首页,展示KPI卡片和图表。",
"02_project_list": "项目管理列表页面。"
}
}
The script handles Vue/React SPA login by:
HTMLInputElement.value setter + dispatching input events (Vue-reactive compatible)$router.push() for subsequent page navigation (avoids Pinia/Redux store reset on full page reload)| Field | Required | Description |
|---|---|---|
baseUrl | ✅ | Base URL of the web app |
outputDir | ✅ | Output directory for screenshots |
resolution | No | Viewport size [width, height], default [1920, 1080] |
login | No | Login config (skip for public pages) |
login.usernameSelector | ✅* | CSS selector for username input |
login.passwordSelector | ✅* | CSS selector for password input |
login.submitSelector | ✅* | CSS selector for submit button |
login.credentials | ✅* | { username, password } |
pages | ✅ | Array of pages to capture |
pages[].name | ✅ | Filename prefix (e.g. 01_dashboard) |
pages[].path | ✅ | URL path (e.g. /dashboard) |
pages[].waitMs | No | Extra wait in ms after navigation (default 2000) |
descriptions | No | Map of name → description text (included in result.json) |
{outputDir}/{name}.png — one PNG per page{outputDir}/result.json — metadata with filenames, titles, URLs, descriptions{
"project": "auto-generated",
"captureDate": "2026-03-22",
"baseUrl": "...",
"resolution": "1920x1080",
"screenshots": [
{
"filename": "01_dashboard.png",
"title": "Dashboard",
"url": "...",
"description": "..."
}
]
}
To include the login page as the first screenshot, add it to pages with a special flag:
{
"pages": [
{ "name": "00_login", "path": "/login", "isLoginPage": true, "waitMs": 2000 }
]
}
When isLoginPage: true, the script captures this page before performing login.
If the form-based login doesn't work (e.g., custom auth flow), use storeLogin instead:
{
"login": {
"url": "/login",
"storeLogin": {
"storeName": "user",
"method": "login",
"args": ["平台管理员"]
}
}
}
This directly calls pinia._s.get(storeName).method(...args) via CDP.
--disable-gpu (already included).storeLogin approach.login section is configured. Without login, page.goto() is used instead of $router.push().