Learn Measure Blog Live About

First Contentful Paint (FCP)

Updated
Appears in: Metrics

First Contentful Paint (FCP) is an important, user-centric metric for measuring perceived load speed because it marks the first point in the page load timeline where the user can see anything on the screen—a fast FCP helps reassure the user that something is happening.

What is FCP?

The First Contentful Paint (FCP) metric measures the time from when the page starts loading to when any part of the page's content is rendered on the screen. For this metric, "content" refers to text, images (including background images), <svg> elements, or non-white <canvas> elements.

FCP timeline from google.com

In the above load timeline, FCP happens in the second frame, as that's when the first text and image elements are rendered to the screen.

You'll notice that though some of the content has rendered, not all of it has rendered. This is an important distinction to make between First Contentful Paint (FCP) and Largest Contentful Paint (LCP) —which aims to measure when the page's main contents have finished loading.

How to measure FCP

FCP can be measured in the lab or in the field, and it's available in the following tools:

Field tools

Lab tools

Measure FCP in JavaScript

The easiest way to measure FCP (as well as all Web Vitals field metrics is with the web-vitals JavaScript library, which wraps all the complexity of manually measuring FCP into a single function:

import {getFCP} from 'web-vitals';

// Measure and log the current FCP value,
// any time it's ready to be reported.
getFCP(console.log);

To manually measure FCP, you can use the Paint Timing API. The following example shows how to create a PerformanceObserver that listens for paint timing entries and logs the start time of the first-contentful-paint entry to the console:

// Keep track of whether (and when) the page was first hidden, see:
// https://github.com/w3c/page-visibility/issues/29
// NOTE: ideally this check would be performed in the document <head>
// to avoid cases where the visibility state changes before this code runs.
let firstHiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity;
document.addEventListener('visibilitychange', (event) => {
firstHiddenTime = Math.min(firstHiddenTime, event.timeStamp);
}, {once: true});

// Sends the passed data to an analytics endpoint. This code
// uses `/analytics`; you can replace it with your own URL.
function sendToAnalytics(data) {
const body = JSON.stringify(data);
// Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
(navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) ||
fetch('/analytics', {body, method: 'POST', keepalive: true});
}

// Use a try/catch instead of feature detecting `paint`
// support, since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
function onPaintEntry(entry, po) {
// Only report FCP if the page wasn't hidden prior to
// the entry being dispatched. This typically happens when a
// page is loaded in a background tab.
if (entry.name === 'first-contentful-paint' &&
entry.startTime < firstHiddenTime) {
// Disconnect the observer.
po.disconnect();

// Report the FCP value to an analytics endpoint.
sendToAnalytics({fcp: entry.startTime});
}
}

// Create a PerformanceObserver that calls `onPaintEntry` for each entry.
const po = new PerformanceObserver((entryList, po) => {
entryList.getEntries().forEach((entry) => onPaintEntry(entry, po));
});

// Observe entries of type `paint`, including buffered entries,
// i.e. entries that occurred before calling `observe()` below.
po.observe({
type: 'paint',
buffered: true,
});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}

What is a good FCP score?

To provide a good user experience, sites should strive to have First Contentful Paint occur within 1 second of the page starting to load. To ensure you're hitting this target for most of your users, a good threshold to measure is the 75th percentile of page loads, segmented across mobile and desktop devices.

How to improve FCP

To learn how to improve FCP for a specific site, you can run a Lighthouse performance audit and pay attention to any specific opportunities or diagnostics the audit suggests.

To learn how to improve FCP in general (for any site), refer to the following performance guides:

CHANGELOG

Occasionally, bugs are discovered in the APIs used to measure metrics, and sometimes in the definitions of the metrics themselves. As a result, changes must sometimes be made, and these changes can show up as improvements or regressions in your internal reports and dashboards.

To help you manage this, all changes to either the implementation or definition of these metrics will be surfaced in this CHANGELOG.

Last updated: Improve article