Node.js ≥ 22 · MIT License

Full-page screenshots,
dead simple.

Not a smart analyzer. Not a browser automation framework. Just a dumb, reliable screenshotter — one URL, one perfect full-page capture.

terminal
$ mshot --url https://example.com --out screenshot.jpg
MSHOT_SCROLL: page height 900px, pre-scroll done
screenshot.jpg
Features

Everything you need,
nothing you don't

mshot focuses on one thing and does it perfectly — pixel-perfect full-page screenshots, reliably.

Pre-scroll stabilization

Scrolls top→bottom→top before capture, triggering lazy images, IntersectionObserver content, and any scroll-dependent rendering. No more half-loaded pages.

Bounded resource settling

Waits for document.fonts.ready and all <img> elements — with a hard timeout ceiling. Never hangs.

Batch mode with one browser

Captures dozens of pages using a single Chromium instance. Built-in concurrency, link discovery, and a structured manifest.json output.

Rendered link discovery

Discovers real, rendered links from the base page — including lazy-loaded and JS-rendered content. Supports multi-depth crawling for deeper site coverage.

Route pattern deduplication

Numeric IDs, UUIDs, encoded segments — all normalized to :id. Captures one representative per pattern. No more 50 identical entity pages.

Segmented output

One browser capture → Sharp-powered overview thumbnail + overlapping segments. No repeated captures, no extra browser opens. Configurable height and overlap.

Multi-viewport capture

Capture desktop (1440px) and mobile (390px) viewports in a single batch run. Each viewport gets its own screenshot and manifest entry.

JPEG, PNG, WebP

Powered by Sharp for format conversion and quality control. Choose your output format and quality level — from tiny WebP to lossless PNG.

Agent-safe & atomic

Clean stdout/stderr contract, atomic file writes (tmp → rename), and automatic cleanup on failure. Built to be called by agents and CI pipelines.

Pipeline

How it works

A tight, predictable pipeline from URL to pixel-perfect screenshot.

1

Navigate → Load

Fresh Chromium navigates to the URL, waits for domcontentloaded, then networkidle.

2

Pre-scroll stabilization

Scrolls top→bottom→top to trigger lazy images, IntersectionObserver content, and any scroll-dependent rendering. Capped at 30,000px.

3

Resource settling

Best-effort wait for fonts and images to load, bounded by --settle-timeout. Animations disabled for stable frames.

4

Full-page screenshot

Captures the full page in one go. Optional --max-height crop for extremely tall pages.

5

Convert & write atomically

Sharp converts to the target format. File is written via tmp → rename for atomicity. On failure, everything is cleaned up.

Modes

Two modes. One goal.

Single URL for quick captures, batch mode for comprehensive visual regression.

Single mode

One URL → one full-page screenshot. Perfect for quick captures, documentation, or one-off visual checks.

$ mshot --url https://example.com --out screenshot.jpg
# Supports --width, --quality, --max-height
# Formats: .jpg, .png, .webp

Batch mode

Discover links, capture multiple pages with concurrency, multi-viewport support, and structured manifest output.

$ mshot batch --url http://localhost:3079 --out-dir ./screenshots
# + --discover --viewports desktop,mobile --segments
# + --depth 2 --concurrency 4 --urls-file routes.txt

Batch outputs structured manifest

Every capture tracked with timings and metadata

manifest.json
{
  "manifestVersion": 1,
  "baseUrl": "http://localhost:3079",
  "pages": [
    {
      "url": "http://localhost:3079",
      "screenshots": { "desktop": "home-desktop.jpg" },
      "timings": { "totalMs": 2000 }
    }
  ]
}
Deep dive

Segmented output

For extremely long pages — one capture, split into manageable pieces.

overview
seg 1
seg 2
seg 3
seg 4

1 browser capture → Sharp overview + overlapping segments
No repeated captures. No extra browser opens.

Philosophy

Stable over clever

Predictable

Deterministic behavior. Same input, same output. Every time.

Agent-safe

Clean stdout/stderr contract. Atomic writes. No stale files.

No fluff

No DOM parsing. No AI. No analysis. Just screenshot and save.

Install

Get started in 30 seconds

Two commands. That's it.

terminal
$ npm install -g mshot
$ npx playwright install chromium
$ mshot --url https://example.com --out screenshot.jpg
Node.js ≥ 22 npm or npx MIT License