These docs are a work in progress: some pages may still be incomplete or contain inaccuracies.
fastmon Docs
Web Vitals

Largest Contentful Paint (LCP)

What LCP is, what's a good LCP, and how to debug a slow one, with fastmon's data.

LCP measures how long it takes for the largest visible element on a page to actually show up. When someone says "the page felt slow to load," they're usually talking about LCP: the moment when something meaningful is finally on screen.

LCP is part of Core Web Vitals, Google's standard user-experience set, and it counts toward search ranking.

What's a good LCP?

LCP is reported in milliseconds and bucketed into three ranges. The threshold to track is the 75th percentile across page-views; that's how Google reports it, and it's the number you should optimize against.

LCP at p75Rating
≤ 2,500 msGood
≤ 4,000 msNeeds improvement
> 4,000 msPoor

If your p75 is 2,500 ms or below, three out of four visitors had a load experience Google calls good. If it's 4,000 ms or above, one in four sat there for more than four seconds before the page felt ready.

What counts as the "largest contentful element"

The browser tracks the largest element that has finished painting in the visible viewport. Eligible elements are:

  • <img> and <image> inside <svg>
  • <video> (the poster frame)
  • An element with a background-image set via CSS
  • Block-level text nodes

The "size" is the rendered area on screen, intersected with the viewport. Off-screen content does not count, even if it's bigger.

The "largest" can change as the page loads. The browser keeps emitting LCP entries until the user interacts with the page (clicks, scrolls, or keys). The last entry before that interaction is the LCP value.

When LCP is reported

LCP is finalized:

  • when the user scrolls, clicks, or presses a key (whichever comes first), or
  • when the page becomes hidden (visibilitychange).

Fastmon's tracker picks up the final LCP at that moment and includes it in the next batched payload.

Examples

Marketing page with a hero image. LCP is almost always the hero <img>. If the image is below the fold or lazy-loaded, LCP ends up as a text block, usually faster.

SaaS dashboard with a skeleton loader. LCP is the skeleton container until real content paints, then it jumps to the largest data element. Watch out for falsely "fast" LCPs caused by a chunky skeleton box.

Article with embedded video. LCP is the video poster, not the article text. Optimizing the poster image improves LCP, even though it's the article body the visitor actually reads.

How to see LCP in fastmon

The dashboard's Performance section shows LCP at p50, p75, and p95 out of the box. To break it down:

  • By URL: Performance → group by URL. Find the worst pages first.
  • By device: group by device_type. Mobile LCP is almost always worse than desktop.
  • By country: group by country. RTT to your origin matters.
  • By release: set compare_to_release_id in the Analytics API to see whether a deploy regressed LCP.

Programmatically:

curl https://api.fastmon.eu/v1/organizations/$ORG/analytics/query \
  -H "Authorization: Bearer fm_$TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "time_range": { "from": "2026-05-01T00:00:00Z", "to": "2026-05-07T00:00:00Z" },
    "metrics": ["lcp"],
    "aggregations": ["p75"],
    "group_by": { "granularity": "day", "dimensions": ["url"] }
  }'

How to improve a slow LCP

LCP usually breaks down into one of four contributors. The fastmon dashboard surfaces each; start with the one with the largest share.

  1. TTFB. If your time to first byte is already >1,500 ms, no amount of front-end optimization will save your LCP. Cache HTML at the edge, or render statically.
  2. Resource load delay. The LCP image isn't requested early enough. Preload it (<link rel="preload" as="image">) or move it above the fold in the HTML.
  3. Resource load duration. The LCP image is too big or served slowly. Use modern formats (AVIF/WebP), serve responsive sizes via srcset, and put it on a CDN close to your visitors.
  4. Element render delay. The browser has the bytes but is blocked by render-blocking CSS or JavaScript. Inline critical CSS, defer non-critical scripts.

For a deeper walkthrough, see web.dev's Optimize LCP; the underlying optimization advice is the same regardless of which RUM tool you use.

Common surprises

  • LCP is usually an image, not text. Tweaking fonts probably won't move your LCP at all.
  • SPAs don't restart LCP on route change. LCP is a navigation-level metric; SPA route changes don't produce a new one.
  • Lazy-loading the hero kills LCP. Classic copy-paste mistake. Don't lazy-load above-the-fold content.
  • background-image counts. If your "hero" is a CSS background, the browser still measures it as LCP.

What's next

On this page