# Fullpage Screenshot

> Capture full-page screenshots of a website at several viewport widths at once, including pages behind basic auth or needing setup clicks. Use when asked to screenshot a site, grab full-page captures, check a page across breakpoints, produce responsive review artefacts, or compare how a layout renders at mobile, tablet and desktop widths.

- Skill: `mad-coders/fullpage-screenshot` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add mad-coders/fullpage-screenshot`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mad-coders/fullpage-screenshot/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: mad-coders (https://skillmd.com/u/mad-coders)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mad-coders/fullpage-screenshot

---


# Full-page screenshots across breakpoints

Capture a whole page - not just the visible viewport - at several widths in one
run, and get a report that doubles as a responsive-layout check.

## Install

```bash
make install     # into ~/.claude/skills, available in every project
make check       # confirm it is installed and a browser will start
```

`make install-project` puts it in `./.claude/skills` instead, so it travels
with a repository. `make link` symlinks rather than copies, so `git pull`
updates the installed skill. `make uninstall` removes it.

## Quick start

```bash
make capture URL=https://example.com
# or
node scripts/capture.mjs --url https://example.com --out ./screenshots
```

Widths default to `375,768,992,1200,1440`. Override with `--widths`.

If a capture will not start, `node scripts/capture.mjs --check` lists every
browser it can find and reports which of them actually launch.

## Why not just take a screenshot

Three things make this harder than it looks, and the script handles all three.

**A viewport screenshot is not a page screenshot.** Most tooling captures what
is on screen. Stitching slices by scrolling breaks on sticky headers, which
reappear in every slice. Use the browser's own full-page capture instead.

**Images decode late.** A full-page capture fires before lazy or still-decoding
images finish, and you get half-loaded photography in an otherwise perfect
screenshot. The script waits for every `<img>` to settle first.

**The page may need setting up.** Behind basic auth, a cookie banner, a state
toggle. `--auth` covers credentials; `--prepare` runs arbitrary JS in the page
before the shot.

## The report is the point

Every run prints one row per capture:

```
width  requested  captured  height  status
375    375        375       4205    ok
768    768        773       3865    OVERFLOWS BY 5px
```

**A full-page capture expands to fit horizontal overflow.** So when the captured
width exceeds the requested width, the page overflows sideways at that
breakpoint - which is a layout bug you would otherwise have to hunt for. The
screenshots come with a free responsive audit attached.

## Options

| flag | default | meaning |
|---|---|---|
| `--url` | required | page to capture |
| `--out` | `./screenshots` | output directory, created if absent |
| `--widths` | `375,768,992,1200,1440` | comma separated CSS widths |
| `--scale` | `2` | device pixel ratio; `1` for smaller files |
| `--auth` | none | `user:password` for HTTP basic auth |
| `--prepare` | none | path to a JS module run in the page before each capture |
| `--name` | `page` | filename prefix |
| `--chrome` | auto-detected | path to a Chrome binary |

## Preparing the page

`--prepare` takes a module exporting a default async function. It runs inside
the page for every capture, and receives the width so it can vary by
breakpoint:

```js
// prepare.mjs
export default async function (width) {
    localStorage.setItem('cookie-consent', 'accepted');
    if (width >= 992) {
        document.querySelector('[data-view="grid"]')?.click();
    }
}
```

Capturing two variants of the same page means two runs with different
`--prepare` and `--name`.

## Requirements

Node 18+ and a Chrome or Chromium binary. The script finds one automatically
from the Puppeteer cache, a Playwright cache or the usual system locations; use
`--chrome` to point at a specific build. Only `puppeteer-core` is installed - no
browser download.

See `references/troubleshooting.md` when a browser will not start.

