Screenshot a div from JavaScript — and have it look like your app

Every “javascript screenshot library” search ends at one of three architectures, and most of the frustration comes from picking the wrong one for the job. Here is the honest map.

1. Re-rendering libraries

html2canvas parses your stylesheets and redraws the page onto a canvas with its own layout engine — free, offline, and dependent on that engine keeping up with CSS. It last shipped in January 2022, so the gap only grows: captures are close, and “close” is exactly the complaint that brings people here. Right choice when captures are occasional and pixel drift is acceptable. Full comparison →

2. SVG-serialization libraries

html-to-image (dom-to-image's successor) copies the node into an SVG foreignObject and lets the browser rasterize the copy — better fidelity than re-rendering, still free, actively maintained. The copy is the catch: every external image, font and stylesheet must be fetched and inlined, each with its own CORS and browser quirks. Right choice for open-source capture inside a pipeline you are building yourself. Full comparison →

3. Server-side screenshot APIs

Urlbox, ScreenshotOne and their category load a URL in their own headless browser and return the image. Unbeatable for pages you don't control — monitoring, thumbnails, archives — and structurally unable to see what your logged-in user sees, because the session rendering the page is theirs, not the user's. Priced like the server fleet doing the work. vs Urlbox · vs ScreenshotOne

4. Computed-style capture, in the user's browser

screen2api reads the computed style of every node — the browser's own layout decisions, not a re-implementation of them — so the capture matches the screen, including dark mode, scroll state and whatever your third-party widgets rendered. And because the product is the pipeline, not just the pixels: users can annotate and redact before anything uploads, and the finished files land on your endpoint with your own params attached.

import { createClient } from '@screen2api/sdk'

const s2a = createClient({ publishableKey: 'pk_live_…' })

// The element, as rendered — dark mode, scroll state, third-party widgets
await s2a.capture({
  target: '#invoice',
  formats: ['png', 'pdf'],
  params: { invoiceId: 'inv_1042' },
})

Questions people ask

Why do html2canvas screenshots look wrong sometimes?
Because it re-renders: it parses your CSS and lays the page out again in JavaScript, so anything its renderer does not model — newer CSS, embedded widgets, some fonts — drifts from what the browser drew. Reading the computed style of the live DOM avoids the re-implementation entirely.
Can JavaScript capture what a logged-in user sees?
Only from inside the user's own browser — which is what an SDK embedded in your app does. Server-side screenshot APIs render URLs in their own sessions, so they see the logged-out page unless you share credentials with them.
Is there a way to try it without an account?
Yes — the playground runs the real SDK against a real page, and the free tier is 500 captures a month when you wire it into your own app.