What FCP measures
The clock starts at navigation, not when the server responds. In field data FCP therefore includes unload time from the previous page, connection setup, redirects and Time to First Byte (TTFB). A slow server or a redirect chain raises FCP before the browser has received a single byte of HTML.
Lighthouse does not count content inside iframes towards FCP. The Paint Timing API may also not report paints from cross-origin iframes, so JavaScript measurement can be incomplete there.
FCP thresholds
The web.dev threshold applies to field data: the 75th percentile of visits, segmented by mobile and desktop. The Lighthouse thresholds apply to a single lab test on a given device profile.
In Lighthouse 10, FCP carries 10% of the Performance score, the same as Speed Index. TBT (30%) and LCP and CLS (25% each) weigh more.
| Source | Good | Needs improvement | Poor |
|---|---|---|---|
| web.dev (75th percentile of visits) | ≤ 1.8 s | 1.8–3.0 s | over 3.0 s |
| Lighthouse, mobile | 0–1.8 s | 1.8–3 s | over 3 s |
| Lighthouse, desktop | 0–0.9 s | 0.9–1.6 s | over 1.6 s |
FCP vs LCP vs TTFB
If a page shows a splash screen or a loading indicator, FCP can be fast while the user still sees nothing useful. That is why FCP diagnoses the start of loading, while perceived load speed is judged by LCP.
- TTFB measures when the first byte of the response arrives. It precedes FCP and LCP, which is why web.dev recommends a server response fast enough for the 75th percentile of users to get a good FCP.
- FCP measures when any content appears. That can be a logo, a heading or a loading indicator.
- LCP measures when the largest content element in the viewport appears. It answers whether the main content is there yet.
How to improve FCP
- Eliminate render-blocking resources. Stylesheets and synchronous scripts in <head> hold back the first paint until they have downloaded.
- Reduce TTFB and avoid multiple redirects. Every extra network hop pushes FCP back.
- Remove unused CSS and JavaScript, and minify what remains.
- Preconnect to required origins and preload key requests.
- Keep text visible while web fonts load. font-display: swap shows a system font straight away, which improves FCP and LCP, but the font swap can cause a layout shift (CLS).
- Keep request counts and transfer sizes low, shorten critical request chains and avoid an excessive DOM size.
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<style>
@font-face {
font-family: "Brand";
src: url("/fonts/brand.woff2") format("woff2");
font-display: swap;
}
</style>How to measure FCP
In the lab, FCP is reported by Lighthouse, the Chrome DevTools Performance panel and PageSpeed Insights. Field data comes from the Chrome UX Report (CrUX), which PageSpeed Insights also shows, or from your own RUM.
The simplest way to measure FCP with real users is the web-vitals library. It cannot, however, measure paints inside cross-origin iframes.
import { onFCP } from 'web-vitals';
// Logs FCP as soon as it is available
onFCP(console.log);First Contentful Paint (FCP) is the time from navigation start until the browser renders the first piece of page content: text, an image, an SVG element or a non-white canvas. It shows how quickly users see that the page has started loading.
According to web.dev, a good FCP is 1.8 seconds or less and a poor one is over 3.0 seconds, measured at the 75th percentile of visits. Lighthouse uses stricter desktop thresholds: up to 0.9 s is good and over 1.6 s is poor.
No. The Core Web Vitals are LCP, INP and CLS. FCP is a supporting metric that helps diagnose loading problems affecting LCP. In Lighthouse 10 it carries 10% of the Performance score.
FCP marks when any content appears, such as a logo or a loading indicator. LCP marks when the largest content element in the viewport is rendered, usually the hero image or the main heading.
The usual cause is render-blocking resources: stylesheets and synchronous scripts in <head>, or a web font that hides text until it downloads. In field data FCP also includes redirects and connection setup, so check the whole request chain.
Run a lab test in Lighthouse, Chrome DevTools or PageSpeed Insights. Real-user data is available from CrUX, for example in PageSpeed Insights, or you can collect it yourself with the web-vitals library and its onFCP function.
Sources & further reading
- web.dev: First Contentful Paint (FCP) docs
- Chrome for Developers: Lighthouse: First Contentful Paint docs
- Chrome for Developers: Lighthouse performance scoring docs
- web.dev: Web Vitals docs
- web.dev: Largest Contentful Paint (LCP) docs
- web.dev: Time to First Byte (TTFB) docs
- Chrome for Developers: Ensure text remains visible during webfont load docs