Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Capture authenticated dashboards as screenshots and/or HTML using cookies, with safe same-origin crawling. Use when the goal is archival capture, documentation, or structured snapshotting of dashboard pages. Do not use for arbitrary interactive browsing, existing live-tab reuse, or DOM-debugging workflows; prefer agent-browser or chrome-cdp for those.
.claude/skills/valtterimelkko-capture-dashboard/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-09 | ✗→✓ | ▲ Improved | -9% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 64% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 128% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 35% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 69% | 0% |
Capture authenticated web dashboards as screenshots and HTML files using cookie-based authentication with automatic crawling.
Install the cookie-editor extension to export cookies from your browser:
Required:
npm install -g puppeteerThe capture script uses puppeteer's bundled Chromium browser.
Basic single-page screenshot capture:
bash# 1. Export cookies from your authenticated session # (Use cookie-editor extension, export as JSON, save as cookies.json) # 2. Run capture node scripts/capture.js \ --cookies cookies.json \ --url https://dashboard.example.com \ --mode screenshots
cookies.json)Important: Cookies contain sensitive authentication tokens. Never commit cookie files to version control.
For advanced usage with crawling, create a config file:
json{ "cookies": "./cookies.json", "landing_page": "https://dashboard.example.com", "output_dir": "./dashboard-capture", "mode": "both", "crawl": { "enabled": true, "max_depth": 2, "same_origin_only": true, "exclude_patterns": [ "*logout*", "*signout*", "*delete*", "*remove*", "*destroy*" ] }, "screenshot": { "full_page": true }, "timeout": 30000 }
With config file:
bashnode scripts/capture.js --config config.json
With command-line arguments:
bashnode scripts/capture.js \ --cookies cookies.json \ --url https://dashboard.example.com \ --mode both \ --output ./output
The script will:
Output structure:
output/
├── screenshots/ # PNG screenshots (full-page)
│ ├── dashboard_example_com.png
│ ├── dashboard_example_com_reports.png
│ └── dashboard_example_com_settings.png
├── html/ # HTML files
│ ├── dashboard_example_com.html
│ ├── dashboard_example_com_reports.html
│ └── dashboard_example_com_settings.html
└── metadata.json # Capture metadata and resultsmetadata.json contains:
json{ "status": "success", "pages_captured": 3, "output_directory": "/path/to/output", "capture_time": "2026-02-05T12:34:56Z", "config": { "landing_page": "https://dashboard.example.com", "mode": "both", "max_depth": 2 }, "pages": [ { "url": "https://dashboard.example.com", "depth": 0, "screenshot": { "filename": "dashboard_example_com.png", "path": "/path/to/output/screenshots/dashboard_example_com.png" }, "html": { "filename": "dashboard_example_com.html", "path": "/path/to/output/html/dashboard_example_com.html" }, "timestamp": "2026-02-05T12:34:56Z" } ] }
| Parameter | Description | Example | |-----------|-------------|---------| | cookies | Path to cookie JSON file | "./cookies.json" | | landing_page | Starting URL for capture | "https://dashboard.example.com" |
| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | output_dir | string | "./output" | Output directory path | | mode | string | "both" | Capture mode: "screenshots", "html", or "both" | | timeout | number | 30000 | Page load timeout in milliseconds |
| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | crawl.enabled | boolean | true | Enable automatic crawling | | crawl.max_depth | number | 2 | Maximum crawl depth (0 = landing page only) | | crawl.same_origin_only | boolean | true | Only follow same-origin links | | crawl.exclude_patterns | array | ["*logout*", ...] | URL patterns to exclude |
| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | screenshot.full_page | boolean | true | Capture full scrollable page | | screenshot.format | string | "png" | Screenshot format (png) |
bashnode scripts/capture.js [OPTIONS] OPTIONS: --config FILE Load configuration from JSON file --cookies FILE Path to cookie JSON file --url URL Landing page URL --mode MODE Capture mode: screenshots, html, or both --output DIR Output directory --max-depth N Maximum crawl depth --no-crawl Disable crawling --help, -h Show help message
Capture screenshots of a single dashboard page:
bashnode scripts/capture.js \ --cookies cookies.json \ --url https://dashboard.example.com \ --mode screenshots \ --no-crawl
Capture both screenshots and HTML, crawling up to 2 levels deep:
json{ "cookies": "./cookies.json", "landing_page": "https://dashboard.example.com", "mode": "both", "crawl": { "enabled": true, "max_depth": 2 } }
bashnode scripts/capture.js --config config.json
Capture HTML only for documentation purposes:
bashnode scripts/capture.js \ --cookies cookies.json \ --url https://dashboard.example.com \ --mode html \ --output ./docs/dashboard-html
Exclude additional URL patterns:
json{ "cookies": "./cookies.json", "landing_page": "https://dashboard.example.com", "crawl": { "exclude_patterns": [ "*logout*", "*delete*", "*edit*", "*admin*" ] } }
Symptom: Script reports "Authentication failed - redirected to login page"
Solutions:
See references/troubleshooting.md for detailed cookie export instructions.
Symptom: puppeteer not found error
Solution:
bashnpm install -g puppeteer
If that fails, try local installation:
bashnpm install puppeteer # Then use: node_modules/.bin/node scripts/capture.js
Symptom: Page navigation times out
Solutions:
"timeout": 60000 (60 seconds)Symptom: Only landing page captured, no crawling
Solutions:
crawl.enabled is truemax_depth is greater than 0same_origin_only: true)See detailed troubleshooting guide: references/troubleshooting.md
Cookie Expiration: Cookies expire based on server settings. If capture fails with authentication errors, re-export fresh cookies.
Same-Origin Restriction: By default, only links within the same domain are followed. This prevents accidentally crawling external sites.
Depth Limit: Maximum depth of 2 prevents excessive crawling. Depth 0 = landing page, Depth 1 = direct links, Depth 2 = links from depth 1 pages.
Safety Filters: Exclude patterns prevent the script from clicking logout, delete, or other dangerous actions. These patterns use wildcard matching (*logout* matches any URL containing "logout").
File Naming: URLs are converted to safe filenames by replacing non-alphanumeric characters with underscores. Long URLs are truncated to 200 characters.
Graceful Degradation: If a single page fails to capture, the script continues with other pages and reports partial success.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-09 | fail→pass | 17,850 | 2,542 | -86% | 1 | 1 | 0% | 3,054 | 2,792 | -9% | 0 | 0 | — |
case-01 | fail→pass | 17,394 | 11,938 | -31% | 1 | 1 | 0% | 1,985 | 3,253 | +64% | 0 | 0 | — |
case-02 | fail→pass | 7,873 | 2,452 | -69% | 1 | 1 | 0% | 1,268 | 2,886 | +128% | 0 | 0 | — |
case-03 | fail→pass | 13,707 | 4,480 | -67% | 1 | 1 | 0% | 2,389 | 3,215 | +35% | 0 | 0 | — |
case-04 | fail→pass | 8,720 | 3,164 | -64% | 1 | 1 | 0% | 1,638 | 2,761 | +69% | 0 | 0 | — |
case-05 | pass→pass | 14,976 | 2,477 | -83% | 1 | 1 | 0% | 2,621 | 2,832 | +8% | 0 | 0 | — |
case-06 | pass→pass | 9,014 | 3,989 | -56% | 1 | 1 | 0% | 1,567 | 3,162 | +102% | 0 | 0 | — |
case-07 | pass→pass | 11,604 | 2,716 | -77% | 1 | 1 | 0% | 1,967 | 2,884 | +47% | 0 | 0 | — |
case-08 | pass→pass | 7,069 | 2,659 | -62% | 1 | 1 | 0% | 1,169 | 2,772 | +137% | 0 | 0 | — |
case-10 | pass→pass | 9,563 | 2,225 | -77% | 1 | 1 | 0% | 1,642 | 2,720 | +66% | 0 | 0 | — |
case-11 | pass→pass | 12,530 | 5,091 | -59% | 1 | 1 | 0% | 2,264 | 3,442 | +52% | 0 | 0 | — |
case-12 | pass→pass | 4,421 | 1,899 | -57% | 1 | 1 | 0% | 776 | 2,641 | +240% | 0 | 0 | — |
case-13 | pass→pass | 9,666 | 11,208 | +16% | 1 | 1 | 0% | 1,745 | 3,697 | +112% | 0 | 0 | — |
case-14 | fail→pass | 12,269 | 6,360 | -48% | 1 | 1 | 0% | 2,183 | 3,521 | +61% | 0 | 0 | — |
case-15 | pass→pass | 8,864 | 1,781 | -80% | 1 | 1 | 0% | 1,794 | 2,619 | +46% | 0 | 0 | — |
case-16 | pass→pass | 8,077 | 2,206 | -73% | 1 | 1 | 0% | 1,298 | 2,740 | +111% | 0 | 0 | — |
case-17 | pass→pass | 9,210 | 4,327 | -53% | 1 | 1 | 0% | 1,478 | 3,085 | +109% | 0 | 0 | — |
case-18 | fail→pass | 20,085 | 2,047 | -90% | 1 | 1 | 0% | 3,271 | 2,723 | -17% | 0 | 0 | — |
case-19 | pass→pass | 9,305 | 2,947 | -68% | 1 | 1 | 0% | 1,417 | 2,815 | +99% | 0 | 0 | — |
case-20 | pass→pass | 10,851 | 11,557 | +7% | 1 | 1 | 0% | 2,046 | 4,523 | +121% | 0 | 0 | — |
case-21 | pass→pass | 11,640 | 11,638 | -0% | 1 | 1 | 0% | 2,250 | 4,689 | +108% | 0 | 0 | — |
case-22 | pass→pass | 7,467 | 8,254 | +11% | 1 | 1 | 0% | 1,423 | 4,000 | +181% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.