Largest Contentful Paint Test: How to Check and Fix LCP
Find out when the biggest part of your first screen appears, what a good LCP time is, and which fixes move the number fastest.
Free to use 19 min read Updated Oct 2026
Largest contentful paint in one minute
Quick answer: Largest contentful paint (LCP) is the time from the start of navigation until the biggest image or text block in the first screen is painted. Our report wants that moment at 2.5 seconds or sooner on a desktop lab run.
- Pass: 2.5 seconds or less. A reading of exactly 2.5 still passes.
- Warning: above 2.5 and up to 4.0 seconds, which earns no score.
- Fail: above 4.0 seconds, or no LCP value found at all.
- Fix: find the LCP element, make it load early and small, then remove whatever blocks its first paint.
One honest note before you start. Our report reads a single desktop lab run, while Google judges the 75th percentile of real visits across many devices. The two often disagree.
What is largest contentful paint (LCP)?
Among the three Core Web Vitals, LCP is the one about loading, while cumulative layout shift covers stability and interaction to next paint covers responsiveness. Where the other two describe stability and responsiveness, LCP answers a simpler question: how soon does the main content of this page look ready to a person?
The easiest way to understand the metric is to watch a page load. The browser doesn't know in advance which element is the main one. It reports a new candidate every time something larger than the previous best gets painted, so the final LCP is the last candidate recorded before the page settles. A logo might be the first candidate at 0.6 seconds, a heading the next at 1.1, and a full width photo the last at 3.2. The photo's time is your LCP. Size means the visible area inside the viewport. For an image the browser uses the smaller of the displayed size and the file's own dimensions, so stretching a small file across the screen does not make it count as bigger.
Two other numbers get confused with LCP. First contentful paint (FCP) fires as soon as anything is painted, even a logo, so it can be quick while the main content is still missing. Page load time ends at the load event, which also waits for images below the fold, so it can finish well before or after the hero paints. Our page load time check covers that whole-page number.
Which elements can be the LCP element
Only a short list of element types can become the LCP element. The browser looks at these when it hunts for the largest item in the first screen:
- Images. A standard
imgelement counts, and so does an image placed inside an inline SVG. - Video posters. The poster image of a
videoelement is a candidate, which matters on pages with an autoplaying header clip. - CSS background images. An element whose background is loaded through
url()counts, although gradients do not. - Text blocks. Block level elements that contain text, such as a paragraph or a large heading, can win.
Some things are ignored on purpose. Elements with an opacity of 0, images that stretch across the entire viewport and behave like a backdrop, and very low detail placeholder images are all skipped. That is why a plain text landing page often has a heading as its LCP element: nothing bigger competes with it.
When the LCP value is final
New candidates keep arriving until the visitor taps, scrolls or presses a key, or until the page is unloaded. Browsers stop reporting at that first input because interaction can change what is on screen. Pages opened in a background tab are not reported until the visitor switches to them, so the number reflects what the person actually saw rather than the load.
Our run reads the value right after the load event, while field data keeps collecting candidates until the visitor first taps or scrolls. That, plus slower real devices, is why the two can disagree. A hero that paints at 2.1 seconds in a desktop lab run can take 3.6 seconds on a mid range phone, and both readings are honest.
What is a good largest contentful paint score?
Google publishes three bands for LCP. Assessment is done on the 75th percentile of page loads, which means at least three out of four visits have to be good for a page group to count as good. Mobile and desktop visits are assessed separately, so a fast desktop site can still fail on phones.
| Rating | LCP time | What it means | Our report |
|---|---|---|---|
| Good | 2.5 s or less | Main content appears quickly for most visits | Pass |
| Needs improvement | Above 2.5 s, up to 4.0 s | Noticeable wait, worth fixing | Warning, no score |
| Poor | Above 4.0 s | Most visitors wait a long time for the main content | Fail |
Our report applies the same two numbers to one lab run. It reads the rounded seconds value, and the edge values are spelled out in the rules table below. If you are chasing a good LCP score, leave some headroom below 2.5 seconds in the lab, because real devices are usually slower than a data center browser.
How our largest contentful paint test works
The rule: we load your page in headless Chromium at 1280 by 720, read the start time of the last largest-contentful-paint entry after the load event, round it to two decimals in seconds, and pass it at 2.5 s or less. Above 2.5 s and up to 4.0 s is a warning. Above 4.0 s, or no value, fails.
- Pass: 2.5 seconds or less in our single desktop run.
- Warning: above 2.5 and up to 4.0 seconds, no score.
- Fail: above 4.0 seconds, or no LCP entry recorded.
- Not tested: mobile throttling, repeat runs, real visitor data, any candidate that paints after the load event, which element was the largest, and how the time splits into the four parts.
What the checker measures
The report opens your URL in headless Chromium on our server, driven by Playwright. The window is a plain 1280 by 720 desktop viewport, with no network throttling, no CPU throttling and no device emulation. It is one run, not an average.
Before any of your page scripts execute, the checker registers a PerformanceObserver for largest-contentful-paint entries with buffering switched on. The start time of the last entry it received becomes your LCP. The page is loaded until the load event, with a 20 second limit, and the value is read straight after that event.
That last detail matters. A candidate that appears after the load event, such as a hero image injected late by a script, is not counted. The milliseconds are converted to seconds and rounded to two decimals before they are compared with the limits and printed in the report.
Pass, warning and fail rules
The rounded seconds value is compared with two limits, and both are written as "above". That is why a reading of exactly 2.5 passes and exactly 4.0 is still only a warning.
| Rounded seconds | Status | Score effect | What you see |
|---|---|---|---|
| 2.5 or less | Pass | Counts toward the score | Green icon and the seconds |
| Above 2.5, up to and including 4.0 | Warning | No points | Alert box, seconds, How to Fix button |
| Above 4.0 | Fail | No points | Alert box, seconds, How to Fix button |
| Missing or zero | Fail | No points | Alert box with a blank seconds field |
Scoring counts passed checks over total checks. A warning is not the worst grade, but it earns no points, so moving from 2.8 seconds to 2.4 raises your report score even though the change feels small.
The missing value rule deserves a word. If the browser never recorded an LCP entry, or recorded a value of zero, for example because the page showed nothing visible to a plain headless browser, the check fails and the seconds field stays blank. Confirm the page renders content without a login or a consent wall, then run the report again. If a firewall or bot challenge sits in front of your site, any lab tool may be measuring that page instead of yours.
What you see in the report
On a pass you get a green icon, the word Congratulations and the measured seconds. On a warning or a fail you get an alert box showing the seconds plus a red How to Fix button, and the same instructions are written out further down this page. The report shows seconds and status only. It does not name the winning element or split the time into its four parts, so the measuring section below is your next step.
Why your number may differ from other tools
Our server sits in a data center with a fast connection, so network time is shorter than what a phone on mobile data sees. The viewport is desktop sized, which can change which element is the largest. Every run also starts with a cold cache, so no image or script saved from an earlier visit helps it along.
Mobile lab tools do the opposite on purpose. They slow the CPU and the network to imitate a mid range handset, so their LCP is usually higher than ours. Treat our number as a quick lab signal that tells you whether something is badly wrong, then confirm it in field data.
Why largest contentful paint matters for SEO
Google recommends good Core Web Vitals for success in Search, and its guidance on page experience says plainly that relevance still comes first. A fast page that fails to answer the query will not beat a slower page that does. Treat LCP as a tiebreaker and a visitor win, not a ranking switch. Google explains its position in the Google Search Central Core Web Vitals documentation. In Search Console, the Core Web Vitals report groups URLs as good, needs improvement or poor from field data, which turns LCP into a concrete to do list.
Visitors judge speed by when the hero appears above the fold, not by when the last tracking pixel fires. A late hero reads as a blank or broken page, and some people leave before it arrives. LCP also carries 25 percent of the Lighthouse performance score in current versions, more than first contentful paint, so a slow LCP drags that score down hard. Lighthouse also weighs total blocking time, speed index and cumulative layout shift (CLS), while interaction to next paint (INP) is a field metric.
LCP is only one of three vitals, and a slow server tends to drag the others down too, so the Core Web Vitals guide is the better place to see how they fit together.
The four parts of a largest contentful paint time
An LCP time is not one lump. It is the sum of four consecutive parts, and knowing which one is biggest tells you where to spend your effort. Google's guidance suggests a healthy split of roughly 40 percent for time to first byte, under 10 percent for resource load delay, roughly 40 percent for resource load duration and under 10 percent for element render delay. Google itself calls these figures guidelines, not strict rules, and they describe a well optimized page rather than the average one.
| Part | What it covers | Usual cause | First fix |
|---|---|---|---|
| Time to first byte | Navigation start until the first byte of HTML arrives | Slow hosting, redirects, no page cache | Page caching and a nearby server |
| Resource load delay | First byte until the browser starts fetching the LCP resource | Image hidden in CSS or script, lazy loading | Put the image in the HTML |
| Resource load duration | Download time of the LCP image itself | Oversized or uncompressed file | Resize and use WebP or AVIF |
| Element render delay | Resource finished until the element is painted | Blocking CSS or JavaScript, client side rendering | Defer scripts, inline critical CSS |
Take a page that scores 4.0 seconds. The server wait is 2.4 seconds, the load delay 0.2, the download 1.0 and the render delay 0.4. That puts the server at 60 percent of the total, far above the roughly 40 percent Google recommends, so start with caching and hosting. The download is 25 percent of the total, already below the 40 percent guideline, so even a perfect image would save at most about a second. The server wait is the bigger prize, so fix it first, then come back to the image. Cut that wait to 1.0 second and the page lands at about 2.6 seconds, which is still a warning. The download and the render delay are the next slices to trim, re-testing after each.
If the LCP element is plain text drawn in a system font, there is no resource to download. The two middle parts are close to zero, and the time is simply server response plus render delay. A slow text only page therefore points at the server or at blocking code. If the heading waits on a web font, the font download shows up in the middle parts instead.
How to measure largest contentful paint and find the LCP element
No single tool tells the whole story. You want a lab number, a field number, and the element behind both. Test both a cold and a warm load, and repeat each lab run a few times, since 2.4 once and 2.9 next time is normal.
- Start with the free report. Run our free SEO report and note the seconds and the status.
- Open PageSpeed Insights. Read the field data panel first, because it shows real visits at the 75th percentile, then scroll to the lab section and the LCP element diagnostic.
- Record in Chrome DevTools. In the Performance panel, record a page reload and click the LCP marker to see the element, and open the LCP breakdown or insight in recent DevTools builds to see the four parts.
- Check Search Console. The Core Web Vitals report shows which groups of URLs are poor in field data, so you know whether the problem is one page or a whole template.
- Log it yourself. Paste the console snippet below if you want the raw start time and the element in plain view.
Field data versus lab data
Field data comes from the Chrome User Experience Report (CrUX), which collects measurements from real Chrome users, and it is what Google uses to judge your site. Lab data comes from a controlled run like ours and is the right tool for debugging, because you can repeat it after every change. WebPageTest is a handy extra for repeat lab runs from different locations. Small or new sites often show no field data yet, so rely on repeated lab runs until it appears.
The two can differ by whole seconds, because real devices and networks are worse than a lab setup and field data keeps recording until the first input. When they disagree, believe the field number for ranking and the lab number for finding causes.
Find the element with a console snippet
Open DevTools on the page, switch to the Console and paste this. It replays the buffered entries and prints the start time and the element of the latest candidate. The LargestContentfulPaint API reference documents every property on the entry.
new PerformanceObserver(function (list) {
var entries = list.getEntries();
var last = entries[entries.length - 1];
console.log('LCP', Math.round(last.startTime) + ' ms', last.element);
}).observe({ type: 'largest-contentful-paint', buffered: true });Hover over the logged element and Chrome highlights it on the page. For the phone version, turn on the device toolbar and run it again, because the element can differ.
How to improve largest contentful paint, step by step
The rule of thumb is simple: fix the biggest subpart first, change one thing at a time and re-test after each change. Shaving 300 milliseconds off an image does nothing when the server takes two seconds to answer. The advice below follows the same four part model that Google's guide to optimizing LCP describes in more depth.
The order below is the default, and your measured biggest subpart overrides it:
- Find the biggest part. Open the LCP breakdown in Chrome DevTools and note which of the four slices holds the most seconds.
- Fix server time. Check time to first byte in PageSpeed Insights. If it is well above 40 percent of the total, caching and redirects come first.
- Make the image discoverable. View the page source and search for the hero file name. If it is missing there, the browser cannot start the download early.
- Shrink it. Compare the downloaded file size in the DevTools Network tab with the size the image occupies on screen.
- Clear blocking work. Look at what loads in the head before the hero paints.
Cut server response time (TTFB)
A good time to first byte is around 800 milliseconds or less. Switch on full page caching so the server stops rebuilding the same HTML for every visit, remove redirect chains such as http to https to www, and consider faster hosting or a region closer to your audience. Our explainer on hosting speed and rankings shows what to look for.
A CDN can also cache the HTML itself at the edge, not just images. Our CDN usage test tells you whether one is already in front of your site.
Make the LCP resource discoverable early
Put the main image in the initial HTML as a normal img element, not injected by a script and not set as a CSS background image. Give that one image fetchpriority="high" and never loading="lazy".
When the hero is genuinely only reachable through CSS or script, add a preload link so the browser fetches it during the first parse. Preload sparingly, because ten preloads mean the LCP image competes with nine others.
Here is the markup to aim for on a hero image found in the HTML:
<img src="/img/hero-1200.webp"
srcset="/img/hero-600.webp 600w, /img/hero-1200.webp 1200w, /img/hero-1800.webp 1800w"
sizes="(min-width: 1024px) 1200px, 100vw"
width="1200" height="600"
fetchpriority="high"
alt="Team reviewing a site audit">And this is the preload for a hero that only appears through CSS or script:
<link rel="preload" as="image"
href="/img/hero-1200.webp"
imagesrcset="/img/hero-600.webp 600w, /img/hero-1200.webp 1200w, /img/hero-1800.webp 1800w"
imagesizes="(min-width: 1024px) 1200px, 100vw"
fetchpriority="high">For a CSS background, set href to the exact URL the stylesheet requests. Use imagesrcset and imagesizes only when the same hero is also an img with srcset, and keep them identical to it. If they differ, the browser may download two files and delay the element you are speeding up.
Shrink the LCP image
Serve the pixel size the screen needs with responsive images, meaning srcset and sizes, so a phone never downloads the 2400 pixel desktop version. Convert to WebP or AVIF and compress the result; our free image compressor and WebP converter do both in the browser, and the modern image formats check shows which files on your page still ship as heavy JPEG or PNG. An image CDN that resizes on request achieves the same without manual exports.
Remove render blocking work
Inline the small amount of critical CSS the first screen needs, then load the rest without blocking. Add defer to scripts that depend on the DOM or on each other, and use async only for independent scripts such as an analytics tag, because async scripts run in whatever order they arrive. Trim third party tags that run before the hero. The render blocking resources guide lists what to look for.
Fix text and font based LCP
When the heading is the LCP element, a web font can hold it back. Use font-display: swap or optional, subset the font to the characters you use, and preload the one file the heading needs. A font preload must carry the crossorigin attribute, even for fonts on your own domain, or the browser fetches the file twice. For the hero heading text specifically, a system font stack is a legitimate choice, and it costs nothing to download.
Avoid client side rendering for the hero
If the first screen is built in the browser after a large JavaScript bundle runs, the element render delay balloons. A page that ships only a bare <div id="root"></div> has no LCP candidate until the bundle has run, so all of that time lands in the render delay. Use server side rendering, or prerender the first screen, so the hero exists in the HTML.
Re-test after every change
Run the free report again after each single change and compare the seconds, so you know which edit helped. If two changes go live together, you won't know which one earned the drop. Field data lags weeks behind your edits, so give it time before you judge.
Largest contentful paint fixes for WordPress, Shopify and custom sites
Platforms put different levers within reach. Check the rendered HTML for the hero image tag rather than trusting the settings screen.
WordPress
WordPress 6.3 and later adds fetchpriority="high" to the first large image automatically, and the pixel minimum can be changed with the wp_min_priority_img_pixels filter. A hero set as a CSS background does not get it, so check the output. Use a page cache, pick one image optimization approach, and avoid sliders on the first screen.
Shopify
The image_tag Liquid filter has a preload option that sends a preload hint in the response header. It also passes extra attributes through, so give the hero loading: 'eager' and fetchpriority: 'high'. Themes differ, so check the generated markup in view source to confirm the fetchpriority attribute actually appears on the img tag.
{{ section.settings.hero | image_url: width: 1500
| image_tag: preload: true, loading: 'eager', fetchpriority: 'high',
widths: '600, 900, 1200, 1500', sizes: '100vw' }}Replace section.settings.hero with the image object your theme section already uses. The preload: true option only sends the header and leaves the img tag alone, which is why loading and fetchpriority are passed separately.
Custom or static sites
Open the layout or page template, find the hero img, add fetchpriority="high" plus the width and height, delete any loading="lazy" on it and serve a modern format at the right widths. No plugin rewrites your tags on a static site, so view the live source once after deploying to confirm the browser gets exactly what you wrote.
Common largest contentful paint mistakes
Lazy loading the hero image is the classic one. It tells the browser to wait before fetching the single download that matters most, and the delay lands directly on your LCP. A close second is setting the hero as a CSS background, because the browser then discovers it only after the stylesheet is parsed.
Sliders and carousels cause trouble when they wait for script before showing the first slide, which pushes the render delay up. Serving a desktop sized image to every phone, or skipping compression on a hero photo, inflates the load duration.
A cookie banner or large overlay can also become the LCP element, and then the fix is to shrink it. Two more traps are about honesty rather than technique. Tuning only the lab number while field data stays slow improves the report, not the visit. And removing the hero image to pass is a worse page that happens to score better.
Largest contentful paint checklist
- Element identified. You know which element is the LCP element and have checked it in the rendered HTML.
- Priority set. The hero image has fetchpriority high and no lazy loading.
- Image trimmed. It is sized for the screen, compressed and served as WebP or AVIF.
- Server quick. Caching is on and redirects are trimmed.
- Nothing blocking. No render blocking script or style sits ahead of the first screen.
- Verified twice. You re-ran the report and checked field data after a few weeks.
How to Fix
The short version, the same steps you see when you click How to Fix in your report.
Why this fails: the biggest image or text block in your first screen was painted later than 2.5 seconds after navigation started. Between 2.5 and 4.0 seconds is a warning, and anything above 4.0 seconds is a fail. If the seconds value is blank, no largest element was detected, so confirm the page shows visible content to a plain headless browser and run the report again.
How to fix it: first find the LCP element with the PageSpeed Insights diagnostic or the Chrome DevTools Performance panel. It is usually the hero image or the main heading. Then work through these steps in order.
- Speed up the server by turning on full page caching and removing redirect chains.
- Put the hero image in the HTML itself, add fetchpriority high and remove any lazy loading from it.
- Resize the image to the displayed size, compress it and export it as WebP or AVIF.
- Add defer to scripts that block the first paint, load non-critical CSS later, and inline only the small critical CSS.
- Keep the hero out of client side rendering so it exists in the server response.
Hero image in the HTML:
<img src="/img/hero-1200.webp" width="1200" height="600"
srcset="/img/hero-600.webp 600w, /img/hero-1200.webp 1200w"
sizes="100vw" fetchpriority="high" alt="Describe the hero">If the hero is only discovered through CSS or script, add this preload as well:
<link rel="preload" as="image" href="/img/hero-1200.webp"
imagesrcset="/img/hero-600.webp 600w, /img/hero-1200.webp 1200w"
imagesizes="100vw" fetchpriority="high">Platform notes:
- WordPress: view the page source and confirm the hero img has fetchpriority high and no loading lazy. A CSS background never gets it.
- Shopify: pass loading: 'eager' and fetchpriority: 'high' to image_tag on the hero.
- Custom or static HTML: add the attributes in the template and serve modern formats.
Re-test: run our free report again and check that the LCP seconds read 2.5 or lower, then confirm in PageSpeed Insights field data after a few weeks. Google explains each part in the Optimize LCP guide on web.dev.
Frequently Asked Questions
What is a good largest contentful paint score?
How is largest contentful paint calculated?
What is the difference between LCP and first contentful paint?
How do I find my largest contentful paint element?
Why is my largest contentful paint score so high?
Does lazy loading hurt largest contentful paint?
How do I reduce largest contentful paint on WordPress?
See how your site scores right now
Paste your address into the free report, then use the How to Fix button on anything that needs work.
Free to use. Results in under a minute for most sites.