Full page screenshot

Use when the user asks to capture a full-page screenshot, long screenshot, or complete page capture of a web page.

How to use it

Claude Code
  1. Run the line below. It pulls the whole folder into ~/.claude/skills/full-page-screenshot, including the files SKILL.md points to.
  2. Describe your job in plain words. Claude Code follows the skill from there.
Claude Code — installs the whole folder, not just SKILL.md
npx degit alirezarezvani/claude-skills/engineering/skills/full-page-screenshot#main ~/.claude/skills/full-page-screenshot

For one project only, change the path to .claude/skills/full-page-screenshot. This skill also uses Node.js — copying SKILL.md alone won't be enough. See the folder on GitHub.

Claude (web or desktop app)
  1. On this page open ⋯ → Download .md.
  2. Save it as SKILL.md in a folder, zip the folder, then Customize → Skills → + → Create skill → Upload a skill.
  3. Pick the file and Save. Claude shows the name and description and runs a security scan.
  4. Check the skill is switched on.
  5. Start a new chat and describe your job in plain words. The AI follows the skill from there.
ChatGPT or another app
  1. ChatGPT: make a Project and paste it into Instructions.
  2. Neither? Paste it at the top of a new chat — it works for that chat.
Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Source of Full page screenshot

Show the full text124 lines
namedescription
full-page-screenshotUse 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:

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 

Discussion