The preload scanner is a second, lightweight parser the browser runs alongside the main one. While the main parser is stuck waiting on a blocking script or building the DOM, the scanner reads ahead through the raw bytes of the HTML looking for things worth fetching now: images, stylesheets, scripts, fonts. Google describes its job as speculative, “examining raw markup in order to find resources to opportunistically fetch before the primary HTML parser would otherwise discover them.”
It is invisible, it has no API, and it is doing most of the work behind every “why is my image loading so late” question.
It reads one thing: the bytes the server sent
The scanner’s power and its blind spot are the same fact. It works on the response text, not on the page:
- Not the DOM after JavaScript runs. An
<img>created by a script does not exist when the scanner passes through. - Not stylesheets. Google is explicit that it “scans markup” and “doesn’t scan other
resource types, such as CSS which may involve fetches for images referenced by the
background-imageproperty.” - Not
data-src. A lazy-loading library’s placeholder attribute is not a URL the browser recognises.
So the rule that matters is short: if a resource is not written as a real attribute in the HTML your server returns, it cannot be discovered early. No amount of priority tuning changes that, because there is nothing yet to prioritise.
On 37% of the sites we audited, there was nothing to find
We can count how often that blind spot has something real in it, because our proxy runs a filter whose entire job is to find the above-the-fold image and prioritise it, and it writes down what it found. Across 261 audited sites:
| Outcome | Sites | Share |
|---|---|---|
| A real above-the-fold content image, discoverable | 165 | 63% |
| No content image, only the logo could be prioritised | 24 | 9% |
| Nothing eligible at all | 72 | 28% |
The middle row is the vivid one. Those pages do have something the scanner can find early, and it is the logo in the header. The photograph that fills the first screen is somewhere the scanner cannot look.
Four ways a page hides its hero
- Client-side rendering. The markup ships a container and a script. This is the near- universal case on framework sites in our base.
- A CSS background image. A legitimate LCP element, and completely outside the scanner’s
reach. Send the hint out of band, in an HTTP
Link:header. loading="lazy"on the hero. The scanner reads the attribute and correctly declines to fetch early. You have hidden your own largest paint.- A
data-srcplaceholder. Same outcome, from a library instead of an attribute.
How to check yours in thirty seconds
Open the page source, not the inspector. view-source: shows the bytes the server sent;
DevTools shows the DOM after JavaScript has rewritten it, which is precisely the difference
the scanner cares about. Search for your hero’s filename. If it is not there as a plain
src, the scanner never saw it.
Where WebSpeed steps in
Our pipeline reads the served HTML the same way the scanner does, finds the largest
above-the-fold image, and rewrites the markup so it is discoverable: a real src, a
high-priority hint, no lazy attribute, and a matching preload for backgrounds the scanner
cannot reach. Where the first screen genuinely is not in the HTML, we say so instead of
adding a hint that points at nothing.