SEO check

First Contentful Paint (FCP): What It Is and How to Improve It

Learn what first contentful paint measures, what a good FCP is, and how to shorten the blank wait before your page shows its first content.

Free to use 17 min read Updated Oct 2026

First contentful paint in one minute

Quick answer: First contentful paint (FCP) is the time from the start of navigation until the browser paints the first real content, meaning text, an image, an SVG or a canvas that is no longer blank. Our report passes a page at 1.5 seconds or less. Google rates 1.8 seconds or less as good in field data, so keep the two numbers apart. The score section below lays them side by side.

  • Pass: FCP arrives in 1.5 s or less in our report.
  • Warning: Above 1.5 s up to 3.0 s earns a warning and no score points.
  • Fail: Above 3.0 s, or no paint found at all, fails.
  • Fix: Answer the request faster, remove the CSS and JavaScript that block the first paint, and keep text visible while fonts load.

Check my site free

What is first contentful paint (FCP)?

The FCP time is a timestamp, in milliseconds, measured from the start of navigation to the first frame that shows any page content. It is the visitor's first proof that the page is working. Before that moment they face a blank screen and cannot tell whether your site is loading or broken.

Browsers expose the value through the Paint Timing API as an entry named first-contentful-paint. You can read it yourself with performance.getEntriesByType("paint"), and our report reads the very same entry. The PerformancePaintTiming on MDN reference documents the entry and its startTime value in detail.

FCP is a diagnostic metric, not one of the three Core Web Vitals, which are LCP, INP and CLS. It normally arrives at or before LCP, because the largest element on the screen is itself a contentful paint.

Developers should know that the raw paint entry is not identical to the official metric. A page loaded in a background tab can report a very late FCP, so real user monitoring should discard those loads. Prerendered pages are measured from activation, and back and forward cache restores are not reported by the raw entry at all. The web-vitals library handles these cases for you.

What counts as content

The browser counts text nodes, images (including CSS background images), inline SVG and a canvas that has drawn something other than plain white. Any one of those appearing is enough. Paint inside a cross-origin iframe, such as an embedded video or chat widget, may not move the number our report reads.

What does not count

A plain background colour, an empty white page or a box with no text or image inside does not count. That is why a page can show a first paint, perhaps a dark header band, while the metric is still a second away. The browser has changed some pixels, but there is nothing for a visitor to read yet.

What is a good first contentful paint score?

Who is measuring decides what counts as a good score. Google publishes field thresholds based on real visits, and Lighthouse uses lab control points that differ between mobile and desktop. Our report applies one desktop rule to every page. Our pass line of 1.5 s is stricter than Google's field limit but looser than the 0.9 s desktop green in Lighthouse. Our fail line of 3.0 s matches Google's poor threshold and is more forgiving than the 1.6 s desktop red in Lighthouse. The Google FCP guide on web.dev is the official source for the field limits, judged at the 75th percentile of page loads.

SourceGood or passNeeds improvement or warningPoor or fail
Google field data1.8 s or lessAbove 1.8 s up to 3.0 sAbove 3.0 s
Lighthouse lab, mobileUp to 1.8 sAbove 1.8 s up to 3.0 sAbove 3.0 s
Lighthouse lab, desktopUp to 0.9 sAbove 0.9 s up to 1.6 sAbove 1.6 s
SEO Site Checker report1.5 s or lessAbove 1.5 s up to 3.0 sAbove 3.0 s

We'd rather say openly that our pass limit is stricter than Google's. A page whose first content appears at 1.7 seconds in our lab run earns a warning here, while the same figure in field data counts as good in Google's terms, and nobody is wrong. Judge real visitors by field data, and treat any lab number, ours included, as a quick signal for before and after testing.

How SEO Site Checker tests first contentful paint

This is what happens when the free report measures FCP for your URL, including the limits on what the number can tell you.

The rule: The report records the browser's FCP in seconds, rounded to two decimals. 1.5 s or less passes, above 1.5 s up to 3.0 s is a warning, above 3.0 s fails, and a missing or zero value also fails.

What the checker measures

The report opens your URL in headless Chromium, a real browser engine driven by Playwright on our server. It uses the default 1280 by 720 desktop viewport, with no network throttling, no CPU throttling and no mobile emulation. Each audit is a single lab run, and the browser waits for the load event, the same moment our page load time check is about, with a limit of 20 seconds.

Once the page has loaded, the report reads performance.getEntriesByType("paint") and takes the entry named first-contentful-paint, the same entry real browsers expose to your own scripts. Its start time in milliseconds is divided by 1000 and rounded to two decimals.

A page that never reaches the load event within 20 seconds cannot be graded, because the audit stops and the report fails to run instead of showing a slow FCP. The check also ignores real visitors, mobile conditions and repeat visits with a warm cache, so a pass here does not prove your field FCP is good.

Pass, warning and fail rules

ResultRuleEdge case
Pass1.5 s or lessExactly 1.5 s passes
WarningAbove 1.5 s up to 3.0 sExactly 3.0 s is still a warning
FailAbove 3.0 sNo paint entry, or a time of 0, fails with a blank value

The score works on passed checks divided by all checks, so a warning earns no points, even though its icon uses a softer colour than a fail.

What you see in the report

A pass shows a green tick, the word Congratulations and the time in seconds. A warning or a fail shows an alert box with the seconds and a red How to Fix button, which opens a short fix plan, plus a link to read this guide.

Why your number may differ from other tools

Mobile lab tools slow the CPU and the network on purpose to imitate a mid-range phone, and field data covers many different real devices and connections. Our run is a fast desktop pass from a server, so it can differ from PageSpeed Insights and from your actual visitors.

Bot protection is the other caveat. If the report shows a bot protection banner, the FCP describes the challenge page in front of your site, not your real content.

Run the full SEO report

First contentful paint vs first paint, LCP, TTFB and page load time

Several timing metrics sit close together on the load timeline and get mixed up constantly. This table shows what each one marks and which limit Google considers good.

MetricWhat it marksGood limitCore Web Vital
Time to first byte (TTFB)First byte of the HTML arrives0.8 s or lessNo
First paintAny pixel change, even a background colourNo set limitNo
First contentful paintFirst text, image, SVG or drawn canvas1.8 s or lessNo
Largest contentful paintThe biggest element in view is painted2.5 s or lessYes
Page load timeThe load event firesNo official limitNo

In most page loads the order runs like this: navigation start, then TTFB, then first paint, then FCP, then LCP. The load event lands before or after LCP depending on the page. A slow FCP with a fast TTFB points to blocking resources or fonts, while a healthy FCP with a slow LCP points to the hero image or content that arrives late.

Old guides still mention two retired metrics. Time to Interactive stopped counting toward the Lighthouse performance score in version 10, and the First Meaningful Paint metric was removed in Lighthouse 12.1. FCP and LCP are the paint metrics to use now.

For the biggest element, read our largest contentful paint test guide, and see the page load time page for the load event.

Why first contentful paint matters for users and SEO

Until the first paint, a visitor on a slow mobile connection sees a white screen and has no reason to believe the page will ever load. Some will go back to the results page, so a late first paint hurts before anything else has a chance to.

On the SEO side, be careful not to oversell it. FCP is not a Core Web Vital, and Google's page experience documentation points to the Core Web Vitals, not FCP, as what its ranking systems use. The same documentation says there is no single page experience signal, and that good scores do not guarantee a top ranking. Our Core Web Vitals guide covers the three that do count.

It is still worth fixing, for two reasons. FCP sits at the start of the load chain, so a slow server or blocking CSS drags LCP and the whole Lighthouse score down with it. FCP carries a weight of 10 percent in the Lighthouse performance score, next to Speed Index at 10, LCP at 25, Total Blocking Time at 30 and CLS at 25. And the fixes aimed at FCP (a faster server, less blocking code, visible text) are the same fixes that help the Core Web Vitals, so the effort pays twice.

What makes first contentful paint slow?

Causes are easiest to sort by where they hit on the timeline. Something happens before the HTML arrives, something else happens while the browser parses it, and a third group only shows up once scripts run.

Slow server response and redirects. Nothing can paint until the HTML arrives. Uncached dynamic pages, distant or overloaded hosting, no CDN and chains of redirects (http to https to www, for example) all add to TTFB. Our hosting speed article explains why a weak server delays everything after it.

Render-blocking CSS. The browser will not paint until the stylesheets in the head are downloaded and parsed. Large theme files and @import chains make the wait longer, because each import is discovered only after the previous file arrives.

Render-blocking JavaScript. Synchronous scripts in the head stop the parser, and so do tag managers or chat widgets loaded ahead of the content. Our render blocking resources guide audits this cause in depth.

Web fonts that hide text. With default settings, a browser can keep text invisible while a font downloads, a behaviour often called a flash of invisible text, so FCP waits for the font file.

Content that only exists after JavaScript runs. Client side rendering ships an empty root element, so FCP has to wait for the entire bundle to download and execute.

Heavy or uncompressed HTML and a very large DOM delay the first paint too, because the browser has more bytes to download and more nodes to parse and style before it can draw a frame. An anti-flicker snippet or a hide-until-loaded rule can also keep finished content invisible until a third-party script answers.

The network waterfall in DevTools tells these causes apart quickly. If the HTML finishes at 1.9 s and the first paint lands at 2.1 s, the server reply is the problem and font tuning will not help. If the HTML is done at 0.3 s but a large stylesheet finishes at 1.9 s, with the paint at 2.0 s, a blocking CSS file is the culprit.

How to check first contentful paint

Use lab data for quick before and after tests, and field data for what real visitors experience.

Lab tools

  1. Run our report. Start with the free SEO report and read the FCP line in the speed section.
  2. Open PageSpeed Insights. Compare the lab FCP from Lighthouse with the field FCP from the Chrome User Experience Report (CrUX), which appears only when the page has enough traffic. Flip between the mobile and desktop tabs to see how far apart they sit.
  3. Use Chrome DevTools. Open the Lighthouse panel for a full audit, or the Performance panel, where the Timings track marks FCP and LCP. Turn throttling on to see a slow phone. The Lighthouse FCP audit page shows how Lighthouse scores the metric.

WebPageTest adds a filmstrip of the load. Whatever you pick, keep the page and device settings the same and take the middle value of three runs, because a single lab run can swing.

Field data and code

Read it in the browser. Load the page, open the DevTools console and paste the snippet below. It prints the paint entries your browser exposes, so in Chrome you can see the gap between the first paint and FCP for that one visit.

JavaScript
performance.getEntriesByType("paint").forEach((entry) => {
  console.log(entry.name, Math.round(entry.startTime) + " ms");
});

The output lists first-paint and first-contentful-paint with their times. To catch the entry as it happens, use a PerformanceObserver on the paint type with buffered: true, so earlier entries are included.

JavaScript
new PerformanceObserver((list) => {
  list.getEntriesByName("first-contentful-paint").forEach((e) => console.log(e.startTime));
}).observe({ type: "paint", buffered: true });

Real user data. Add the web-vitals library, call onFCP(console.log) while testing, then send the value to your analytics once you trust it. PageSpeed Insights shows the same field FCP from the Chrome User Experience Report, which covers a rolling 28 day window of real visits, so field data lags behind a fix.

How to improve first contentful paint, step by step

The nine fixes below are numbered in the order they usually pay off, and each group matches a stage of the load. Re-test after every change.

Speed up the server reply

  • Fix 1. Server first. Turn on full page caching, serve through a CDN, move to faster hosting if the host is the bottleneck and trim slow database work. Aim for a TTFB of 0.8 s or less, which is the web.dev good limit. Our CDN usage check shows whether a CDN is already in front of your site.
  • Fix 2. Cut the redirects. Link straight to the final https URL on one canonical host, so a visitor takes at most one hop before the HTML starts to arrive.

Unblock the first paint

  • Fix 3. Inline critical CSS. Put the small amount of CSS that the first screen needs inside the page, and load the rest without blocking, using the preload and onload pattern with a noscript fallback. To find it, open the DevTools Coverage tab and see which rules the first screen uses, or let a critical CSS generator or your caching plugin extract it. Keep the inlined block small, then check several screen widths so nothing flashes unstyled.
  • Fix 4. Trim the CSS. Minify it, remove unused rules and avoid @import. Our free CSS Minifier handles the minify part in a few seconds.
  • Fix 5. Defer scripts. Add defer to every script the first screen does not need, and load analytics and tag manager scripts with async or defer so they cannot stop the parser before the first paint.
  • Fix 6. Handle fonts. Set font-display: swap so text shows in a fallback font while the real one downloads. Preload only the one font used above the fold, add the crossorigin attribute, and self-host and subset the files.
HTML
<style>/* critical CSS for the first screen goes here */</style>
<link rel="preload" href="/css/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/main.css"></noscript>
<script src="/js/app.js" defer></script>
<script src="https://example.com/analytics.js" async></script>
<link rel="preload" href="/fonts/body.woff2" as="font" type="font/woff2" crossorigin>
CSS
@font-face {
  font-family: "BodyFont";
  src: url("/fonts/body.woff2") format("woff2");
  font-display: swap;
}

The stylesheet link starts as rel="preload" and flips to rel="stylesheet" once it arrives, so the browser fetches it early without stopping the paint. That only works when the critical CSS is already in the page, otherwise visitors see unstyled content for a moment. A strict Content Security Policy blocks inline onload handlers, so use your caching plugin's critical CSS feature there. Read the render blocking resources guide for more on spotting the files involved, and try the JavaScript Minifier on any script you keep.

Make sure content is in the HTML

  • Fix 7. Compress text files. Serve HTML, CSS and JavaScript with Brotli or gzip. Our text compression check tells you whether your server already does it.
  • Fix 8. Render on the server. Use server-side rendering or static generation so the text is present in the first response instead of an empty root element that waits for a bundle.
  • Fix 9. Keep the page small. Trim the HTML and the DOM size. Add preconnect for one or two key third-party origins, such as your font host. If your server or CDN supports 103 Early Hints, it can also send those hints while the full response is still being built. Then test again.

How to improve first contentful paint in WordPress, Shopify and other platforms

Each platform gives you different levers, so the table maps the general fixes to settings you can actually find and change.

PlatformBiggest leverQuick win
WordPress and WooCommerceOne page cache layer and a lean themeSwitch on your caching plugin's critical CSS and delay or defer JavaScript options, host fonts locally instead of using Google-hosted ones, and remove builder widgets that load site-wide
ShopifyLeftover app code, theme scripts and fontsTurn off unused App embeds in the theme editor, search the theme.liquid file for script tags that removed apps left behind, and cut fonts to one or two families
Wix and SquarespaceFewer apps, embeds and font familiesRemove the animated or embedded block from the first screen and drop the extra font families
Next.js, Nuxt and AstroContent rendered on the server or at build timeSplit large bundles and keep hydration code from blocking the first paint
Plain HTML or custom stacksThe fix steps aboveFollow them in order and re-test after each one

On WordPress, check the host first, because no plugin can paint a page faster than the server answers. If the first document takes more than 0.8 s to arrive, fix hosting and caching before you touch CSS or fonts. Use one cache layer only, either the host's or a plugin's, since stacking two adds conflicts without adding speed.

Shopify already supplies the CDN and compression. Removing an app does not always remove its code, which is why the theme file search matters.

Common first contentful paint mistakes

Warning: A better FCP number that does not help visitors is not an improvement. Always judge a change with LCP as well as FCP.

  • Gaming the metric. An instant logo or spinner makes FCP look great while the real content still arrives late. The tell is a good FCP next to an LCP that is seconds later.
  • Deferring all CSS. Without inlined critical CSS you get a flash of unstyled content and layout shift.
  • Inlining too much. Huge CSS blocks in every page bloat the HTML and cannot be cached.
  • Hiding the page. A cookie banner or anti-flicker snippet that waits for a third-party script can hold back everything. The text is in the HTML but sits behind an opacity: 0 rule until the consent script answers.
  • Comparing across setups. One warm cache test on fast Wi-Fi, or our desktop figure set against a mobile lab figure, proves nothing.

First contentful paint checklist

  • Server reply. TTFB sits at 0.8 s or less on your key pages. Check the Waiting for server response time of the first document in the DevTools Network panel.
  • Redirects. No redirect chain stands in front of the final URL.
  • Critical CSS. It is inline, and the rest loads without blocking.
  • Scripts. They are deferred, and third-party tags come after the content.
  • Fonts. The font-display rule is set and only one font is preloaded.
  • Compression. HTML, CSS and JavaScript go out with Brotli or gzip.
  • Content. It is present in the first HTML response. Open view-source and confirm the main headline text is there.
  • Re-test. Mobile and desktop are both checked, and FCP is at 1.5 s or less in our report.

How to Fix

The short version, the same steps you see when you click How to Fix in your report.

Why this fails: The first text or image appeared later than 1.5 s, so visitors stared at a blank screen for too long. Above 1.5 s and up to 3.0 s is a warning, and above 3.0 s is a fail.

How to fix it:

  1. Find the cause. Open the page in Chrome DevTools, select the first document in the Network panel and read Waiting for server response on the Timing tab, or check the server response time audit in PageSpeed Insights. Compare it with your FCP. A slow reply means a server problem, while a fast reply with a slow FCP means blocking CSS, scripts or fonts.
  2. Speed up the server reply. Turn on page caching, serve through a CDN and remove redirect chains, so the HTML starts arriving sooner.
  3. Inline critical CSS. Put the styles for the first screen in the page and load the rest without blocking. A caching plugin or a critical CSS generator will extract them for you.
  4. Defer scripts. Add defer to any script that the first screen does not need.
  5. Keep text visible. Set font-display: swap so text shows while the font downloads.
  6. Compress and render on the server. Turn on Brotli or gzip, and make sure the real content is in the HTML itself instead of waiting for a script.
HTML
<!-- critical CSS goes inline in a style tag above these lines -->
<link rel="preload" href="/css/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/main.css"></noscript>
<script src="/js/app.js" defer></script>
<style>@font-face{font-family:"BodyFont";src:url("/fonts/body.woff2");font-display:swap}</style>
  • WordPress: use page caching and generate critical CSS.
  • Shopify: remove unused apps and theme scripts.
  • Custom or static HTML: follow the steps and the markup above.

Re-test: Run our free report again and check that the first contentful paint reads 1.5 seconds or lower. Real user data in PageSpeed Insights lags a few weeks behind a fix. The Google FCP guide on web.dev explains the field limits.

Re-test my website

Frequently Asked Questions

What is a good first contentful paint score?
Google rates 1.8 seconds or less as good, above 1.8 and up to 3.0 seconds as needing improvement, and above 3.0 seconds as poor, judged at the 75th percentile of page loads. Our free report passes a page only at 1.5 seconds or less, so a result between 1.5 and 1.8 seconds shows as a warning.
Is first contentful paint a Core Web Vital?
No. The three Core Web Vitals are largest contentful paint, interaction to next paint and cumulative layout shift. FCP is a diagnostic metric that helps explain a slow LCP, and it carries a weight of 10 percent in the Lighthouse performance score.
What is the difference between first contentful paint and largest contentful paint?
FCP marks the moment the first text or image appears, while largest contentful paint marks when the biggest visible element has painted, and only LCP is a Core Web Vital. FCP normally arrives at or before LCP. Our largest contentful paint test page covers the second metric.
What is the difference between first paint and first contentful paint?
A first paint is triggered by any pixel change at all, even a plain background colour, while first contentful paint waits for real content, such as text, an image, an SVG or a canvas that has drawn something other than white. A page can therefore have a first paint well before its FCP.
Does first contentful paint affect SEO?
Not as a named signal, because Google's page experience guidance points to the Core Web Vitals and not to FCP. The fixes for a slow FCP also help LCP, though, and a faster page keeps visitors from leaving before they see anything. Treat it as a useful diagnostic rather than a ranking lever.
How do you measure first contentful paint?
Run our free report, PageSpeed Insights or Lighthouse for lab numbers, and use the Chrome User Experience Report or the web-vitals library for real users. A short console snippet can also read the paint entries, which is the same entry our report reads.
How can I improve first contentful paint in WordPress?
Start with page caching and faster hosting, since a slow server delays everything. Then generate critical CSS, remove unused plugins and builder widgets, host fonts locally and defer scripts that the first screen does not need. Re-test after each change so you know which one actually helped.
Why is my first contentful paint slow on mobile?
Mobile tests slow the CPU and the network on purpose, so server delay, blocking CSS, large scripts and web fonts hurt more than on desktop. Work through the fix steps on this page, and compare mobile with mobile, because the two lab numbers are not meant to match.

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.