Skip to main content

The capture cascade

Screenshots are taken in two stages, and it is worth understanding which one you get, because their fidelity differs.

Stage one — the browser's own screen capture. Pixel-exact: it is a picture of what the screen actually showed, including everything CSS can do. The browser asks the user for permission once per capture, and that prompt is expected behavior, not a failure — it appears only after the user clicks "Capture screenshot", never on page load.

Stage two — the DOM renderer. No permission prompt, works everywhere including iOS Safari, and reconstructs the page from the DOM rather than photographing it. That reconstruction is very good and has named limits, listed under what the DOM stage does not reproduce.

screenshot.strategy picks the behavior:

ValueBehavior
auto (default)try stage one, fall back to stage two when it is unavailable or declined
nativestage one only
domstage two only — no permission prompt ever
offno screenshot button at all

Which stage produced a given screenshot is recorded on the report, so a maintainer can tell an exact picture from a reconstruction.

Whatever the stage, the reporter sees the screenshot before sending and can discard or retake it. Nothing is uploaded until they attach it.

What ends up in the frame

The visible viewport, not the whole page. screenshot.viewport_only is on by default and both stages honor it, so a report about something further down the page arrives as the band the reporter was actually looking at. That is usually the point — but it is worth knowing before you go looking for the rest of the page in the image.

Stage one captures whatever the reporter agreed to share. The browser owns that choice, and this package does not get to make it: Chromium narrows the picker to the current tab, elsewhere the reporter can pick another window or the whole screen, and what they pick is what arrives. Two consequences worth carrying: a report can contain more of their desktop than either of you intended, and region redaction covers regions of your page — it has no reach into a window that is not yours.

The byte cap is enforced on the server only

screenshot.max_bytes (8 MB) is checked after the upload lands, and the browser is never told the number. Lowering it is the one change here that can strand a reporter: the capture is produced, uploaded, refused, and nothing on the client knows to try again smaller, so they get a capture-and-reject loop with no way out of it. If your captures really are too large, lower screenshot.scale — that is the knob the browser obeys — and leave the cap where the renderer's own output was sized against it.