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
- Run the line below. It pulls the whole folder into
~/.claude/skills/full-page-screenshot, including the files SKILL.md points to. - Describe your job in plain words. Claude Code follows the skill from there.
npx degit alirezarezvani/claude-skills/engineering/skills/full-page-screenshot#main ~/.claude/skills/full-page-screenshotFor 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)
- On this page open ⋯ → Download .md.
- Save it as SKILL.md in a folder, zip the folder, then Customize → Skills → + → Create skill → Upload a skill.
- Pick the file and Save. Claude shows the name and description and runs a security scan.
- Check the skill is switched on.
- Start a new chat and describe your job in plain words. The AI follows the skill from there.
ChatGPT or another app
- ChatGPT: make a Project and paste it into Instructions.
- 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.
Paste into Claude, ChatGPT or Cursor.
Source of Full page screenshot
Show the full text124 lines
| name | description |
|---|---|
| full-page-screenshot | 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:
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
Option A: Screenshot an already-open tab (recommended for authenticated pages)
- List available tabs:
node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --list
- 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:
--urlmode 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
SPA scroll container expansion — Detects
overflow-y: auto/scrollcontainers, scrolls through them to trigger lazy-loading, then removes overflow constraints (including Tailwindh-[calc(...)]) so all content renders in a single pass.DOM stability detection — After
readyState=complete, monitors DOM element count until it stabilizes. This ensures SPA frameworks finish rendering dynamic content.Lazy-load triggering — Scrolls the viewport incrementally to fire
IntersectionObservercallbacks, then waits for all<img>elements to complete loading.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.
Auto-discovery of Chrome — Reads
DevToolsActivePortfile to find the debugging port. Falls back to probing ports 9222, 9229, 9333.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
engineering/browser-automation— General browser automation patterns via CDP/Playwrightengineering/performance-profiler— Performance analysis that may complement visual captures
| 1 | |
| 2 | name "full-page-screenshot" |
| 3 | 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." |
| 4 | |
| 5 | |
| 6 | # Full Page Screenshot |
| 7 | |
| 8 | 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. |
| 9 | |
| 10 | ## Prerequisites |
| 11 | |
| 12 | **Node.js 22+** (uses built-in `WebSocket`) |
| 13 | **Chrome/Chromium** with remote debugging enabled |
| 14 | |
| 15 | Check environment readiness: |
| 16 | |
| 17 | |
| 18 | node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --check |
| 19 | |
| 20 | |
| 21 | If 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 | |
| 27 | List available tabs: |
| 28 | |
| 29 | |
| 30 | node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --list |
| 31 | |
| 32 | |
| 33 | Identify the target by title/URL, then capture: |
| 34 | |
| 35 | |
| 36 | node "${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 | |
| 42 | node "${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 | |
| 60 | # macOS |
| 61 | sips -g pixelWidth -g pixelHeight /tmp/screenshot.png |
| 62 | |
| 63 | # Linux |
| 64 | file /tmp/screenshot.png |
| 65 | |
| 66 | |
| 67 | ## Core Capabilities |
| 68 | |
| 69 | **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 | |
| 71 | **DOM stability detection** — After `readyState=complete`, monitors DOM element count until it stabilizes. This ensures SPA frameworks finish rendering dynamic content. |
| 72 | |
| 73 | **Lazy-load triggering** — Scrolls the viewport incrementally to fire `IntersectionObserver` callbacks, then waits for all `<img>` elements to complete loading. |
| 74 | |
| 75 | **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 | |
| 77 | **Auto-discovery of Chrome** — Reads `DevToolsActivePort` file to find the debugging port. Falls back to probing ports 9222, 9229, 9333. |
| 78 | |
| 79 | **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 | |
| 84 | 1. Discover Chrome debugging port |
| 85 | 2. Connect via WebSocket (CDP) |
| 86 | 3. Attach to target / create background tab |
| 87 | 4. Set viewport width via Emulation domain |
| 88 | 5. Wait: readyState + DOM stability |
| 89 | 6. Detect & expand scroll containers |
| 90 | 7. Scroll through page (trigger lazy-load) |
| 91 | 8. Wait for images to complete |
| 92 | 9. Measure final content height |
| 93 | 10. Page.captureScreenshot (or tiled capture) |
| 94 | 11. Stitch tiles if needed (PIL) |
| 95 | 12. 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`] — General browser automation patterns via CDP/Playwright |
| 123 | [`engineering/performance-profiler`] — Performance analysis that may complement visual captures |
| 124 |
Discussion
Browse more free Claude skills.