How-To Recipe
zumerlab/snapdom

How to screenshot a div in JavaScript

The shortest possible answer: pick the element, call snapdom.toPng, get back an image. Two minutes from npm install to working code.

TL;DR

const img = await snapdom.toPng(document.querySelector('#my-div')); — that's the entire recipe. The promise resolves to an HTMLImageElement you can append, download or upload.

Step 1 — Install SnapDOM

npm install @zumer/snapdom

If you don't use a bundler, you can also use the CDN build:

<script type="module">
  import { snapdom } from "https://unpkg.com/@zumer/snapdom/dist/snapdom.mjs";
</script>

Step 2 — Pick the div you want to screenshot

Anything that's part of the live document tree works. Most people use document.querySelector:

const el = document.querySelector('#card');

The element doesn't need to be visible inside the viewport, but it does need to be attached to the document (not display: none).

Step 3 — Capture it

One line:

import { snapdom } from '@zumer/snapdom';

const img = await snapdom.toPng(el);

The returned img is a real HTMLImageElement with the captured content as its src (a base64-encoded SVG/PNG data URL).

Step 4 — Do something with the image

Append it to the page

const img = await snapdom.toPng(el);
document.body.appendChild(img);

Download it as a file

const result = await snapdom(el);
await result.download({ format: 'png', filename: 'card' });

Get a Blob to upload to a server

const blob = await snapdom.toBlob(el);

const form = new FormData();
form.append('file', blob, 'screenshot.png');
await fetch('/api/upload', { method: 'POST', body: form });

Full working example

Drop this into a fresh HTML file and open it in a browser:

<!DOCTYPE html>
<html>
<body>
  <div id="card" style="padding:24px;background:#6366f1;color:#fff;border-radius:12px;">
    <h2>Hello SnapDOM</h2>
    <p>This entire div is about to become a PNG.</p>
  </div>
  <button id="go">Capture</button>

  <script type="module">
    import { snapdom } from "https://unpkg.com/@zumer/snapdom/dist/snapdom.mjs";

    document.getElementById('go').addEventListener('click', async () => {
      const img = await snapdom.toPng(document.getElementById('card'));
      document.body.appendChild(img);
    });
  </script>
</body>
</html>

Useful options

Frequently asked questions

Why not use the browser's built-in screenshot API?

There isn't one. The closest thing is the Screen Capture API (getDisplayMedia) which captures the whole tab or screen and requires user permission — it cannot target a specific DOM element. SnapDOM is the workaround.

Does this work with web fonts?

Yes, but you have to opt in. Pass { embedFonts: true } and SnapDOM will inline the matching @font-face declarations so the captured image renders with your real fonts.

Can I screenshot something inside an iframe?

Same-origin iframes are supported out of the box. Cross-origin iframes are not — the browser blocks access to their content.

What about Shadow DOM?

SnapDOM walks open Shadow DOM trees during capture, so Web Components render correctly.

How big is the library?

Under 30 KB minified + gzipped, with zero runtime dependencies.

Try the live demo

See SnapDOM running in your browser before installing it.

Open the demo Install from npm