← All posts

Field vs lab data, and why Lighthouse, CrUX and RUM disagree


Lighthouse, CrUX and your own real-user monitoring (RUM) disagree because they measure different visits: Lighthouse times one load on a simulated device, CrUX summarizes 28 days of visits from a subset of Chrome users at the 75th percentile, and RUM reports whatever your script collects from whichever browsers support each metric. Use CrUX to see where you stand in Google's Core Web Vitals assessment, RUM to find which templates, elements and scripts cause the problem, and Lighthouse or DevTools to reproduce and fix it.

Much of the confusion comes from asking one of them to do another's job, such as treating a Lighthouse score as a prediction of Search Console, or expecting a RUM dashboard to match CrUX to the millisecond.

Three sources side by side

CrUXYour RUMLighthouse
Who is measuredOpted-in Chrome users, desktop and AndroidEvery visitor your script runs forOne simulated visit
BrowsersChrome onlyAll, within each browser's metric supportChrome
Pages coveredPublic URLs with enough trafficAny page carrying the scriptAny URL you can load
Aggregation75th percentile per device typeWhatever you configureA single run
Time windowRolling 28 daysNear real timeThe moment of the test
INPFrom real interactionsFrom real interactionsNot in a standard run; TBT as a proxy
Best used forPass or fail as Google reports itLocating causesReproducing, debugging, regression checks

Who CrUX counts and who it leaves out

The CrUX methodology page sets narrow eligibility. A visit counts only when the user has usage statistics reporting turned on, syncs their browsing history, has no sync passphrase, and uses Chrome on desktop (Windows, macOS, ChromeOS, Linux) or on Android. Chrome on iOS, Android apps that use WebView, and other Chromium browsers such as Edge are excluded. Pages and origins must be publicly discoverable and "sufficiently popular", with no threshold disclosed, and responses with a status other than 200 are left out.

Three consequences follow:

  • An audience that mostly browses on iPhones shows up in CrUX only through its Android and desktop visitors.

  • Low-traffic pages have no URL-level data. PageSpeed Insights then falls back to origin-level data, and shows no field data if the origin is also too small. Search Console groups similar URLs and needs a minimum amount of data per group. Google has not documented how ranking treats pages without field data, so claims either way are guesses.

  • Field data only includes people whose page loaded. web.dev's explanation of why lab and field data differ points out that it covers only users who were able to load the site. A visitor who gave up on a blank screen leaves no LCP value behind.

CrUX matters for search because it feeds the Core Web Vitals report in Search Console, and Google's page experience documentation states that "Core Web Vitals are used by our ranking systems." The same page adds that Search "always seeks to show the most relevant content, even if the page experience is sub-par." The Lighthouse performance score is a lab composite and plays no part in that report.

Why Lighthouse sees a different page than your users

Start with how Lighthouse runs. According to its throttling documentation, the default is simulated throttling: Lighthouse loads the page without throttling on whatever machine runs it, then models how that load would have gone on a 150 ms latency, 1.6 Mbps connection and on a CPU four times slower than the host. Because the CPU slowdown is relative to the host, the same page can score differently on a fast laptop and on a busy CI server. PageSpeed Insights runs Lighthouse with a mid-tier mobile device profile. None of this describes a specific user. It is a fixed yardstick, which makes it good for before-and-after comparisons and poor as a stand-in for your audience.

On top of that, each metric diverges for its own reasons.

LCP

The largest element in the lab viewport may not be the largest one on a given phone. Personalized content can change the LCP element per user. Lab loads start with a cold cache, while returning visitors already have the CSS, fonts and hero image cached. Lab tests ignore the back/forward cache, which makes some field navigations close to instant. And in the field the browser stops looking for larger elements once the user scrolls or interacts. Field LCP can end up better or worse than the lab value depending on which of these dominates.

CLS

Lab CLS covers shifts that happen during load, above the fold. Field CLS counts unexpected shifts across the whole life of the page, including those that only occur after scrolling (lazy-loaded ads, late embeds, sticky bars) and content inserted for some users only (personalization, consent and geo banners). Those are exactly the shifts a lab run misses. The CLS guide covers how to fix each cause.

INP

Only real interactions produce INP. A standard Lighthouse run never clicks anything, so it reports Total Blocking Time (TBT), which measures how much the main thread was blocked during load. TBT says nothing about a slow handler on a filter button minutes into a visit. web.dev also describes a mobile tap delay, on pages without a mobile viewport tag, that affects INP but not TBT. The guide to finding and fixing slow interactions shows how to identify them with attribution data.

Why your RUM tool and CrUX still disagree

Both are real-user data, so a gap between them looks like a bug. The causes are mostly mundane:

  • Since Safari 26.2 shipped in December 2025, LCP and INP are measurable in all major browsers, while CLS is still measurable only in Chromium. Your RUM LCP and INP now include Safari and Firefox visitors, which CrUX never will, and your RUM CLS covers fewer browsers than your RUM LCP.

  • The same announcement notes a small difference in where the clock stops: Chrome measures to the moment a frame is presented, Firefox and Safari to the earlier paint time.

  • CrUX also drops Chrome on iOS, WebView traffic, Edge, and Chrome users without history sync. RUM includes them.

  • Many RUM dashboards default to the median or the average, per page view or per session. CrUX reports the 75th percentile per device type over 28 days.

  • RUM includes logged-in areas, checkout and low-traffic URLs. CrUX covers public, sufficiently popular URLs, grouped in Search Console the way Google decides.

  • A RUM script that is sampled, loads late, or only runs after analytics consent undercounts visits that end early and visitors who decline consent.

To reconcile the two, filter RUM to Chrome on desktop and Android, compute the 75th percentile per device type over the same 28 days, and restrict it to the public URLs that appear in CrUX. If the numbers now roughly agree, the gap was population. If they still differ, look at sampling, consent gating and when the script loads.

A hypothetical case where the lab misses a CLS failure

Say a news site's article template scores well in Lighthouse, with CLS close to zero in the lab report, yet Search Console marks the mobile article group as poor for CLS. The site's RUM data, filtered to Chrome on Android, agrees with Search Console. The web-vitals attribution build, which reports the element behind the largest shift, points at the article body container, with shifts recorded one to three seconds after load. Splitting the poor values by country shows they come almost entirely from visitors in the EU.

The explanation: the consent platform shows a banner only where consent is required, and inserts it above the content once its location lookup returns. The lab test runs from a location where no banner appears, so Lighthouse never sees the shift. The fix is to render the banner as an overlay, or to reserve its space from the first paint. The lab can verify the fix only after the test is set up to show the banner, and the field confirms it over the next 28 days.

Making a lab run resemble your audience

Before trusting a lab result for a decision, line up the test conditions with the field data:

  • Test the device type that fails in Search Console, not the one that is easiest to emulate.

  • Calibrate CPU throttling. With field data enabled, the DevTools Performance panel shows your local values next to CrUX and suggests throttling settings based on it; without it, remember that a 4x slowdown is relative to your own machine.

  • Match the network to the slower quarter of users, since the assessment sits at the 75th percentile.

  • Test cold and warm cache if returning visitors are a large share of traffic.

  • Reproduce the logged-in, consent and location states that change what the page shows.

  • Use a viewport size common in your field data, because the LCP element can change with it.

  • Interact during and after load when INP is the problem.

  • Run several times and compare medians, because single runs vary.

Using all three in one loop

The sources fit together in a fixed order:

  1. CrUX, through Search Console or PageSpeed Insights, picks the problem: which metric, which device type, which URL group.

  2. RUM localizes it to a template, an element, a script, a browser or a country.

  3. The lab reproduces and explains it with a DevTools trace, and Lighthouse records the before and after.

  4. After release, RUM confirms the change within days and CrUX over the following 28 days, which is also how long the Search Console validation period lasts.

The Lighthouse score has a place in this loop, as a regression check in CI with a budget per metric. It makes a poor team KPI. It is a weighted composite from one simulated device, so targeting it rewards changes that move the lab score whether or not users notice, and it hides everything only the field shows: interactions, late shifts, slow devices. Report field percentiles per template to stakeholders instead, and record them before any redesign or replatform, since the site migration checklist depends on having that baseline to compare against. Keeping three data sources running takes effort that small teams may not have, a concern raised in the piece on whether Google has set web standards too high. If you can only add one thing, add RUM with attribution on your most important template, because it is the only source that tells you both where and why.