Skip to content
Back to Resources
Guide

Core Web Vitals Monitoring: Lab vs Real-User Data

Skopx Team
August 21, 2026
15 min read

Core Web Vitals monitoring needs two data sources at once: lab data from Lighthouse, which runs a synthetic page load on a simulated device, and field data from the Chrome User Experience Report (CrUX), which aggregates what real Chrome users actually experienced. Only the field number counts for Google's page experience assessment, and it is reported at the 75th percentile over a rolling 28 day window, so a perfect Lighthouse score can sit next to a failing CrUX grade without either being wrong.

That gap is the single most common source of confusion in performance work. A developer runs PageSpeed Insights, sees a green 98, ships, and then Search Console keeps flagging the same URL group as "Needs improvement" for another month. Nothing is broken. The two numbers are answering different questions. This guide explains what each source measures, how the 75th percentile changes what you should optimize, which API to pull from for which job, and how to build a monitoring loop that catches regressions before they age into your field data.

What Core Web Vitals actually measure

Core Web Vitals is a fixed, small set of metrics that Google treats as user-facing quality signals. There are three, and each one stands in for a different moment in the page experience.

Largest Contentful Paint (LCP) measures loading. It marks the render time of the largest text block or image in the viewport, relative to when the navigation started. In practice it is usually a hero image, a video poster, or a headline. LCP is dominated by three things: server response time, render-blocking resources in the head, and how late the LCP resource is discovered by the browser's preload scanner.

Interaction to Next Paint (INP) measures responsiveness. It replaced First Input Delay in March 2024. Where FID only measured the delay before an event handler started, INP measures the full latency of an interaction, from user input through event processing to the next frame the browser actually paints. It reports a high percentile of all interactions on the page, not just the first one, which makes it far harder to game and far more representative of how a page feels after it has loaded. Long tasks on the main thread, oversized event handlers, and heavy re-renders are the usual causes.

Cumulative Layout Shift (CLS) measures visual stability. It sums the largest burst of unexpected layout shifts across the page lifetime. Images without dimensions, injected banners, late-loading fonts that change metrics, and ad slots that resize are the classic offenders.

Two more metrics show up constantly in tooling but are not Core Web Vitals: Time to First Byte (TTFB) and First Contentful Paint (FCP). Treat them as diagnostics. A bad TTFB explains a bad LCP; it is not separately graded.

What are the current thresholds and how is the grade calculated?

Each metric has a "good" ceiling and a "poor" floor. Anything between the two is "needs improvement." The assessment is applied to the 75th percentile of the metric's distribution, evaluated separately for phone and desktop.

MetricGoodNeeds improvementPoorMeasurable in lab?
Largest Contentful Paint2.5s or less2.5s to 4.0sOver 4.0sYes
Interaction to Next Paint200ms or less200ms to 500msOver 500msNo, needs real interaction
Cumulative Layout Shift0.1 or less0.1 to 0.25Over 0.25Partially, load-time shifts only
Time to First Byte (diagnostic)800ms or less800ms to 1800msOver 1800msYes
First Contentful Paint (diagnostic)1.8s or less1.8s to 3.0sOver 3.0sYes

To pass the overall Core Web Vitals assessment, a URL or origin needs all three metrics in the good bucket at p75. One failing metric fails the whole assessment. This is why chasing an LCP from 2.4s to 1.9s while INP sits at 340ms is wasted effort: you are improving a metric that already passes and ignoring the one that does not.

Note the third column of the table carefully. INP cannot be measured by a synthetic page load, because nobody clicked anything. Lighthouse reports Total Blocking Time instead, which correlates with INP but is not the same number and has no threshold in the Core Web Vitals assessment. Any tool that claims to give you a "lab INP" is giving you a proxy, and you should know which proxy it chose.

Why is p75 the number that decides your grade?

The 75th percentile means three out of four page views were at or better than the reported value. It is a deliberate choice by Google: an average would be dragged down by a long tail of slow devices and hide real problems, while a median would let a quarter of your users have a bad time invisibly. p75 forces you to care about the slower part of your audience without being held hostage by the absolute worst outlier.

This has three practical consequences that change how you work.

First, your fastest users are irrelevant to the score. Optimizing the experience on a fast laptop with fiber moves the p25, not the p75. The visits that determine your grade are the mid-range Android phone on a congested mobile network, the office desktop with a heavy extension load, the returning user on a throttled connection. If you only test on your own machine, you are measuring a percentile that does not count.

Second, traffic mix moves your score without any code change. If a campaign sends a wave of mobile traffic from a region with slower networks, your p75 can degrade while every line of your code stays identical. The reverse is also true, and it is a trap: a seasonal shift toward desktop traffic can make a page look like it improved when nothing was fixed. Always read the form factor breakdown before celebrating.

Third, the 28 day rolling window makes field data lag. CrUX aggregates the trailing 28 days, so a fix deployed today will not fully appear in the field number for four weeks. Partial improvement shows up gradually as good days replace bad days in the window. This lag is the entire reason lab monitoring still matters: it is your only same-day signal.

How do PageSpeed Insights, the CrUX API, and BigQuery differ?

All three surface CrUX data, but they answer different questions and have different limits. Picking the wrong one is how teams end up with monitoring that quietly stops working.

PageSpeed Insights runs a fresh Lighthouse audit on demand and, in the same response, returns whatever CrUX field data exists for that URL. It is the only one of the three that gives you lab and field in a single call, which makes it the natural backbone for a monitoring job. The response includes loadingExperience (URL level field data, when available) and originLoadingExperience (origin level, always available if the origin qualifies). The lab half of the response is the full Lighthouse JSON, including the audit list you need for diagnosis. Rate limits apply, so a large site needs queueing and a sensible sampling plan. The PageSpeed Insights API guide covers request shape, quota handling, and how to parse the parts that matter.

The CrUX API returns field data only, with no Lighthouse run, which makes it much cheaper and faster per call. It gives you full histograms rather than just the p75, and it lets you request phone, tablet, and desktop separately. If your monitoring is specifically about the graded metrics and you do not need a fresh audit every time, this is the efficient choice. It also exposes the CrUX History API for a trailing series of weekly datapoints, which is how you build a trend line instead of a single dot.

The CrUX BigQuery dataset publishes monthly, origin level only, with full distributions and country breakdowns. It is the right tool for competitive benchmarking and for questions like "how does our p75 compare to the rest of our category," and the wrong tool for detecting a regression this week.

SourceLabFieldGranularityFreshnessBest for
PageSpeed Insights APIYesYesURL and originLab is live, field is 28 day rollingCombined audit plus grade in one call
CrUX APINoYesURL and origin, by form factor28 day rolling, updated dailyCheap recurring grade checks and histograms
CrUX History APINoYesURL and originWeekly datapoints over a trailing windowTrend lines and regression detection
CrUX on BigQueryNoYesOrigin onlyMonthlyBenchmarking and cohort analysis
Search Console CWV reportNoYesURL groups28 day rollingSeeing which page templates fail at scale
Your own RUM scriptNoYesAnything you instrumentReal timeAttribution, custom segments, non Chrome browsers

One critical eligibility rule cuts across all the CrUX sources: a URL only gets its own field data if it has enough qualifying samples from opted-in Chrome users. Low traffic pages fall back to origin level data, and a brand new page has none at all. If your monitoring dashboard shows "no field data" for half your URLs, that is usually not a bug, it is a sample size floor. Group those pages by template and monitor the template's representative URL instead.

What should a Core Web Vitals monitoring stack look like?

A durable setup has four layers, and most teams stop after the first one.

Layer one, the daily field pull. Once a day, hit the CrUX API for your monitored URLs and origin, store p75 for LCP, INP, and CLS by form factor, and keep the history. Store the raw histogram, not just the p75, because the histogram tells you whether a borderline metric is a broad shift or a small bad segment dragging the tail. This is the number that decides your grade, so it is the number you keep forever.

Layer two, the lab audit on deploy. Run Lighthouse against a fixed set of representative URLs on every production deploy, and diff the audit list against the previous run. Lab data is noisy in absolute terms but reliable for detecting change under identical conditions, especially for render-blocking resources, unminified payloads, uncompressed images, and newly introduced third-party scripts. The point of this layer is not to produce a pretty score, it is to catch the specific change that will degrade your field data four weeks from now.

Layer three, real user monitoring you own. The web-vitals JavaScript library reports all three metrics from your own visitors, including the attribution build that tells you which element was the LCP and which interaction produced the worst INP. Your own RUM covers browsers CrUX does not, segments by logged-in state or page type or campaign, and reports in real time. It will not match CrUX exactly, because CrUX samples differently and only includes Chrome users who opted in. Do not try to reconcile the two to the decimal. Use CrUX for the grade, use RUM for the diagnosis.

Layer four, Search Console. The Core Web Vitals report groups URLs by similarity and shows which groups fail, which is the fastest way to learn that the failure is a template problem rather than a page problem. Pair it with the Search Performance API so you can weight your work by pages that actually receive impressions. The Search Console API guide walks through pulling that data on a schedule.

Skopx's Site Health module assembles the first, second, and fourth layers automatically: Lighthouse scores through PageSpeed Insights, real-user Core Web Vitals through CrUX, Search Console performance data, and an in-house on-page SEO audit that produces a 0 to 100 score with a specific fix list. If you would rather assemble it yourself, the same pattern is straightforward to build as a scheduled job. The technical SEO automation guide covers the scheduling and alerting mechanics, and Skopx's workflow automation can run the pull, compare against yesterday, and post a diff to Slack without you writing the plumbing.

What do you do when lab and field disagree?

Disagreement is normal. The productive move is to identify which of the four standard causes you are looking at, then act accordingly.

Cause one: the fix is real but too recent. Lab improved today, field still reflects a 28 day window that mostly predates the fix. Do nothing except wait and watch the CrUX History series bend. If the weekly datapoints are trending down, the fix landed.

Cause two: the lab environment is not your users. Lighthouse mobile runs a simulated mid-tier device on a throttled connection. If your real audience is mostly desktop on good connections, lab will look worse than field. If your audience skews toward older devices, lab will look better than field. Compare the CrUX phone and desktop splits against your analytics device mix before you trust the lab number as representative.

Cause three: the metric is not measurable in lab. This is almost always INP. A synthetic load cannot click your filter dropdown, open your mega menu, or type into your search box. If field INP is failing and lab looks fine, stop looking at Lighthouse and start profiling actual interactions with the attribution build of the web-vitals library.

Cause four: field data is origin level, not URL level. The page you are auditing has too little traffic to qualify, so PageSpeed Insights is showing you the whole origin's grade next to a Lighthouse run of one specific page. Check whether the response contains loadingExperience for the URL or only originLoadingExperience. Mistaking one for the other produces months of confused work.

A useful triage order: confirm which data you are reading, confirm the form factor, check the histogram shape, then look at the lab audits for a mechanical cause. Only after all four do you start changing code.

Which alerts are worth setting, and which are noise?

Alerting on raw score movement produces a channel everyone mutes within a week. Lab scores fluctuate between identical runs because of variable CPU contention, network timing, and third-party response times. Field p75 moves a little every day as the window rolls.

Alert on these instead:

  • Threshold crossings, not deltas. Fire when a metric moves from good to needs improvement, or from needs improvement to poor. That is the change with consequences.
  • Sustained direction, not single days. Require three consecutive days of degradation before firing, which filters out one-off CrUX window noise.
  • New audit failures in lab. A render-blocking resource that was not there yesterday is worth waking up for, even when the score barely moved. This is the earliest possible warning.
  • Sample availability changes. If a URL had field data and now does not, either traffic collapsed or the URL changed. Both matter.
  • Third-party weight. Track total bytes and request count from domains you do not control. It only ever goes up, and it usually goes up without a code review.

Do not alert on the Lighthouse performance score itself. It is a weighted composite, currently made up of Total Blocking Time, LCP, CLS, First Contentful Paint, and Speed Index, and a two point move tells you nothing about which input changed. Use the score as a headline for reporting and the individual audits for action. The relationship between composite scores and underlying signals is covered further in our SEO health score explainer.

How does Core Web Vitals monitoring fit the rest of your technical SEO work?

Performance is one input among several, and it is easy to over-index on it because it produces such satisfying numbers. Google has been explicit that page experience is a tiebreaker rather than a dominant factor: a fast page with thin content does not outrank a slow page with the answer. The honest framing is that Core Web Vitals monitoring protects you from losing ground you already earned, and it improves conversion behavior on its own merits regardless of ranking.

Run it alongside the rest of the technical checklist: crawlability, canonical correctness, structured data, internal linking, and index coverage. Our website audit checklist covers the full sweep, and what to look for in an SEO audit tool explains how to tell a tool that measures from a tool that only reports.

One more shift worth planning for: an increasing share of discovery now happens through AI assistants that summarize and cite sources rather than sending a click. Those systems fetch and parse your pages too, and a page that is slow or unstable for a browser is often awkward for a crawler as well. If AI-mediated discovery matters to your category, pair your performance work with the practices in our generative engine optimization guide.

Frequently Asked Questions

Why does PageSpeed Insights show a 100 lab score but a failing field grade?

Because they measure different things. The lab score comes from one synthetic load on a simulated device under controlled conditions, run just now. The field grade comes from the 75th percentile of real Chrome user experiences over the trailing 28 days, across every device, network, and geography in your traffic. A single clean load proves the page can be fast, not that it usually is. Check the form factor split and the histogram shape in the field data to see which segment is failing.

How long after a fix does CrUX data update?

CrUX uses a rolling 28 day window and refreshes daily, so improvement appears gradually rather than all at once. You should see the trend begin bending within a few days if the fix affects most page views, and the full effect lands after the window has completely turned over. If you need a same-day signal, that is what your own RUM instrumentation is for. Search Console's Core Web Vitals report reflects the same underlying data and moves on the same schedule.

Can I measure INP without real users?

Not properly. INP requires actual interactions, and a synthetic audit does not interact with your page. Lighthouse reports Total Blocking Time as the closest lab proxy, and it is genuinely useful for finding the long main thread tasks that cause bad INP, but it is not the graded metric and it has no Core Web Vitals threshold. To measure INP for real, deploy the web-vitals library with attribution enabled, or read INP from CrUX and profile the interactions it points you toward.

Should I monitor at URL level or origin level?

Both, for different purposes. Origin level is always available if your site qualifies at all and gives you the overall trajectory, which is what you report to stakeholders. URL level is only available for pages with enough qualifying samples, and it is what you actually debug against. The practical approach is to pick a representative URL per page template, monitor those at URL level, and track the origin alongside them. Pages that never accumulate enough samples inherit the origin grade in practice, so fix the template rather than the page.

What does Skopx do for Core Web Vitals monitoring?

Site Health pulls Lighthouse scores through the PageSpeed Insights API, real-user Core Web Vitals through CrUX, and performance data from Search Console, then runs an in-house on-page SEO audit that returns a 0 to 100 score with a specific fix list rather than a generic grade. It sits inside a platform that connects nearly 1,000 business tools, so the same data can feed a chat-built workflow, a scheduled briefing, or an internal dashboard. Plans start at $5 per month for Solo and $16 per seat per month for Team; see pricing for what is included.

Share this article

Skopx Team

The Skopx engineering and product team

Related Articles

Stay Updated

Get the latest insights on AI-powered code intelligence delivered to your inbox.