LCP request discovery in Lighthouse: checks and the fix
Your LCP image can only start downloading once the browser has found it. Why a photo in a stylesheet, a slider or a lazy-load setting makes LCP late, and how to start it with the HTML.
What does LCP request discovery tell you about your LCP image?
LCP request discovery is the Lighthouse 13 insight that replaced "Preload Largest Contentful Paint image" and "Largest Contentful Paint image was lazily loaded". It checks whether your LCP image, the big photo your visitors wait for, is discoverable from the HTML: whether the browser could start downloading it the moment the HTML arrived, with high priority. The fix: the photo as an <img> in the HTML, without loading="lazy", with fetchpriority="high".
Table of Contents!
What do the three LCP request discovery checks mean?
In Lighthouse 13 and PageSpeed Insights the notice reads: "Optimize LCP by making the LCP image discoverable from the HTML immediately, and avoiding lazy-loading". Under it are three checks, each green or red.

The notice for a hotel home page whose big photo has loading="lazy". Lighthouse 13.6 with DevTools throttling.
- fetchpriority=high should be applied: the browser requested your LCP image without
fetchpriority="high". When the photo came through a preload, the check reads "fetchpriority=high should be applied to the image preload request": the preload needs it too. When it passes, it reads "fetchpriority=high applied". - Request is discoverable in initial document: the photo's URL is in the HTML itself, in an
<img>or a preload, where the preload scanner (the part of the browser that reads ahead through the HTML) finds it. A background image in a stylesheet, a slider that builds its slides with JavaScript or a lazy-load script that moved the URL intodata-srcturns this check red. - LCP resources shouldn’t use loading=lazy: the photo has
loading="lazy", so the browser asks for it only once the layout shows it is on screen.
One red check makes the notice red. The LCP element at the bottom, a thumbnail with its HTML, shows which element Lighthouse measured on a phone screen. Unscored means the notice adds no points by itself, but LCP counts for a quarter of your Performance score, and Google ranks on what your real visitors get. The notice only appears when your LCP element is an image: an <img>, a CSS background or a video poster.
Why does a late LCP image make the page slow?
On a phone, your visitor sees the headline and the text around an empty block where the big photo goes, for a second or more.
While the HTML downloads, Chrome's preload scanner reads ahead through it and requests every image in an <img> src or srcset without loading="lazy": the earliest a photo can start. Any other photo starts later: in a stylesheet it waits for that file and the layout; in a style attribute or with loading="lazy" it waits for the layout, which needs every render-blocking stylesheet first; a slider or lazy-load script has to download and run before it asks for the photo.
That wait, the resource load delay, usually takes longer than the download: at the median site with a poor LCP, the image waits 1,290 ms and then downloads in 350 ms (web.dev).
On a hotel home page I built like a WordPress site with a page builder, I put the same photo on the page in seven ways and loaded each on a throttled phone:
| The photo is | Requested | LCP |
|---|---|---|
an <img> with fetchpriority="high" | 0.59 | 2.02 |
| a background, with a preload | 0.59 | 2.03 |
an <img> with loading="lazy" | 1.73 | 3.64 |
| a background in the stylesheet | 1.71 | 3.62 |
an <img> a lazy-load script fills in | 2.44 | 3.98 |
| a background in a style attribute | 1.70 | 4.16 |
| a slide a slider script builds | 2.43 | 4.63 |
Medians of five loads, in seconds, on Slow 4G with a 4x slower CPU. The HTML arrived at 0.58 s every time.
Every version loaded the same 63 kB photo, except the style attribute, which can't switch to the smaller phone file. When the request started made the difference: the photo in the HTML was requested as soon as the HTML arrived, the others waited for the first paint at 1.7 s or the scripts at 2.4 s.

Before: loading="lazy"

After: no loading="lazy", fetchpriority="high"
The hotel page 2.5 seconds into the load on the same throttled phone.
fetchpriority="high" tells Chrome from the first moment that this image matters, so it gets more of the connection. On a busy page, where the photo competes with dozens of scripts and stylesheets, that can make LCP up to 30% faster; Google measured 2.6 to 1.9 s on Google Flights. It helps only a photo the browser has found: a photo in a stylesheet or a script needs the change in the HTML first.
Why is fetchpriority=high still red when the image has it?
The check looks at the request that loaded your LCP image. Search the page source, logged out, for the photo's file name. The usual causes:
- A preload you didn't write. A theme, host or CDN can send a preload for the photo in a Link header or in 103 Early Hints; a cache plugin or Next.js adds a
<link rel="preload">to the head. For a header, open the Network panel in DevTools, click the first request (the page itself) and read its Headers. Then add fetchpriority="high" to that preload or switch it off. - A lazy-load plugin rewrote the image. When the discoverable check is red too, look for data-src or data-lazy-src on the photo: WP Rocket, Perfmatters and LiteSpeed Cache move the URL there and let a script request the photo later. Exclude the photo from lazy loading.
- WordPress gave the attribute to another image. WordPress adds fetchpriority="high" to the first large image in the first screen (50,000 pixels or more). A logo uploaded at double size, say 600 by 200 pixels, comes first and takes it. Upload the logo at the size it shows.
- Lighthouse measured a different image. The LCP element at the bottom of the notice shows which one. On a phone it can be a separate mobile hero, with the desktop photo hidden by CSS. Use one photo for both screens, or one
<picture>with a<source>for the phone file and fetchpriority="high" on its<img>, so the photo on screen is the one with the attribute.

The hotel page with a lazy-load script: two red checks. Lighthouse 13.6 with DevTools throttling.
How long do your visitors wait for the LCP image?
Your field data shows how long real visitors wait. In CoreDash, open the LCP Breakdown for mobile and pick LCP Priority under More dimensions: each row is one way the LCP image was loaded, with its p75 LCP split into parts. The green part is the load delay, the wait between the HTML arriving and the image starting to download. Group by URL to find the template where it is long.

Lazy-loaded LCP images take 5.4 seconds on phones, most of it load delay.
According to the State of Web Vitals, an LCP image with loading=lazy starts downloading about 190 ms later on phones than one without.
How do you see in DevTools how late the image started?
Record a trace of the page in the Performance panel of Chrome DevTools and open LCP request discovery in the Insights sidebar. On my hotel test page, with the photo as a background in the page builder's stylesheet, the insight shows "LCP image loaded 1,552 ms after earliest start point": the photo's request started that long after the HTML's first byte, the moment it could have started. The striped bar in the Network track marks that wait.

The photo's request starts after the stylesheets. Chrome DevTools, Performance panel, throttled phone.
In the Network panel, the Initiator column next to the photo names the file that requested it: a stylesheet, a slider script, or the HTML when it started on time.
How do you fix LCP request discovery?
Find the photo's file name in the page source. In an <img> src or srcset the browser finds it early; in data-src, a stylesheet or nowhere, that is what to change. The goal everywhere: the photo as an <img> in the HTML, without loading="lazy", with fetchpriority="high", on that one image.
WordPress and lazy-load plugins
WordPress keeps the first images out of lazy loading and gives the first large one fetchpriority="high". When the notice is still red, a plugin usually overrides this:
- WP Rocket: Optimize Critical Images, on by default, learns the LCP image from real visits, preloads it with fetchpriority="high" and keeps it out of LazyLoad. Test again after the cache is rebuilt.
- Perfmatters: set Exclude Leading Images and Preload Critical Images to the number of images in the first screen on a phone, often one.
- LiteSpeed Cache: add the photo's file name to Lazy Load Image Excludes, or switch on Viewport Images.
- FlyingPress: check that the photo has loading="eager" and a preload; if not, exclude it from lazy loading.
Keep one lazy loader, or the photo stays lazy after you excluded it in one. In the Cover block, Fixed background turns the photo into a background in a style attribute: switch it off and the photo is an <img> again. My plugin WP Core Web Vitals learns the LCP image per screen size from your visitors and loads it first, with high priority.
Elementor and other page builders
A photo set as the background of an Elementor Container or Section ends up in Elementor's CSS, so the browser finds it only after that CSS and the layout. Use an Image widget for the hero photo (an Elementor hero with an image); Optimized Image Loading (Settings, Performance) then handles it the way WordPress does. Lazy Load Background Images, on by default, can hold back a background hero that sits under a notice bar. In other builders, too, use an image element for the first photo.
Sliders
The first slide needs to be an <img> in the HTML, without loading="lazy", with fetchpriority="high"; the other slides get loading="lazy" and fetchpriority="low". A slider that builds its slides with JavaScript starts the first slide only after that script has run: use one that prints the first slide in the HTML, or show one photo on phones. In Elementor's Image Carousel, the Lazyload switch puts every slide's URL in data-src: switch it off.
Shopify
Dawn, Horizon and the themes built on them give the image in a template's first section fetchpriority="high" and load it right away, so make the banner or slideshow the first section. On a Dawn product page the main photo lacks fetchpriority: in snippets/product-thumbnail.liquid, add fetchpriority: 'high' to the image_tag when lazy_load is false (the first photo). A hero an app builds with JavaScript starts late whatever the theme does: use a theme section.
In other themes, look in the section's file for loading: 'lazy' or a lazyload class with data-src, and key the priority on the section's place:
{%- liquid
assign fetch_priority = 'auto'
if section.index == 1
assign fetch_priority = 'high'
endif
-%}
{{ section.settings.image | image_url: width: 1600 | image_tag: widths: '750, 1100, 1600', sizes: '100vw', fetchpriority: fetch_priority }} Without a loading parameter, image_tag lazy-loads images from the fourth section on.
CSS background images
Turn the background into an <img> first: the browser then finds it in the HTML, and srcset lets every screen pick its own file. object-fit makes it fill the space the way the background did:
<section class="hero">
<img class="hero-img" src="/wp-content/uploads/2026/10/terrace-1024.jpg"
srcset="/wp-content/uploads/2026/10/terrace-768.jpg 768w, /wp-content/uploads/2026/10/terrace-1024.jpg 1024w, /wp-content/uploads/2026/10/terrace-1600.jpg 1600w"
sizes="100vw" width="1600" height="1067" alt="Terrace above the sea" fetchpriority="high">
</section>
.hero { position: relative; }
.hero-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; } When it has to stay a background, preload the file the CSS picks per screen size, with the CSS's media queries and fetchpriority="high"; a preload for another file downloads the photo twice. Add it to that page's template only. For CSS that switches to the 768 px file below 768 px:
<link rel="preload" as="image" href="/wp-content/uploads/2026/10/terrace-768.jpg" media="(max-width: 767px)" fetchpriority="high">
<link rel="preload" as="image" href="/wp-content/uploads/2026/10/terrace-1600.jpg" media="(min-width: 768px)" fetchpriority="high"> Next.js, Astro and React
next/image lazy-loads by default. Since Next.js 15, priority (preload in 16) makes the image eager and preloads it without fetchpriority, so the check stays red. Set both yourself, without priority:
<Image src={hero} alt="Terrace above the sea" sizes="100vw" loading="eager" fetchPriority="high" /> In Astro 5.10 and later, the priority prop on <Image> sets both. A hero that React renders in the browser exists only after the JavaScript has run: render it on the server or prerender the page, so the <img> is in the HTML.
A hero you can't change
An A/B test that swaps the photo or a widget that builds the hero with JavaScript starts it late. When the photo's URL stays the same, a preload with fetchpriority="high" in your own template starts it early. On a slow server, 103 Early Hints can start a photo that is the same file on every screen before the HTML arrives.
Does the LCP image now start with the HTML?
Run Lighthouse again: three green checks, and your photo as the LCP element. In DevTools the photo's request starts right after the HTML. Passed, and LCP still slow? Look at the other parts of LCP: a slow server (time to first byte), a photo that takes long to download (load duration), or stylesheets and scripts that hold the paint (render delay). For real visitors, watch the load delay on phones in CoreDash; Search Console takes 28 days.
A Core Web Vitals power hour is for the photo this page can't reach: one placed by a page builder, slider or app that has no setting for it, or one that passes all three checks while LCP on phones stays slow. We follow it through a trace of your own page, from the HTML to the screen, and find what holds it back.
CoreDash has MCP built in.
Connect it to Claude or any AI agent. Ask it why your INP spiked last Tuesday.
See how it works