Skip to content
AgencyProofby Intelliblitz

Method note

How to report a Lighthouse score without overstating it

Run Lighthouse twice on the same page and the number moves. That is the tool working correctly. This is a run protocol that produces a number you can defend, and the sentence to put beside it when a client asks what it proves.

Balaji Ponnambalam8 min read
One clamped paper maquette stands between two differently built measuring rigs, their blank dials resting at plainly different angles, while an inspector steadies the finer arm under a single lamp.

Seven Lighthouse runs, one page, one afternoon, one laptop.

RunDevice profileNetwork settingPage statePerformance scoreLCPCLSTBTWhat changed
1Mobile, 412 by 823Simulated, 150 ms RTT, 1,638 Kbps, 4x CPUCold, storage cleared991,005 ms0.0460 msBaseline
2Mobile, 412 by 823Simulated, 150 ms RTT, 1,638 Kbps, 4x CPUCold, storage cleared991,052 ms0.0460 msNothing
3Mobile, 412 by 823Simulated, 150 ms RTT, 1,638 Kbps, 4x CPUCold, storage cleared99995 ms0.0460 msNothing
4Mobile, 412 by 823Simulated, 150 ms RTT, 1,638 Kbps, 4x CPUCold, storage cleared100995 ms0.0460 msNothing
5Mobile, 412 by 823Simulated, 150 ms RTT, 1,638 Kbps, 4x CPUWarm, storage kept from run 4100862 ms0.04610 msPage state
6Desktop, 1,350 by 940Simulated, 40 ms RTT, 10,240 Kbps, 1x CPUCold, storage cleared99342 ms0.0000 msDevice preset
7Desktop, 1,350 by 940Simulated, 40 ms RTT, 10,240 Kbps, 1x CPUCold, storage cleared100324 ms0.0000 msNothing
Scroll for more →

This evidence is first-party. I ran these against https://www.intelliblitz.com/, a site we own, on 2026-07-28 between 13:32 and 13:34 UTC. They describe that page at that moment. They are not a benchmark, and no third-party site was touched to produce them.

Read the first four rows again. Nothing was changed between them, and the score still moved. That is the instrument behaving normally, and Lighthouse documents why it happens: page nondeterminism, local network variability, web server load, client hardware, resource contention from whatever else the machine is doing, and the browser's own scheduling. Its own advice is blunt about the remedy. The median score of five runs, the documentation says, is twice as stable as one run.

So the useful question is not which number is correct. It is what a number is allowed to support, and that depends on how it was produced.

Step 1. Write the configuration down before you write the number down

A performance score is not a measurement. It is a weighted average of five metric scores, and the weights carried in the runs above are First Contentful Paint 10, Speed Index 10, Largest Contentful Paint 25, Total Blocking Time 30, Cumulative Layout Shift 25. Two of those, LCP and TBT, carry more than half the result between them. A score that moves may be reporting a real change in one metric, a rounding boundary in another, or nothing at all.

Every one of those five metrics is produced under conditions the tool or you chose. Record them before you record the number, because a score without its configuration cannot be repeated, and a result nobody can repeat is an anecdote.

Step 2. Run it four times and change nothing

Four identical runs is enough to see a spread rather than a coincidence, and one short of what the documentation asks for. Mine produced 99, 99, 99 and 100. A fifth would have made the median defensible; I ran four, which is a limit on this evidence, not a recommendation.

What moved and what did not

The score moved by one point. Underneath it, LCP ranged from 995 ms to 1,052 ms, a spread of 57 ms. Speed Index, which the table does not carry, ranged from 2,480 ms to 2,840 ms, a spread of 360 ms on a base of 2,480. CLS was 0.046 in all four. TBT was 0 ms in all four.

That last pair matters more than the first. The two metrics that stayed still are the ones with the heaviest weights, and they stayed still because this page has almost no JavaScript work to block the main thread. On a page with a heavy bundle, TBT is where the noise lives, and TBT is 30 percent of the score. The spread you see is a property of the page under test, not a constant to carry to the next site.

Run 4, the highest number in the set
Performance 100 LCP 995 ms | CLS 0.046 | TBT 0 ms Lighthouse 13.4.0, Chrome 150.0.7871.187, headless Mobile emulation, simulated throttling, storage cleared 2026-07-28T13:33:16Z

EstablishesOne lab result for one URL, under one recorded configuration, at one moment, on one machine.

Does not establishWhat any visitor experienced. Whether the page is faster than it was last month. Whether 100 is repeatable, which only the other runs can address, and they answer 99.

Step 3. Change the device profile, then read what else moved

Runs 6 and 7 use the desktop preset. The score barely moved. Everything under it did: LCP fell from about 1,000 ms to about 330 ms, and CLS fell from 0.046 to 0.000.

The preset is a configuration, not a variable

Changing one flag did not change one thing. The desktop preset swaps the emulated viewport from 412 by 823 to 1,350 by 940, drops the CPU slowdown from 4x to 1x, and changes the simulated network from 150 ms and 1,638 Kbps to 40 ms and 10,240 Kbps. Three variables move together. If you want to isolate the viewport, you have to override the throttling settings by hand and say that you did.

Layout shift is a property of the viewport as much as the page

CLS of 0.046 on mobile and 0.000 on desktop is the same markup measured against two different layouts. The desktop runs also requested 95 resources where the mobile runs requested 80, because responsive images resolve differently at a different width. Neither number is the truth about the page. They answer different questions, and only one of them matches how most of that site's visitors arrive.

Step 4. Change the page state and watch the network leave

Run 5 is the baseline configuration with one flag added, --disable-storage-reset, executed immediately after run 4 in the same browser profile.

A warm run is a different question, not a better answer

The page transferred 8,172 bytes. Runs 1 through 4 each transferred about 5.5 MB. LCP dropped to 862 ms, below anything the cold runs produced, and TBT rose from 0 ms to 10 ms.

That is a legitimate measurement of a returning visitor and a dishonest measurement of a first visit. If a report quotes a warm number without saying so, the client is being shown the best case and told it is the case. Say which one you ran, in the same sentence as the number.

Step 5. Decide what leaves the building

Now the number has to survive a client asking what it means.

Question the client asksOne lab runRepeated lab runsField data
Is the page slow right now?Weak, one sample under one configurationYes, for that configuration and momentYes, for real visits in the collection window
Did our fix help?No, the change may be smaller than the spreadYes, if the spread is smaller than the changeYes, once enough visits accumulate
What do our actual visitors experience?NoNoYes, within the dataset's eligibility rules
Which element is holding LCP back?Yes, the diagnostic names itYes, and confirms it is consistentNo, field data reports timings, not causes
Is this page faster than a competitor's?No, and do not ask this of a lab runNoOnly where both are in the dataset
Scroll for more →

The right column deserves a name. The Chrome UX Report is a dataset that reflects, in its own words, how real-world Chrome users experience popular destinations on the web: real visits, real devices, real networks, subject to eligibility rules that exclude pages without enough traffic to be statistically meaningful. It is not a better lab run. web.dev is explicit that connection setup, redirects and other delays before the first byte land inside field LCP and can push the two apart.

Column two is the one most reports skip. Repeating the run takes minutes and converts a number you have to hedge into a number you can defend.

Step 6. Write the sentence that travels with the number

The command that produced run 1, verbatim, so the whole thing is repeatable:

lighthouse https://www.intelliblitz.com/ \
  --only-categories=performance \
  --output=json --output-path=run-1.json \
  --chrome-flags="--headless=new --user-data-dir=/tmp/lh-profile \
    --no-first-run --no-default-browser-check" \
  --quiet

Run 5 adds --disable-storage-reset. Runs 6 and 7 add --preset=desktop. Nothing else differs.

None of this is an AgencyProof capability. What the product does in this family is narrower: it checks first-pass performance signals on sampled pages. Static performance signals and Lighthouse lab measurements, when present, are point-in-time diagnostics. They are not field data or a guarantee of user experience. If you want a lab score, you run the tool yourself, exactly as above.

What the protocol cannot give you is a claim about visitors. Seven runs on one laptop on one connection describe one machine's view of one page. They do not tell you what the site felt like to somebody on a train, and no number of repetitions will convert lab evidence into field evidence.

So here is the sentence to put beside the number, with your own values substituted:

Lighthouse 13.4.0 scored this page 99 on four consecutive mobile runs and 100 on one, under simulated throttling with a cleared cache, on 2026-07-28. That is a lab result for this page under those conditions, not a measurement of what visitors experienced.

Provenance

Written by
Balaji PonnambalamFounder, AgencyProof
Technical review
Written and self-reviewed against the codebaseAgencyProof is a one-person engineering team; there is no second reviewer to claim.
Published
Evidence basis
Examples come from AgencyProof's own sites, scanned by us.

Every product claim in an article is checked against the AgencyProof source tree before publication, and traced to the code path that implements it. Where the article describes a method rather than a shipped behaviour, it says which it is.