First Contentful Paint (FCP): What It Is, How to Measure and Fix It

Learn what First Contentful Paint measures, why it is not a Core Web Vital, and 15 proven techniques to make your pages render faster

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-03

First Contentful Paint (FCP) measures the time from when a page starts loading to when the browser renders the first piece of content from the DOM, such as text, an image, or an SVG. A good FCP score is below 1.8 seconds at the 75th percentile. FCP is not a Core Web Vital but serves as an important diagnostic metric for perceived loading speed.

Important: FCP is not one of the three Core Web Vitals. The actual Core Web Vitals are Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS). FCP is a supplemental diagnostic metric that helps you understand perceived loading speed and identify render-blocking bottlenecks.

Fix first contentful paint

Fix First Contentful Paint

The First Contentful Paint (FCP) is the moment when a browser draws the first meaningful element on a page for the visitor to see. In other words, it is the moment a browser first renders something on the screen. As such, the FCP is a good way to measure perceived page load speed.

You can improve the FCP by making sure a browser can start rendering without any delay. Below you will learn what FCP is, how to measure it, and 15 proven techniques to make it faster.

What is the First Contentful Paint (FCP)?

The First Contentful Paint (FCP) is a way to measure loading page speed. You cannot summarize page speed as a point in time; there are actually several moments during the loading process where a visitor might experience the site as loading quickly or slowly. The FCP measures the time difference between requesting the page and when the first meaningful content is rendered on the screen for the first time.

What exactly does that tell you though? It tells you that the FCP is primarily a "user-centric metric" because it says something about the loading speed a visitor experiences. It says something about the user experience. At the FCP moment, you can be sure a visitor actually sees "something" on the screen.

Let's break down the words: 'First', 'Contentful' and 'Paint'.

  1. First: By First, of course, we mean the first exact moment something substantial appears on your browser.
  2. Contentful: With contentful we mean an HTML element with content. So not a layout element like a blank element or background color, but rather some text, an image (including background image), SVG or canvas.
  3. Paint: Paint means (more or less) that the browser is ready to put something on the screen. This seems simple but actually it is the browser's most complicated task. In order to put something on the screen, a browser must be ready to calculate all characteristics of an element. Below is an example of the rendering process that is required before anything can be added on the screen.

FCP vs LCP: What is the Difference?

FCP and LCP (Largest Contentful Paint) both measure loading performance, but they capture different moments in the page load timeline. Understanding the difference helps you prioritize your optimization work correctly.

First Contentful Paint (FCP) Largest Contentful Paint (LCP)
What it measures Time until the first piece of content renders Time until the largest content element renders
Good threshold < 1.8 seconds < 2.5 seconds
Poor threshold > 3.0 seconds > 4.0 seconds
Core Web Vital? No (diagnostic metric) Yes
Content type Any: text, image, SVG, canvas Largest: image, text block, video poster
User perception "Something is happening" "The page is almost ready"
Primary bottleneck TTFB + render-blocking resources TTFB + resource load + render delay

In practice, FCP often fires well before LCP. For example, a page may render a heading (FCP) within 400ms but wait another 2 seconds for the hero image to load (LCP). If your FCP is slow, your LCP will almost certainly be slow too, because FCP captures the very first bottleneck in the rendering pipeline. Read more in our complete LCP guide.

What is a good First Contentful Paint score?

A good FCP score is anything below 1.8 seconds. If your FCP score is between 1.8 and 3 seconds it needs improvement. Any FCP score above 3 seconds is considered poor. To meet the recommended threshold for the First Contentful Paint, at least 75% of your visitors need to have a "good" FCP score.


As always with performance metrics, a faster First Contentful Paint score is better than a slower one.

How do you measure your First Contentful Paint (FCP)?

The FCP is measured by Google by gathering data from real users. That data is stored in the CrUX dataset. That data is publicly available through the CrUX API or Google BigQuery. The FCP can also be measured through so-called lab tests. The most common lab test is called Lighthouse.

Getting the First Contentful Paint from the CrUX dataset

The First Contentful Paint can be read from the CrUX dataset through pagespeed.web.dev, the CrUX API, or through Google BigQuery.

Measuring the First Contentful Paint through Real User Monitoring (RUM)

RUM Tracking stands for Real User Monitoring. With Real User Monitoring you can track the First Contentful Paint through real user interactions. The advantage of RUM Tracking is that you do not have to wait 28 days for fresh data and the data can be queried and analyzed in far greater detail.

Measuring the FCP in Lighthouse

  1. Open the page (in Chrome) whose FCP you want to measure. Make sure you do this incognito so the plugins will not interfere and possibly slow down the FCP of your page.
  2. Right-click on the page and select Inspect Element. This way you open the Chrome developer console.
  3. At the top of the console, you will see the Lighthouse tab. Click on it. Then under Categories, choose Performance (leave others blank) and choose Mobile under Device.
  4. Now click on Generate Report. Lighthouse will create a speed report of your page. At the top left corner of the report, you will see what the FCP of your page is.

This is a screenshot of the Lighthouse report for this page. The FCP of this page on a mobile device is 0.8 seconds! Not bad right?

Measuring FCP with an online tool

You can also measure the FCP with a number of online tools. The best known are GTMetrix, pingdom and pagespeed.web.dev. These tools are easy to work with and will give some data about the FCP under specific lab circumstances.

What Real-World FCP Data Shows

CoreDash data shows FCP closely tracks TTFB: the p75 FCP is 392ms overall, with desktop at 372ms and mobile at 692ms (1.9x slower). The FCP to TTFB delta is just 248ms on desktop and 376ms on mobile, indicating that render-blocking time accounts for a relatively small portion of FCP on a well optimized site.

Globally, according to the 2025 Web Almanac, 70% of desktop pages achieve good FCP, while only 55% of mobile pages do. Both improved from 2024, with mobile gaining 4 percentage points, suggesting that web developers are increasingly addressing render-blocking resources.

The tight correlation between FCP and TTFB means that improving your Time to First Byte is often the single most effective way to improve your First Contentful Paint. On this site, the FCP is only about 250ms above the TTFB, which means most of the FCP time is spent waiting for the server to respond rather than on render-blocking work.

Improving the First Contentful Paint

Time to make the FCP faster. The idea behind a fast FCP is actually quite simple: making sure a browser can start rendering immediately. Anything that can cause rendering to be delayed will result in a poor FCP score.

Just like with the Largest Contentful Paint, the First Contentful Paint can be broken down into 2 or 4 categories:

  1. Time to First Byte (TTFB): The time from when the browser starts loading the page until when it receives the first byte of the HTML.
  2. Resource load delay: The time between TTFB and when the browser starts loading the FCP resource.
  3. Resource load time: The time it takes to load the FCP resource itself.
  4. Element render delay: The time between when the FCP resource finished loading until the FCP element is fully rendered.

Speed tip: You can easily eliminate steps 2 and 3 by making sure the FCP element does not require a network resource. In case of a text element, consider using font-display:swap. In case of a small image element, consider placing the image inline.

This just leaves us with the Time to First Byte and the Element Render delay to optimize.

Below are 14 solutions I often use to improve the FCP. But be careful, using a solution in the wrong place can actually create delays. That is why it is best to consult a pagespeed expert before you start yourself.

1. Fast server response (TTFB)

The TTFB (the time between the request and the first byte the server sends) is always the first step in the rendering process. From that point on, your browser starts multitasking, and the impact of further optimizations starts to decline. The HTML code is the only request that directly affects all speed metrics.

The speed at which the HTML code is sent from the server is often measured as the Time to First Byte (TTFB). It is important to make this as quick as possible. Often you do this by enabling server side caching.

When it comes to Time to First Byte, lower is always better.

You can easily measure the Time to First Byte yourself. It is done as follows:

  1. Use the shortcut Ctrl-Shift-I to open the developers console of Google Chrome.
  2. At the top of the console, you will see a Network tab. Click on it.
  3. Reload the page through Ctrl-R.
  4. You will now see all the network requests that Chrome has sent to your server.
  5. Click on the top network request, which is the request for your page itself.
  6. Now you will get more information about this network request. Click on the timing tab at the top of this information to see what the TTFB is for your page.

2. HTTP/3

HTTP/3 is the third version of the HTTP protocol. HTTP/3 solves many of the problems found in the older HTTP/1.1 and HTTP/2 protocols. For example, since HTTP/2, you can send multiple files at the same time through the same connection. HTTP/3 provides a faster initial connection and less trouble from minor network interruptions.

Without going into too much detail, HTTP/3 allows for a significant speed gain, especially on a slower network such as a mobile network. Your network administrator can tell you if your web server is already suited for the faster HTTP/3 protocol.

You can check for yourself whether your website is already using the faster HTTP/3 protocol. Use the shortcut Ctrl-Shift-I to open the network inspector of Google Chrome. Right-click on the table header and select Protocol. Now reload the page to see what protocol your site is using.

3. 103 Early Hints

103 Early Hints is a relatively new HTTP status code that allows a server to send preliminary response headers before the final response is ready. This is especially useful when your server needs time to generate the HTML (for example, querying a database or running server side logic). Instead of making the browser wait idle, the server sends a 103 response with preload and preconnect hints so the browser can start fetching critical resources immediately.

This directly improves FCP because the browser can begin downloading fonts, stylesheets, and other render-critical resources before the HTML even arrives. The impact is most significant on pages with a high TTFB.

HTTP/1.1 103 Early Hints
Link: </static/font/outfit.woff2>; rel=preload; as=font; type=font/woff2; crossorigin
Link: </static/css/critical.css>; rel=preload; as=style

HTTP/1.1 200 OK
Content-Type: text/html
...

Not all hosting providers support 103 Early Hints yet. Cloudflare has built-in support for Early Hints, and Apache and Nginx can be configured to send them. Read more in our complete 103 Early Hints guide.

4. Browser Caching

The network connection is often a weak link when it comes to page speed. Wouldn't it be so much easier to skip the network altogether?

When a visitor has been to your site before, you can indicate if and how long the network resources (for example a stylesheet) can be stored by the visitor's browser. Every time the visitor needs one of these files again, they pop up from the browser's cache in no time. As a result, the browser can start rendering much faster and speed up the FCP.

5. Compression

The network speed is in almost all cases a weak link. For a good First Contentful Paint, it is so important that the files are sent through the network as fast as possible. Compression reduces the number of bytes that must be sent from the server; fewer bytes means less time waiting on a network resource. Compression, in my opinion, is a technique that is not getting the attention it deserves. Unfortunately, too many webmasters "turn compression on" and then do not take another look at it anymore. And that is a shame because it is just an easy way to make things go just a little bit faster.

There are two popular compression techniques: Gzip and Brotli. Gzip is the most used compression technique but Brotli is quickly catching up. Brotli has been created by Google itself and has 15 to 20% better results when it comes to HTML, JavaScript or CSS files. Brotli is, therefore, ideal for the web.

There is also a difference between dynamic compression and static compression. With dynamic compression you compress the file just before you send it through your web server; with static compression, the compressed file is stored on the server. This is often a much smarter way to compress, but it is rarely used.

6. Early web-fonts with resource hints

Resource hints initiate a download or network connection before the browser would do so on its own. Some network resources, such as web fonts or images, are only downloaded after the browser is sure it needs to display them.

If you are sure you need a resource to render the visible part of the site, it is almost always a good idea to include a "resource hint". This will make sure the browser starts downloading or connecting to the resource immediately. As a result, the resource is available sooner and the browser can start rendering sooner.

But be careful with resource hints. If you use them incorrectly, they can actually slow down your page.

Early download with "preloading"

<link rel="preload" href="/static/font/opensans600.woff2" as="font" type="font/woff2" crossorigin>

The preload link is one of the most powerful tools in the page speed arsenal. Through the preload link, you download a network resource you will need later. This is often a very good idea with fonts, critical scripts and images on the visible part of the site.

Connecting in advance with preconnect

The preconnect link already connects to a server. This is useful when you host files on a third-party server such as a CDN or Google Analytics.

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

Even better than preconnecting to Google Fonts is self-hosting your Google Fonts. This eliminates the third-party connection entirely and gives you full control over caching and delivery.

7. Prefetch the next page with prefetch

<link rel="prefetch" href="/page2.html">

With prefetch, you can fetch low priority resources. This is a useful way to fetch resources that you think you will need later, for example when you expect someone to click on the next page link.

8. Avoid redirects

A common mistake is having a redirect chain that is too long. Let me explain: Your site probably runs through a secure connection. When a visitor types in your site without adding https, the visitor will be redirected to the non-secured version of your website. However, if everything is set up right, the visitor will be redirected to the secure website. You can see this in the green example below.

But sometimes the redirection takes place via one or more intermediate steps, as shown in the red example. It is these intermediate steps that cause the website to run slow, resulting in a poor First Contentful Paint score. Each intermediate step costs extra time, which can quickly add up. So, always make sure you get to the right page within one redirect.

9. Minimize CSS

An external CSS file is always render-blocking. What that means is that a browser normally cannot start displaying content until all stylesheets have been downloaded and analyzed. Therefore, it is best to keep stylesheets as small as possible. This way you do not have to wait as long for the stylesheet to be downloaded. For a more complete guide, read our article on how to fix and remove unused CSS.

Reducing the CSS size with shortcode

One of the ways to reduce the CSS size is by using shortcodes. These are one-liners that allow you to write down the most important properties of a CSS selector in one line.

body{
    font-style: normal;
    font-weight: 400;
    font-stretch: normal;
    font-size: 0.94rem;
    line-height: 1.6;
    font-family: "Segoe UI", "Segoe UI", system-ui, -apple-system, sans-serif;
}

You can also write it as:

body{font: 400 .94rem/1.6 Segoe UI,Segoe UI,system-ui,-apple-system, sans-serif;}

Reducing the size of CSS further

It is possible to reduce the CSS size even more by merging selectors with a comma, removing enters and spaces and writing shorter color codes.

h1{
  color : #000000;
}
h2{
  color : #000000;
}
h3{
  color : #000000;
}
h4{
  color : #000000;
}
h5{
  color : #000000;
}

Could be shortened like

h1,h2,h3,h4,h5{color:#000}

10. Critical CSS

We can take CSS one step further by using critical CSS. Critical CSS is a must-have for a fast website and a fast First Contentful Paint.

Critical CSS is a collection of all the selectors (like body, p, h1 etc.) you need to show the visible part of the page. Do not put this critical CSS in a separate stylesheet; instead, add it directly in the <head> of the page. This way you do not have to download a new file and the browser can start rendering at lightning speed. This makes for a faster FCP. The CSS you do not directly need for the visible part of the page is loaded after the first rendering cycle is completed. To your visitor, the page is already done; no one will notice the new styles still being added in the background.

Critical CSS can be easily generated with our own critical CSS tool. Just paste the URL of your webpage in the tool and we will do the rest for you!

Inline Critical CSS Example

<head>
  <style>
    /* Critical CSS: only what is needed for above-the-fold content */
    body{font:400 1rem/1.6 system-ui,sans-serif;margin:0}
    h1{font-size:2rem;margin:.5em 0}
    .hero{padding:2rem;background:#f5f5f5}
  </style>
  <!-- Non-critical CSS loaded asynchronously -->
  <link rel="preload" href="/css/full.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="/css/full.css"></noscript>
</head>

11. Defer loading JavaScript

One of the most common reasons for a slow First Contentful Paint is JavaScript. Depending on how you use JavaScript, it can block the rendering of the page. Normally JavaScript is downloaded and executed before the render tree is built. Without the render tree, a browser cannot put anything on the screen, and that includes the FCP. For a full overview of deferral techniques, read 14 methods to defer JavaScript.

Critical rendering path sequence showing how JavaScript blocks rendering

We can work around this by postponing JavaScript. You can do this in three ways.

Async JavaScript

<script async src="async.js"></script>

By adding the async attribute to a script tag, the buildup of the page is no longer blocked while the JavaScript is being downloaded. The async attribute indicates that the download and the buildup of the render tree can happen at the same time.

Once the script is executed, the page is blocked. In most cases, thanks to the async attribute, the browser has had enough time to build an important part of the page, with the First Contentful Paint already on the page.

Defer JavaScript

<script defer src="deferred.js"></script>

The defer attribute works more or less the same as the async attribute. By adding the defer attribute to a script tag, the script may also be downloaded simultaneously to building the page. After all scripts are downloaded, they are executed in the order they were found in the HTML code. This can also block the display of the page but in many cases the First Contentful Paint is already on the screen.

12. Do not rely on external resources

External resources, such as external fonts, external images, external stylesheets or external scripts, are a potential bottleneck when it comes to the First Contentful Paint. Since you have no control of the server where the files are hosted, you do not know how fast they will be sent. In addition, you cannot use the existing connection to the web server. A new connection to a new server must be set up, and that takes time.

One of the most common external resources on the web is Google Fonts. Self-hosting your Google Fonts eliminates an entire third-party connection and gives you full control over caching, compression, and font-display behavior.

Blocking external resources

No external resources

13. Use the right font format

Fonts deserve extra attention when it comes to the First Contentful Paint. On about 99% of the pages we look at, the FCP element is a text line. When you use external web fonts, you should download these fonts from a server first, which of course takes time.

Recently, web fonts have been getting more attention, and there are more new, faster font formats. The fastest font format at the moment is woff2, followed by woff. Woff2 is supported by every modern browser.

You can specify the preferred order of your web font in the CSS font-face declaration. You do that as follows:

 @font-face {
   font-family: 'myFont';
   font-weight: 400;
   font-style: normal;
   font-display: swap;
   unicode-range: U+000-5FF
   src: local('myFont'),
        url('/fonts/myFont.woff2') format('woff2'),
        url('/fonts/myFont.woff') format('woff');
}

14. Font-display: swap

When using web fonts, the default behavior of these fonts is to not show the text on the page until the font is loaded. This is usually directly at the expense of the First Contentful Paint. Read our complete guide on how to ensure text remains visible during webfont load.

You can solve this by using the font-display:swap declaration. With this you can choose to show the text on the page anyway, in a font the browser knows, while the webfont is loaded in the background.

Without font-display:swapFOIT with a webfont

With font-display:swapNo FOIT with font-display swap

font-display: swap vs optional

There are two common font-display strategies for FCP optimization:

/* swap: Shows fallback font immediately, swaps when webfont loads */
@font-face {
  font-family: 'MyFont';
  font-display: swap;
  src: url('/fonts/myfont.woff2') format('woff2');
}

/* optional: Shows fallback font, only uses webfont if already cached */
@font-face {
  font-family: 'MyFont';
  font-display: optional;
  src: url('/fonts/myfont.woff2') format('woff2');
}

Using font-display: swap guarantees the fastest possible FCP because text renders immediately in the fallback font. Using font-display: optional avoids the flash of unstyled text (FOUT) entirely on first visit, but the webfont will only display if it is already in the browser cache. For most sites, swap is the better choice for FCP.

15. Minimize the DOM size

A web page consists of HTML. The first thing a browser does is convert the HTML to DOM nodes. That is a tree structure of HTML elements that is later used to build the render tree. From the render tree a browser starts rendering; eventually the web page appears on the screen.

How many DOM nodes (HTML elements) you have and how deep these DOM nodes are in the tree structure determines how complicated it is for a browser to build your page. CSS and JavaScript also take more time to analyze when you have too many DOM nodes. This, again, is all directly at the expense of the FCP.

Solve this by:

  • Lazy load parts of your web page
    To speed up the initial display, consider loading parts of your website, like the footer, via AJAX at a later time.
  • Make use of content-visibility
    The CSS property content-visibility tells a browser to skip style, layout and paint during rendering. It does so just before the element becomes visible.
  • Split large pages into multiple pages
    The number of DOM nodes can be reduced by splitting large pages into multiple pages.
  • Implement infinite scroll
    Infinite scrolling is basically lazy loading: when scrolling through repeated elements such as images (Pinterest) or large tables of data, infinite scroll can significantly speed up your page.
  • Avoid JavaScript DOM interaction
    Be extra careful with JavaScript when you have a large number of DOM nodes on your page. A command like querySelectorAll can then load a large number of DOM nodes, increasing memory usage.
  • Avoid complicated CSS declarations
    Be extra careful with complicated CSS commands with a large number of DOM Nodes. For example, checking the last-child status for every div element on your page can be expensive.
  • Use web workers to spare your browser's main thread
    Web workers are JavaScript that can run in parallel with your web page. You can give these web workers commands that are executed in the background. When the web worker has executed the command, it passes it on to the original page. The advantage of this is that you can still execute complex JavaScript without the page freezing up.

Related Optimization Guides

Improving FCP requires work across multiple areas. Here are our most relevant guides:

Frequently Asked Questions about First Contentful Paint

What is a good FCP score?

A good First Contentful Paint score is below 1.8 seconds at the 75th percentile. Scores between 1.8 and 3.0 seconds need improvement, and scores above 3.0 seconds are considered poor. Google uses the 75th percentile of real user data (from the Chrome User Experience Report) to evaluate your FCP. This means at least 75% of your page visits must have an FCP under 1.8 seconds to be rated "good."

Is FCP a Core Web Vital?

No, First Contentful Paint (FCP) is not a Core Web Vital. The three Core Web Vitals are Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS). FCP is classified as a supplemental diagnostic metric. It does not directly factor into Google's Core Web Vitals assessment, but a slow FCP almost always indicates problems that will also affect LCP.

What is the difference between FCP and LCP?

FCP measures the time until the browser renders the first piece of DOM content (any text, image, SVG, or canvas element). LCP measures the time until the largest content element in the viewport finishes rendering (typically a hero image or main heading). FCP tells you "something is happening," while LCP tells you "the main content is ready." FCP is a diagnostic metric; LCP is a Core Web Vital. On most pages, FCP fires well before LCP.

How does TTFB affect FCP?

Time to First Byte (TTFB) is the largest contributor to FCP on most pages. FCP cannot begin until the browser receives the first byte of HTML from the server, so a slow TTFB directly delays FCP by the same amount. CoreDash data shows the FCP to TTFB delta is only about 248ms on desktop and 376ms on mobile for a well optimized site. This means that on many pages, reducing TTFB is the most effective way to improve FCP.

What counts as "content" for FCP?

For First Contentful Paint, "content" includes text nodes, images (including CSS background images with a URL), SVG elements, and non-white canvas elements. It does not include blank elements, elements with only a background color, or invisible elements. The most common FCP element on the web is a text node, such as a heading or paragraph, because text typically renders before images. Using font-display: swap ensures text renders immediately even while web fonts are still loading.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

The RUM tool I built for my own clients.

CoreDash is what I use to audit enterprise platforms. Under 1KB tracking script, EU hosted, no consent banner. AI with MCP support built in. The same tool, available to everyone.

Create Free Account
First Contentful Paint (FCP): What It Is, How to Measure and Fix ItCore Web Vitals First Contentful Paint (FCP): What It Is, How to Measure and Fix It