full-page-screenshot · alirezarezvani — Claude Code skill: install and use
Captures an entire web page as one PNG, including content below the fold. Useful for SPAs, lazy-loaded images, and very tall pages.
/plugin marketplace add alirezarezvani/claude-skills
/plugin install engineering-advanced-skills@claude-code-skillsWhat full-page-screenshot does
This skill connects to Chrome through the Chrome DevTools Protocol and produces a single PNG containing the full page. It detects scrollable containers in SPAs, expands them, and scrolls through the page so deferred images have a chance to load.
The package includes the Node.js script full-page-screenshot.mjs. It checks the environment, discovers Chrome's debugging port, connects over WebSocket, waits for DOM stability, and checks that images have loaded. Pages taller than 16,000px are captured as 8,000px tiles; Python PIL can stitch them into one image.
You need Node.js 22+ and Chrome or Chromium with remote debugging enabled. For authenticated pages, use an existing tab with --list instead of --url. Install it when an agent needs full-page captures; it is more than you need for a regular viewport screenshot.
What it helps with
- capture a complete web page in one PNG
- include content inside SPA scroll containers
- trigger lazy-loaded images before capture
- stitch tiles from a very tall page
Example prompts for the agent
- Capture the open page from the authenticated tab and save it as `/tmp/screenshot.png`.
- Run `--check`, list the available tabs with `--list`, then capture the target tab at width 1200.
- Capture the page by URL with `--dpr 1` and wait for it to finish rendering.
How to install full-page-screenshot
1Plugin marketplace
/plugin marketplace add alirezarezvani/claude-skills/plugin install engineering-advanced-skills@claude-code-skillsThis installs the whole engineering-advanced-skills plugin with all its skills
2Skills CLI (Vercel)
npx skills add alirezarezvani/claude-skills --skill full-page-screenshot -a claude-code3Manually: put the files in place
~/.claude/skills/full-page-screenshot/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/full-page-screenshot/
Manually: put the files in place
.agents/skills/full-page-screenshot/SKILL.mdFor all projects use ~/.agents/skills/
Manually: put the files in place
.cursor/skills/full-page-screenshot/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install alirezarezvani/claude-skills full-page-screenshot2Manually: put the files in place
.github/skills/full-page-screenshot/SKILL.mdPlatform CLI
gemini skills install https://github.com/alirezarezvani/claude-skills --path engineering/skills/full-page-screenshotManually: put the files in place
.devin/skills/full-page-screenshot/SKILL.mdThe legacy .windsurf/skills/ path still works
Claude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set349
The whole set →Other versions of full-page-screenshot
Similar
Questions about full-page-screenshot
How do I install full-page-screenshot in Claude Code?
Run npx skills add alirezarezvani/claude-skills --skill full-page-screenshot -a claude-code. It can also be installed through the Claude Code Marketplace.
What does full-page-screenshot do?
It connects to Chrome through the Chrome DevTools Protocol, scrolls through the page, and saves all content as a PNG. The script handles SPA scroll containers, lazy loading, and very tall pages.
What does full-page-screenshot require?
It requires Node.js 22+ and Chrome or Chromium with remote debugging enabled. Python Pillow is needed to stitch tiles for pages taller than 16,000px.
Source text
SKILL.md · MIT
---
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
```
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)
1. List available tabs:
```bash
node "${SKILL_DIR}/scripts/full-page-screenshot.mjs" --list
```
2. Identify the target by title/URL, then capture:
```bash
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)
```bash
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
```bash
# 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
- [`engineering/browser-automation`](../browser-automation/SKILL.md) — General browser automation patterns via CDP/Playwright
- [`engineering/performance-profiler`](../performance-profiler/SKILL.md) — Performance analysis that may complement visual captures
© Alireza Rezvani · MIT · alirezarezvani/claude-skills