Capture a full web page
Snapshot the document’s rendered DOM rather than only the visible viewport.
Pass document.documentElement or a dedicated page wrapper to SnapDOM.
Copy-paste example
Install @zumer/snapdom, select the rendered element, and capture it:
const page = document.documentElement
const capture = await snapdom(page, {
embedFonts: true,
outerShadows: true,
})
await capture.download({ format: 'png', filename: 'full-page' })Why this pattern works
Capturing the root includes the document’s layout beyond the current viewport. A dedicated content wrapper is often preferable when fixed navigation or overlays should be excluded.
Capture content beyond a viewport
This scrollable preview is intentionally tall; capture exports the complete selected DOM subtree.
Hero section
Content rendered below the initial visible area remains part of this DOM element.
Features
Content rendered below the initial visible area remains part of this DOM element.
Customer story
Content rendered below the initial visible area remains part of this DOM element.
Pricing
Content rendered below the initial visible area remains part of this DOM element.
Final call to action
Content rendered below the initial visible area remains part of this DOM element.
Pages taller than the canvas limit
With the default SVG engine, PNG file exports automatically preserve the requested resolution beyond canvas limits. SnapDOM renders the frozen capture in windows and encodes one PNG file:
const capture = await snapdom(page)
await capture.download({ format: 'png', scale: 2 })
// Or get a file to upload/store:
const blob = await capture.toBlob({ format: 'png', scale: 2, dpr: 1 })download() always uses DPR 1. This automatic path requires CompressionStream; older browsers keep the existing downscale and warning. Large files still need encoding time and memory, and image viewers have their own limits.
toCanvas(), toPng() and JPEG/WebP exports keep the single-canvas size guards: 16,384px per side in Safari, 32,767px in Chrome/Firefox, plus an area limit. If you need separate canvases, export pieces with crop:
const capture = await snapdom(page)
const { contentX, contentY, w0, h0 } = capture.meta
const pieceHeight = 4000 // CSS px
for (let y = 0; y < h0; y += pieceHeight) {
const canvas = await capture.toCanvas({
scale: 2,
dpr: 1,
crop: { x: contentX, y: contentY + y, width: w0, height: Math.min(pieceHeight, h0 - y) }
})
// save or upload this piece, then move on
}crop is a rectangle in the coordinates of capture.meta, and each call returns one canvas. The capture runs once; only the rasterization repeats. Keep pieceHeight × scale × dpr under the limit. How tiling works.
Limits and common mistakes
Very large pages create large SVG and bitmap surfaces. For huge or virtualized documents, capture logical sections or render hidden items before capture.
Frequently asked questions
Is this the same as a viewport screenshot?
No. A viewport screenshot captures visible screen pixels; this captures the selected DOM subtree and its layout extent.
Will lazy content be included?
Only content that exists and has resolved. Load or render lazy sections before starting capture.
Capture it in the browser
Install SnapDOM and turn the DOM your users already see into a portable image.
Open the demoInstallation