All options
All capture methods accept an options object.
| Option | Type | Default | Description |
|---|---|---|---|
| debug | boolean | false | When true, logs suppressed errors to console.warn for troubleshooting |
| fast | boolean | true | Skips small idle delays for faster results |
| embedFonts | boolean | false | Inlines non-icon fonts (icon fonts always on) |
| localFonts | array | [] | Local fonts { family, src, weight?, style? } |
| iconFonts | string | RegExp | Array | [] | Extra icon font matchers |
| excludeFonts | object | {} | Exclude families/domains/subsets during embedding |
| scale | number | 1 | Output scale multiplier |
| dpr | number | devicePixelRatio | Device pixel ratio |
| width | number | - | Output width |
| height | number | - | Output height |
| backgroundColor | string | "#fff" | Fallback color for JPG/WebP |
| quality | number | 1 | Quality for JPG/WebP (0 to 1) |
| useProxy | string | '' | Proxy base for CORS fallbacks |
| exclude | string[] | - | CSS selectors to exclude |
| excludeMode | "hide" | "remove" | "hide" | How exclude is applied |
| filter | function | - | Custom predicate (el) => boolean |
| filterMode | "hide" | "remove" | "hide" | How filter is applied |
| cache | string | "soft" | disabled | soft | auto | full |
| placeholders | boolean | true | Show placeholders for images/CORS iframes |
| fallbackURL | string | function | - | Fallback image for <img> load failure |
| outerTransforms | boolean | true | When false removes translate/rotate but preserves scale/skew, producing a flat, reusable capture |
| outerShadows | boolean | false | Do not expand the root's bounding box for shadows/blur/outline, and strip those visual effects from the cloned root |
| safariWarmupAttempts | number | 3 | Safari only: iterations to prime font/decode (WebKit #219770). Use 1 if 3 causes lag |
| compress | boolean | true | Downsample inlined raster images to their visible resolution. Faster raster captures + smaller SVG output, fidelity-neutral. Set false to embed images verbatim |
debug
When debug: true, SnapDOM logs normally suppressed errors to console.warn (with the [snapdom] prefix). Useful for troubleshooting capture issues (canvas failures, blob resolution, style stripping, etc.) without noisy output in production.
await snapdom.toPng(el, { debug: true });
compress
Inlined raster images are embedded at their full natural resolution even when shown in a small box — pixels the output can never display, which only bloat the payload and slow rasterization. With compress (on by default) SnapDOM downsamples each oversized raster to (a touch below) the resolution actually visible (display box × scale × dpr), preserving aspect ratio and never upscaling. The source codec is kept (PNGs stay lossless), and because the image was already shown far smaller than its natural size the quality loss is imperceptible in practice. Images already at or below their visible size are left untouched. Covers <img> (incl. cloned canvas/video), non-repeating CSS background-image, and SVG <image>.
The benefit depends on the export:
- Raster (
toPng/toJpg/toCanvas/toBlob): much faster — the browser decodes/composites small images instead of huge ones. Output size is essentially unchanged (the final bitmap is the same visible pixels). - SVG (
toSvg/ raw): much smaller output — the downsampled images are embedded in the SVG.
It is a no-op for images already shown at (or below) their natural resolution, so the common case pays virtually nothing. Pass compress: false to embed images verbatim (e.g. if you intend to scale the SVG up later).
// default: images downsampled to visible resolution
await snapdom.toPng(el);
// keep images at full resolution
await snapdom.toPng(el, { compress: false });
Fallback image on <img> load failure
Provide a default image for failed <img> loads. You can pass a fixed URL or a callback that receives measured dimensions and returns a URL (handy to generate dynamic placeholders).
// 1) Fixed URL fallback
await snapdom.toSvg(element, {
fallbackURL: '/images/fallback.png'
});
// 2) Dynamic placeholder via callback
await snapdom.toSvg(element, {
fallbackURL: ({ width: 300, height: 150 }) =>
`https://placehold.co/${width}x${height}`
});
// 3) With proxy (if your fallback host has no CORS)
await snapdom.toSvg(element, {
fallbackURL: ({ width = 300, height = 150 }) =>
`https://dummyimage.com/${width}x${height}/cccccc/666.png&text=img`,
useProxy: 'https://proxy.corsfix.com/?'
});
Notes:
- If the fallback image also fails to load, snapDOM replaces the
<img>with a placeholder block preserving width/height. - Width/height used by the callback are gathered from the original element (dataset, style/attrs, etc.) when available.
Dimensions (scale, width, height)
- If
scaleis provided, it takes precedence overwidth/height. - If only
widthis provided, height scales proportionally (and vice versa). - Providing both
widthandheightforces an exact size (may distort).
Cross-Origin Images & Fonts (useProxy)
By default snapDOM tries crossOrigin="anonymous" (or use-credentials for same-origin). If an asset is CORS-blocked, you can set useProxy to a prefix URL that forwards the actual src:
await snapdom.toPng(el, {
useProxy: 'https://proxy.corsfix.com/?' // Note: Any cors proxy could be used 'https://proxy.corsfix.com/?'
});
- The proxy is only used as a fallback; same-origin and CORS-enabled assets skip it.
Fonts
embedFonts
When true, snapDOM embeds non-icon @font-face rules detected as used within the captured subtree. Icon fonts (Font Awesome, Material Icons, etc.) are embedded always.
localFonts
If you serve fonts yourself or have data URLs, you can declare them here to avoid extra CSS discovery:
await snapdom.toPng(el, {
embedFonts: true,
localFonts: [
{ family: 'Inter', src: '/fonts/Inter-Variable.woff2', weight: 400, style: 'normal' },
{ family: 'Inter', src: '/fonts/Inter-Italic.woff2', style: 'italic' }
]
});
iconFonts
Add custom icon families (names or regex matchers). Useful for private icon sets:
await snapdom.toPng(el, {
iconFonts: ['MyIcons', /^(Remix|Feather) Icons?$/i]
});
excludeFonts
Skip specific non-icon fonts to speed up capture or avoid unnecessary downloads.
await snapdom.toPng(el, {
embedFonts: true,
excludeFonts: {
families: ['Noto Serif', 'SomeHeavyFont'], // skip by family name
domains: ['fonts.gstatic.com', 'cdn.example'], // skip by source host
subsets: ['cyrillic-ext'] // skip by unicode-range subset tag
}
});
Notes
excludeFontsonly applies to non-icon fonts. Icon fonts are always embedded.- Matching is case-insensitive for
families. Hosts are matched by substring against the resolved URL.
Filtering nodes: exclude vs filter
exclude: remove by selector.excludeMode:hideappliesvisibility:hiddenCSS rule on excluded nodes and the layout remains as the original.removedo not clone excluded nodes at all.filter: advanced predicate per element (returnfalseto drop).filterMode:hideappliesvisibility:hiddenCSS rule on filtered nodes and the layout remains as the original.removedo not clone filtered nodes at all.
Example: filter out elements with display:none:
/**
* Example filter: skip elements with display:none
* @param {Element} el
* @returns {boolean} true = keep, false = exclude
*/
function filterHidden(el) {
const cs = window.getComputedStyle(el);
if (cs.display === 'none') return false;
return true;
}
await snapdom.toPng(document.body, { filter: filterHidden });
Example with exclude: remove banners or tooltips by selector
await snapdom.toPng(el, {
exclude: ['.cookie-banner', '.tooltip', '[data-test="debug"]']
});
outerTransforms
When capturing rotated or translated elements, you may want use outerTransforms: false option if you want to eliminate those external transforms. So, the output is flat, upright, and ready to use elsewhere.
outerTransforms: true (default)— Keeps the originaltransformsandrotate.
outerShadows
outerShadows: false (default)— Prevents expanding the bounding box for shadows, blur, or outline on the root, and also stripsbox-shadow,text-shadow,filter: blur()/drop-shadow(), andoutlinefrom the cloned root.
💡 Tip: Using both (outerTransforms: false + outerShadows: false) produces a strict, minimal bounding box with no visual bleed.
Example
// outerTransforms and remove shadow bleed
await snapdom.toSvg(el, { outerTransforms: true, outerShadows: true });
Ready to capture?
Drop SnapDOM into your project and capture your first element in one line.
Open the demo Install from npm