New: Earn 20% as an AgentAlley affiliate. Share your link and earn on every sale you refer. Join now New: Earn 20% as an affiliate. Join now

Capture a full-page screenshot, long screenshot

by alirezarezvani · MIT license · ★ 26,349 on GitHub · updated Aug 30

Full page screenshot cover

Use when the user asks to capture a full-page screenshot, long screenshot, or complete page capture of a web page. Handles SPA scroll containers, lazy-loaded images, and very tall pages via Chrome DevTools Protocol with zero external…

---
name: "full-page-screenshot"
description: "Use when the user asks to capture a full-page screenshot, long screenshot, or complete page capture of a web page. Handles SPA scroll containers, lazy-loaded images, and very tall pages via Chrome DevTools Protocol with zero external dependencies."
---

# Full Page Screenshot

Capture a full-page screenshot of any web page via Chrome DevTools Protocol. Produces a single PNG that includes all content — even portions that require scrolling. Zero external dependencies beyond Node.js 22+ and Chrome with remote debugging enabled.

## Prerequisites

- **Node.js 22+** (uses built-in `WebSocket`)
- **Chrome/Chromium** with remote debugging enabled

Check environment readiness:

```bash
node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --check

Overview

Capture a full-page screenshot of any web page via Chrome DevTools Protocol. Produces a single PNG that includes all content — even portions that require scrolling. Zero external dependencies beyond Node.js 22+ and Chrome with remote debugging enabled.

Manual install (npx, ZIP)
Claude Codenpx skills add alirezarezvani/claude-skills --skill full-page-screenshot -g -a claude-code
Claude Code (manual)mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/alirezarezvani/claude-skills/tar.gz/19392f7a0826 \ | tar -xz -C ~/.claude/skills --strip-components=3 claude-skills-19392f7a0826/engineering/skills/full-page-screenshot
Windows (PowerShell)New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/11bc86fab1e746fbd969/full-page-screenshot.zip" -OutFile "$env:TEMP\full-page-screenshot.zip"; Expand-Archive "$env:TEMP\full-page-screenshot.zip" -DestinationPath "$HOME\.claude\skills" -Force
Claude.ai / desktopDownload the ZIP and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md5.4 KB
  • scripts/1 file · 35.1 KB
Read the files here
alirezarezvani/19392f72 files
Shared references2SKILL.md reads these from elsewhere in the repo. Not in the ZIP.Get them on GitHub ↗
SKILL.md
Show the full text124 lines

Full Page Screenshot

Capture a full-page screenshot of any web page via Chrome DevTools Protocol. Produces a single PNG that includes all content — even portions that require scrolling. Zero external dependencies beyond Node.js 22+ and Chrome with remote debugging enabled.

Prerequisites

  • Node.js 22+ (uses built-in WebSocket)
  • Chrome/Chromium with remote debugging enabled

Check environment readiness:

node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --check

If Chrome check fails, instruct user to open chrome://inspect/#remote-debugging and enable "Allow remote debugging for this browser instance".

Workflow

  1. List available tabs:
node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --list
  1. Identify the target by title/URL, then capture:
node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" <targetId> /tmp/screenshot.png --width 1200 --dpr 1
Option B: Screenshot a URL (opens a background tab, captures, closes)
node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --url "https://example.com" /tmp/screenshot.png --width 1200 --dpr 1 --wait 15000

Note: --url mode creates a background tab. Pages requiring authentication (SSO, login walls) should use Option A instead.

Parameters
Parameter Description Default
output Output PNG file path /tmp/screenshot.png
--width Viewport width in CSS pixels (articles: 1200, dashboards: 1440-1920) 1200
--dpr Device pixel ratio (2 = Retina, but 4x file size) 1
--wait Page load timeout in ms (--url mode only) 15000
--css Custom CSS to inject before capture (e.g., hide elements) —
Verify Output
# macOS
sips -g pixelWidth -g pixelHeight /tmp/screenshot.png

# Linux
file /tmp/screenshot.png

Core Capabilities

  1. SPA scroll container expansion — Detects overflow-y: auto/scroll containers, scrolls through them to trigger lazy-loading, then removes overflow constraints (including Tailwind h-[calc(...)]) so all content renders in a single pass.

  2. DOM stability detection — After readyState=complete, monitors DOM element count until it stabilizes. This ensures SPA frameworks finish rendering dynamic content.

  3. Lazy-load triggering — Scrolls the viewport incrementally to fire IntersectionObserver callbacks, then waits for all <img> elements to complete loading.

  4. Tiled capture for very tall pages — Pages exceeding 16,000px are captured in 8,000px tiles and automatically stitched using Python PIL. Falls back to saving tiles separately if PIL is unavailable.

  5. Auto-discovery of Chrome — Reads DevToolsActivePort file to find the debugging port. Falls back to probing ports 9222, 9229, 9333.

  6. CDP Proxy fallback — When a CDP proxy holds the browser WebSocket, the script falls back to proxy API endpoints (/eval, /screenshot, /scroll) for capture.

How It Works

1. Discover Chrome debugging port
2. Connect via WebSocket (CDP)
3. Attach to target / create background tab
4. Set viewport width via Emulation domain
5. Wait: readyState + DOM stability
6. Detect & expand scroll containers
7. Scroll through page (trigger lazy-load)
8. Wait for images to complete
9. Measure final content height
10. Page.captureScreenshot (or tiled capture)
11. Stitch tiles if needed (PIL)
12. Restore viewport, detach, clean up

Anti-Patterns

Do NOT Do instead
Use --dpr 2 on pages > 10,000px tall Use --dpr 1 to avoid Chrome memory issues
Use --url for authenticated/SSO pages Use --list + targetId on a tab where user is logged in
Set --wait below 5000 for SPAs SPAs need time to fetch data and render; use 10000-15000
Capture without checking --check first Always verify Chrome debugging is available
Hardcode viewport widths for all pages Use 1200 for articles, 1440+ for dashboards/tables
Skip output verification Always verify with sips or file command after capture

Troubleshooting

Symptom Cause Fix
"Cannot find Chrome debugging port" Remote debugging not enabled Open chrome://inspect/#remote-debugging, enable it
"WebSocket connection timeout" CDP proxy holding the connection Script auto-falls back to proxy API
Blank/white screenshot Page not loaded yet Increase --wait value
Truncated at bottom Scroll container not expanded Script handles this automatically; file an issue if it persists
Out of memory Very tall page + high DPR Reduce --dpr to 1 and/or reduce --width
"PIL not available for stitching" Python Pillow not installed Install with pip3 install Pillow or accept separate tile files

Cross-References

1---
2name: "full-page-screenshot"
3description: "Use when the user asks to capture a full-page screenshot, long screenshot, or complete page capture of a web page. Handles SPA scroll containers, lazy-loaded images, and very tall pages via Chrome DevTools Protocol with zero external dependencies."
4---
5 
6# Full Page Screenshot
7 
8Capture a full-page screenshot of any web page via Chrome DevTools Protocol. Produces a single PNG that includes all content — even portions that require scrolling. Zero external dependencies beyond Node.js 22+ and Chrome with remote debugging enabled.
9 
10## Prerequisites
11 
12- **Node.js 22+** (uses built-in `WebSocket`)
13- **Chrome/Chromium** with remote debugging enabled
14 
15Check environment readiness:
16 
17```bash
18node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --check
19```
20 
21If Chrome check fails, instruct user to open `chrome://inspect/#remote-debugging` and enable **"Allow remote debugging for this browser instance"**.
22 
23## Workflow
24 
25### Option A: Screenshot an already-open tab (recommended for authenticated pages)
26 
271. List available tabs:
28 
29```bash
30node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --list
31```
32 
332. Identify the target by title/URL, then capture:
34 
35```bash
36node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" <targetId> /tmp/screenshot.png --width 1200 --dpr 1
37```
38 
39### Option B: Screenshot a URL (opens a background tab, captures, closes)
40 
41```bash
42node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --url "https://example.com" /tmp/screenshot.png --width 1200 --dpr 1 --wait 15000
43```
44 
45> **Note:** `--url` mode creates a background tab. Pages requiring authentication (SSO, login walls) should use Option A instead.
46 
47### Parameters
48 
49| Parameter | Description | Default |
50|-----------|-------------|---------|
51| `output` | Output PNG file path | `/tmp/screenshot.png` |
52| `--width` | Viewport width in CSS pixels (articles: 1200, dashboards: 1440-1920) | 1200 |
53| `--dpr` | Device pixel ratio (2 = Retina, but 4x file size) | 1 |
54| `--wait` | Page load timeout in ms (`--url` mode only) | 15000 |
55| `--css` | Custom CSS to inject before capture (e.g., hide elements) | — |
56 
57### Verify Output
58 
59```bash
60# macOS
61sips -g pixelWidth -g pixelHeight /tmp/screenshot.png
62 
63# Linux
64file /tmp/screenshot.png
65```
66 
67## Core Capabilities
68 
691. **SPA scroll container expansion** — Detects `overflow-y: auto/scroll` containers, scrolls through them to trigger lazy-loading, then removes overflow constraints (including Tailwind `h-[calc(...)]`) so all content renders in a single pass.
70 
712. **DOM stability detection** — After `readyState=complete`, monitors DOM element count until it stabilizes. This ensures SPA frameworks finish rendering dynamic content.
72 
733. **Lazy-load triggering** — Scrolls the viewport incrementally to fire `IntersectionObserver` callbacks, then waits for all `<img>` elements to complete loading.
74 
754. **Tiled capture for very tall pages** — Pages exceeding 16,000px are captured in 8,000px tiles and automatically stitched using Python PIL. Falls back to saving tiles separately if PIL is unavailable.
76 
775. **Auto-discovery of Chrome** — Reads `DevToolsActivePort` file to find the debugging port. Falls back to probing ports 9222, 9229, 9333.
78 
796. **CDP Proxy fallback** — When a CDP proxy holds the browser WebSocket, the script falls back to proxy API endpoints (`/eval`, `/screenshot`, `/scroll`) for capture.
80 
81## How It Works
82 
83```
841. Discover Chrome debugging port
852. Connect via WebSocket (CDP)
863. Attach to target / create background tab
874. Set viewport width via Emulation domain
885. Wait: readyState + DOM stability
896. Detect & expand scroll containers
907. Scroll through page (trigger lazy-load)
918. Wait for images to complete
929. Measure final content height
9310. Page.captureScreenshot (or tiled capture)
9411. Stitch tiles if needed (PIL)
9512. Restore viewport, detach, clean up
96```
97 
98## Anti-Patterns
99 
100| Do NOT | Do instead |
101|--------|-----------|
102| Use `--dpr 2` on pages > 10,000px tall | Use `--dpr 1` to avoid Chrome memory issues |
103| Use `--url` for authenticated/SSO pages | Use `--list` + targetId on a tab where user is logged in |
104| Set `--wait` below 5000 for SPAs | SPAs need time to fetch data and render; use 10000-15000 |
105| Capture without checking `--check` first | Always verify Chrome debugging is available |
106| Hardcode viewport widths for all pages | Use 1200 for articles, 1440+ for dashboards/tables |
107| Skip output verification | Always verify with `sips` or `file` command after capture |
108 
109## Troubleshooting
110 
111| Symptom | Cause | Fix |
112|---------|-------|-----|
113| "Cannot find Chrome debugging port" | Remote debugging not enabled | Open `chrome://inspect/#remote-debugging`, enable it |
114| "WebSocket connection timeout" | CDP proxy holding the connection | Script auto-falls back to proxy API |
115| Blank/white screenshot | Page not loaded yet | Increase `--wait` value |
116| Truncated at bottom | Scroll container not expanded | Script handles this automatically; file an issue if it persists |
117| Out of memory | Very tall page + high DPR | Reduce `--dpr` to 1 and/or reduce `--width` |
118| "PIL not available for stitching" | Python Pillow not installed | Install with `pip3 install Pillow` or accept separate tile files |
119 
120## Cross-References
121 
122- [`engineering/browser-automation`](../browser-automation/SKILL.md) — General browser automation patterns via CDP/Playwright
123- [`engineering/performance-profiler`](../performance-profiler/SKILL.md) — Performance analysis that may complement visual captures
124 
View all files on GitHub →

Details

Updated
Aug 30, 2026
License
MIT
Stars on the repo
★ 26,349
Checked
Source
alirezarezvani/claude-skills ↗
Creator
alirezarezvani · 363 listings
View creator

Similar skills

See all →
SkillExtract text, tables, metadataXberg Document Extractionxberg-io/xberg · by xberg-ioExtract text, tables, metadata, and images from 107 document formats (PDF, Office, images, HTML, email, archives, academic) using Xberg. Use when writing code that calls Xberg APIs in Python, Node.js/TypeScript, Rust, or CLI. Covers installation, extraction (sync/async), configuration (OCR, chunking, output format), batch processing, error handling, and plugins.★ 9.4k GitHub starsSkillMove code from one implementation to another functionCode migrationkucherenko/jscpd · by kucherenkoMove code from one implementation to another function by function, tests first and code second, and check two implementations of one app for parity, with jscpd --compare as the progress measure and a coverage map binding each function to its tests. Use when porting a library or app to another language or framework (Java to Kotlin, JavaScript to Rust, a Python library to TypeScript, an iOS app to Android), when asked what is left to port, or when comparing the Android and iOS versions of an app.★ 6.3k GitHub starsSkillManages Ahrefs API usage in Python using ahrefs-pythonOpenClaudia/openclaudia-skills · by OpenClaudiaManages Ahrefs API usage in Python using `ahrefs-python` library. Use when working with SEO / marketing related tasks or with data including backlinks, keywords, domain ratings, organic traffic, site audits, rank tracking, and brand monitoring. Covers `ahrefs-python` usage including AhrefsClient / AsyncAhrefsClient, typed request/response models, error handling, and all API sections.★ 705 GitHub starsMCPDocx LLM translatoradeudealfluence/adeu · by dealfluenceDocx ↔ LLM translator. Projects .docx office files to Markdown for editing. Projects edits back to OOXML as tracked changes (redlines). Python and Node.js implementations.★ 165 GitHub starsSkillCreate an Amazon-compliant white-background main imageAmazon White-Background Main Image · 亚马逊白底主图xianyu110/ecommerce-image-skills · by xianyu110Create an Amazon-compliant white-background main image (pure #FFFFFF background, product fills ≥85% of the frame, no text, props or watermark) from a product photo with GPT Image 2.5, then verify it with a Python check script. Use for Amazon/Walmart/eBay main images, 白底图, 白底主图, hero image, listing main photo.★ 92 GitHub starsMCPOfficial monorepo of SDKs, CLISendmux sdkSendmux/sendmux-sdk · by SendmuxOfficial monorepo of SDKs, CLI, and MCP servers for Sendmux email APIs across TypeScript, Python, Go, PHP, Rust, and Ruby.★ 65 GitHub stars

More from alirezarezvani

SkillResume a paused experiment/ar:ar-resume — Resume Experimentalirezarezvani/claude-skills · by alirezarezvaniResume a paused experiment. Checkout the experiment branch, read results history, continue iterating. Use when the user runs /ar:ar-resume or asks to pick up a previously started autoresearch experiment.★ 26.3k GitHub starsSkillShow experiment dashboard with results, active loops/ar:ar-status — Experiment Dashboardalirezarezvani/claude-skills · by alirezarezvaniShow experiment dashboard with results, active loops, and progress. Use when the user runs /ar:ar-status or asks how an autoresearch experiment is going.★ 26.3k GitHub starsSkillStart an autonomous experiment loop with user-selected/ar:loop — Autonomous Experiment Loopalirezarezvani/claude-skills · by alirezarezvaniStart an autonomous experiment loop with user-selected interval (10min, 1h, daily, weekly, monthly). Uses CronCreate for scheduling. Use when the user runs /ar:loop or asks to run an autoresearch experiment continuously on a schedule.★ 26.3k GitHub starsSkillRun a single experiment iteration/ar:run — Single Experiment Iterationalirezarezvani/claude-skills · by alirezarezvaniRun a single experiment iteration. Edit the target file, evaluate, keep or discard. Use when the user runs /ar:run or asks for one manual autoresearch iteration.★ 26.3k GitHub starsSkillSet up a new autoresearch experiment interactively/ar:setup — Create New Experimentalirezarezvani/claude-skills · by alirezarezvaniSet up a new autoresearch experiment interactively. Collects domain, target file, eval command, metric, direction, and evaluator. Use when the user runs /ar:setup or asks to start optimizing a file with the autoresearch loop.★ 26.3k GitHub starsSkill/cs:boardroom <brief/cs:boardroom — Multi-Role Boardroom Deliberationalirezarezvani/claude-skills · by alirezarezvani/cs:boardroom <brief> — 6-phase multi-role deliberation across the C-suite with Phase 2 isolation, critic pre-screen, and synthesis. Outputs a board memo. Use when a decision spans multiple executive domains — e.g. a pricing change touching finance, positioning, and product, or a raise-vs-cut runway call.★ 26.3k GitHub stars