An engineer who cannot reproduce a ticket looks at the screenshot again, sees a page that does not match the app, and quietly concludes the reporter was on something else. A browser gives a page no way to photograph itself, so that picture may have been drawn a second time, by a renderer forbidden to load anything.
A browser will not let a page photograph itself
No API hands a script the pixels its own document is showing without asking a person first, and none captures a single element at all. A page that wants a picture of itself has two routes, and they cost different things.
| Route | What it needs from the reporter | What it captures | What it cannot do |
|---|---|---|---|
| A frame from the compositor | A permission prompt, accepted, in a browser that offers screen capture | The pixels the screen was showing, canvas and video and embedded frames included | Exist on a phone, or survive a declined prompt |
| A second render | Nothing | The page rebuilt from its own structure, then drawn again inside an image | Request a single resource |
The right-hand column is where the differences come from. A second render clones the visible document, reuses the CSS the browser has already parsed, and hands the result over as an SVG image that is drawn onto a canvas. On the way through, every style value carrying a URL is stripped and every rule that would pull a file is skipped, so the render triggers no font request and no image request. The capture issues no network call at all, which is a written contract rather than an accident, and it is where the differences begin.
The walk is bounded on the same principle. One capture visits at most 5,000 nodes and finishes inside a 5 second deadline. The image is bounded twice over, by a 1,920 pixel long edge and by a raster budget of 1.6 million pixels, which is usually the one that binds first, and it never rasterizes above a device pixel ratio of 2.
A rebuilt picture says so on the ticket
The caveat travels attached to the image rather than sitting in a settings page nobody opens. A picture the widget’s composer rebuilt arrives labelled as rebuilt from the page structure, with a plain warning that it can differ from the live app, followed by the kinds of content this particular capture could not reproduce, written in a reviewer’s terms instead of in the capture’s own codes. What travels with the rest of the report is documented in evidence capture.
That label changes what a reviewer does next. Two tickets showing the same wrong-looking page are two different pieces of evidence, and only one of them raises a question about the reporter’s browser.
On a phone no browser offers screen capture, so wherever the reporter can attach a file instead, the widget removes its own screenshot button rather than produce a redrawing. The device in their hand already takes a perfect picture, and giving up the button is what sends them to it. That behaviour is pinned by a test, so it is a decision rather than a side effect.
What a redrawn page cannot contain, and what to ask for instead
The omissions are named kinds, and each one implies a different next question.
| What the picture could not reproduce | Why a second render cannot hold it | What to ask for instead |
|---|---|---|
| Canvas and WebGL | The drawing lives in a buffer rather than in the document | A screen recording, which replay does not substitute for |
| Video | The same buffer problem, with a moving target on top of it | A screen recording |
| Embedded frames | A frame is a separate document the capture may not read | A report filed from inside the frame’s own page |
| Images | Fetching one is precisely what the capture may not do, whatever its origin | The image URL, and whether it resolves for them |
| Web fonts | A font file is a resource request, so the text is redrawn in a system family | Nothing. The layout is the evidence, the typeface is decoration |
| Form values | They are never serialized, deliberately | The value that broke it, written into the ticket |
| Styles the capture could not read | A stylesheet from another origin, an import, or a budget spent partway through | The page loaded in your own browser at their viewport |
| Part of a very large page | The walk stops at its node bound rather than running long on somebody else’s page | The route, and which region they were looking at |
Read the right-hand column on its own: every row turns “the screenshot is wrong” into a question somebody can answer, and none of them is “are you sure that happened”. A reviewer who reads the omission first stops spending triage on the reporter’s credibility. The first row is the one that catches people out, because a session replay shows the sequence around a canvas and never the pixels inside it.
The text moves before anything else does
Typography is what a reviewer notices first. The shallow reason is the font substitution above; the deeper one is a reasoning error about CSS that any second render can make.
getComputedStyle reports line-height as a pixel length. A stylesheet that writes line-height: 1.7, which is what nearly every stylesheet writes, gets its ratio back already multiplied by the font size of the element the question was asked about. Copy that resolved number down into a clone and a 30px heading inherits the line box computed for 16px body text. Headings collapse, every line under one starts higher than it should, and because the error accumulates the picture drifts further from the page the further down you read. Measured on one page before it was fixed: 21px adrift at 110px deep, 58px at 450px.
The rule that settles it is short. An inherited property has to be handed down in the form it was authored in, as a ratio, and never in the form the engine resolved it to for one particular element. That is closed here, with a regression test holding it closed. It is worth knowing anyway, because anybody rasterizing a DOM for a thumbnail, a PDF or a visual test has the same trap open in their own code, and a reviewer who has seen it stops reading a shifted heading as proof of a different build.
What this picture will not give you
The capture is the viewport, not the document: what was below the fold is not in the image, and neither is anything finer than the bounds above. Regions marked private are dropped rather than blanked, so the content under them closes up, and the geometry below a redacted block is not the geometry of the live page. On the picture of a marked element, where that matters most, the widget declines to trust its own highlight when a redaction above the crop shifted the flow, and hands over an unmarked picture rather than a mark in the wrong place. A capture that exhausts its deadline attaches nothing at all, and the report goes without a picture rather than with a torn one.
A bug living in a canvas, in a video, or inside an embedded frame will not appear in a rebuilt screenshot, and on a page where no compositor frame is available, asking the reporter to send another one returns the same picture. The weak link in that chain is rarely the reporter and usually the evidence request, which is the half a reviewer can change: read how the picture was made, then ask for the thing the picture could not hold. Steps to reproduce written from a recording beat steps argued from a redrawing, and the argument about whether somebody is misremembering never has to start.