Cloaking census · pilot + open protocol

How many sites cheat PageSpeed?

A PageSpeed score is money — so it gets gamed. The sharpest cheat is cloaking: detect Lighthouse or PageSpeed Insights and serve it a stripped, fast page while real visitors keep getting the heavy one. The techniques are publicly documented. What nobody has published is a number: what share of sites actually do it. We did two honest things instead of guessing — ran a real user-agent-flip pilot across the top 2,000 sites, and published the full preregistered protocol to measure it at web scale.

The honest headline: not a number yet — but a floor and a method

Search “how many sites cheat PageSpeed” and you get anecdotes, vendor threads, and one or two GitHub repositories — no population estimate with a denominator, a sampling frame, or a confidence interval. That gap is real, and the wrong way to fill it is to crawl a handful of sites and announce a percentage. So this study is deliberately two-part: a pilot that puts a defensible lower bound on the crudest, most-detectable form of cloaking, and a registered census protocol precise enough to produce the real number without overclaiming.

0published population prevalence estimates, to date
9UA-flip candidates auto-flagged in the pilot
0 / 1,162confirmed after manual review (a lower bound)
±0.06 ppachievable precision at a 100,000-site census

The pilot tests only one thing — whether a site hands a different raw HTML page to a Lighthouse-branded user-agent than to a normal one, from the same IP. That is the bluntest cloaking instrument there is, and it is a strict floor: it cannot see client-side JavaScript cloaking, IP/reverse-DNS cloaking, or User-Agent Client Hints branching, and it does not run the page. A small floor is still informative — it tells you where the cheating isn't (in the easy-to-catch server layer of the most-visited sites) and therefore where a real census has to look. You can run the same core probe on any single URL with our free PageSpeed cloaking test.

What “cheating PageSpeed” actually means

PageSpeed Insights reports two different things about a URL. Field data comes from the Chrome UX Report (CrUX): real Chrome users, their real LCP, INP and CLS over a trailing 28 days. Lab data is a single Lighthouse run in a simulated, throttled environment. The two can legitimately diverge — but only the lab run is a controllable, on-demand, advertisable deliverable. That is the incentive: lab scores are easy to sell, and real-user performance is hard to move because it needs less payload, less main-thread work, and fewer round trips.

Lighthouse's performance score is not a measure of page size; it is a weighted blend of metrics. The weights make it obvious which manipulations pay off — suppress JavaScript and you move the heaviest lever, Total Blocking Time:

Lighthouse 10 performance-score weights (current desktop/mobile scoring). Stripping scripts or media for the measuring client moves TBT, LCP and Speed Index — three-quarters of the score — without improving the page a real visitor loads.
MetricWeightWhat a cloaker targets it with
Total Blocking Time30%Block or defer JavaScript only for the measuring client
Largest Contentful Paint25%Early oversized/hidden LCP candidate; suppress the real hero
Cumulative Layout Shift25%Test-only layout stability; hold back late-shifting content
Speed Index10%Simplified above-the-fold for the lab profile
First Contentful Paint10%Skeleton/partial DOM, early document.close()

This is a lab-tool split-view problem, not a claim about Google Search ranking. Google's spam policy defines cloaking as showing search engines different content to manipulate rankings; PageSpeed cloaking is analogous but distinct — it targets a performance measurement, and it must be defined and measured on its own terms. Throughout, the object is synthetic Lighthouse/PSI split-view serving, not search fraud.

The technique taxonomy — and what a single fetch can and can't see

The public record already documents the mechanisms. The motivating source is a February 2024 GoogleChrome/lighthouse issue opened by a Shopify performance architect, reporting third-party scripts that detect Lighthouse — by the Chrome-Lighthouse user-agent marker, a navigator.platform of Linux x86_64, or a moto g power device string — and then run “LCP hacks,” block JavaScript, prevent lazy images and iframes from loading, and stop HTML parsing with document.close(). The taxonomy below classifies those and the variants a census must anticipate. The last column is the honest scope statement for our pilot.

Cloaking technique families. A raw-HTML, single-fetch probe (our pilot, and the free tool) sees only server-side branching that changes the delivered HTML. Everything else needs a real headless dual-profile crawl.
FamilyExamplesSeen by a raw UA-flip fetch?
Fingerprint detectorsLighthouse UA marker, navigator.platform, UA-Client-Hints, headless/automation, canvas/font, egress IP & reverse DNSPartly — only the UA-string check; not UA-CH, IP or JS fingerprints
Payload suppressionBlock first-/third-party JS, analytics, chat, ads; suppress images/fonts/iframes; skeleton DOMOnly if done server-side; client-side blocking is invisible to a fetch
Metric manipulationEarly oversized/transparent LCP candidate; test-only CLS/TBT tricksNo — needs a real render & trace
Server / middlewareEdge worker or CDN branch on UA/UA-CH/IP; separate templates; redirect divergenceUA-branched HTML: yes. IP/UA-CH branches: no
Benign split viewsResponsive design, geo/locale, consent banners, A/B tests, bot protection, cache stateMust be excluded — these are not cloaking; the pilot's controls do this

Two prior efforts bracket the problem. The closest PageSpeed-specific tool, 0x15f/discover- pagespeed-cloaking, is an engineering prototype tested on “50+ manually reviewed Shopify sites” — useful for feature ideas, but platform-specific, small, and without a sampling frame. The strongest adjacent science, Invernizzi et al.'s Cloak of Visibility (IEEE S&P 2016), proved large-scale multi-profile cloaking detection is feasible — a labeled set of 94,946 URLs at 95.5% accuracy and a 0.9% false-positive rate — but for search and ad cloaking, and it stresses that benign personalization, geo and responsive design make naïve diffs unsafe. Neither answers the PageSpeed prevalence question. That is the gap this work is built to close.

The pilot: a real lower bound on server-side UA cloaking

We took a fixed, citable sampling frame — the Tranco list Q2W74 (generated 2026-06-18), top 2,000 — and fetched each home page's raw HTML four times from the same egress IP, in an ABBA block: normal mobile user-agent, Lighthouse-marked user-agent, Lighthouse again, normal again. The bracketing matters. The two normal loads give an A/A control — how much a site differs from itself between two identical requests (ads, A/B buckets, randomized inventory). The Lighthouse pair gives the A/B signal. A real user-agent flip has to clear a site's own A/A noise to count, not just differ.

The decision thresholds are exactly those in our production cloaking tool: a flip is material only if the Lighthouse HTML is ≥25% lighter, or has ≥3 fewer <script> tags, or drops ≥2 third-party hosts (consent/CMP hosts excluded — Google permits hiding those for Lighthouse). A candidate must additionally be directional (lighter for Lighthouse), stable (both Lighthouse loads show it), and above this site's own A/A noise. Every candidate is then read by hand for a benign explanation before it is allowed to count.

Horizontal bar chart of sample disposition: of 2,000 home pages attempted, a green bar shows how many were cleanly measured, with the rest split across exclusion reasons such as unreachable, non-HTML endpoint, thin or blocked body, and refused the Lighthouse user-agent.
Figure 1 — Sample disposition. A top-sites list is mostly not measurable home pages: CDN, DNS and API endpoints, parked or blocked hosts, and bot walls thin the 2,000 down to the cleanly-measured denominator the prevalence is computed over. Reporting this funnel is mandatory — it is the difference between an honest denominator and a denominator game.

The result is the empirical core of the pilot, and it is mostly a null: flipping to a Lighthouse user-agent moves the delivered HTML no more than a site moves against itself between two identical loads. The two distributions sit on top of each other, and almost nothing reaches the 25% materiality line.

Grouped bar chart comparing two distributions across HTML-size-difference bands (0-1%, 1-5%, 5-10%, 10-25%, and 25% or more). The grey A/A bars (same user-agent, two loads) and the green A/B bars (normal vs Lighthouse user-agent) have nearly identical shapes, both concentrated in the low bands, with almost nothing at or beyond the 25% materiality line.
Figure 2 — The user-agent flip versus a site's own noise. Across 1,162 cleanly-measured sites, 94% show under 1% HTML-size difference when the user-agent is flipped — the same shape as the A/A benign noise floor (97% under 1%). The A/B distribution is not meaningfully shifted “lighter for Lighthouse”: the handful in the high bands are bot-blocks and dynamic-rendering, not stripping.

Nine sites crossed a materiality threshold automatically. Every one was re-fetched and read by hand — and zero survived as deceptive cloaking. Two were bot-protection serving the Lighthouse user-agent a blank page or a “Client Challenge” (anses.gob.ar, slideshare.net) — which hurts the score, the opposite of cloaking. Two were dynamic rendering that handed Lighthouse the fuller prerendered page while the normal user-agent got a “enable JavaScript” shell (roku.com, pluto.tv). Two served the identical visible page in lighter markup (paloaltonetworks.com, cdnvideo.ru). The remaining three (spotify.com, msn.com, temu.com) handed the Lighthouse-marked agent a thin app shell — genuinely differential, but their real content is client-rendered either way and no score-improving mechanism is in evidence, so they stay suspicious, not confirmed. A further 12 reachable sites refused the Lighthouse user-agent outright (bot defense, not score-gaming) and are counted as excluded.

So in 1,162 cleanly-measured top sites, confirmed server-side user-agent cloaking is 0 — a 95% upper bound of 0.26% (rule of three), with the three unexplained cases bounding the worst case at 0.55%. This is a floor, not the answer, and it says something specific: the crudest cloaking is essentially absent in the server layer of the head of the web. That is exactly the prediction that motivates a full census — the cheating, where it exists, lives in client-side JavaScript, IP and fingerprint branching, and the long tail, none of which a single raw fetch can reach. It also shows the harder problem in miniature: a naïve detector would have shipped nine false positives; careful controls and human review took it to zero.

Why “mostly null” is the right pilot result

A pilot that breathlessly “found cloaking everywhere” would be the warning sign. Real top sites run A/B tests, rotate ads, and localize — the A/A control quantifies that churn, and it is the reason a credible detector cannot be a naïve diff. The pilot's job is to prove the measurement machinery (fixed frame, paired profiles, controls, frozen thresholds, manual adjudication) works end-to-end and to bound the easy case. It does. The hard case needs the crawl below.

What a real census takes — the registered protocol

Scaling from “bluntest probe on 2,000 sites” to “defensible prevalence across the web” is not a matter of fetching more pages. It needs a design that survives an adversary and a skeptic. The full protocol — the preregistered analysis plan and labeling rules are in the pack below — is built on six load-bearing ideas.

  1. A fixed frame, real browsers, paired profiles

    A locked Tranco list ID/date as the denominator (CrUX origins as a sensitivity frame), and two version-locked profiles: a real Chrome (REAL_CHROME) and a Lighthouse/PSI emulation (LH_PSI_EMU) harvested immediately before launch, because the fingerprint drifts.

  2. Randomized repeats and ablations

    At least three paired runs per site in randomized ABBA/BAAB order across multiple countries and days, then one-factor-at-a-time ablations (UA only, UA-CH only, navigator.platform only, viewport only, egress IP only) so a positive can be attributed to a specific detector instead of guessed at.

  3. Five-layer feature extraction

    Network (bytes by type, third-party, blocked requests), DOM/content (nodes, text shingles, similarity), visual (screenshot & perceptual-hash with consent zones masked), trace (LCP element geometry, TBT, layout shifts), and static/dynamic code (Lighthouse-string branches, document.close, resource-blocking hooks).

  4. Preregistered materiality, frozen after a pilot

    Directional thresholds set before the main run — total bytes ≥25% and 250 KB lighter; JS bytes ≥30% and 100 KB; third-party requests ≥50% fewer; DOM nodes ≥20% with content loss; text-shingle similarity <0.75 — then frozen, with main-census sensitivity to the thresholds reported.

  5. A four-part confirmation rule + blinded humans

    A confirmed positive is directional, stable in ≥2 of 3 runs, specific (A/A and B/B control diffs smaller than the A/B diff; an ablation localizes the feature), and backed by mechanism evidence. Two blinded reviewers label paired artifacts; a third adjudicates; report Cohen's κ and per-class precision.

  6. False-positive-adjusted prevalence

    No classifier is perfect, so the headline is corrected with the Rogan–Gladen estimator, p_adj = (p_obs + Sp − 1) / (Se + Sp − 1), using the manual-validation sensitivity and specificity — with bootstrap/Bayesian intervals, not a plug-in CI.

And it has to be powered. The reason a pilot bounds rather than estimates is sample size: a credible prevalence with a tight interval needs tens of thousands of sites, not thousands.

Line chart of the 95% confidence-interval half-width against sample size on a log scale, for assumed true prevalences of 1%, 5% and 10%. At 1% prevalence the half-width falls from about plus or minus 0.20 percentage points at 10,000 sites to about plus or minus 0.06 at 100,000 sites and plus or minus 0.02 at one million.
Figure 3 — Precision versus sample size. At a plausible 1% true prevalence, a 10,000-site sample gives ≈±0.20 pp and a 100,000-site census ≈±0.06 pp (95% Wald, before design effects and classifier adjustment). This is why the deliverable is a powered protocol, and why a 2,000-site pilot is honestly labeled a floor.

Who this is for — and the ethics

The most important framing in this whole area: a store owner whose site cloaks PageSpeed is usually a victim, not a perpetrator. The pattern documented in the wild is a third-party “speed optimization” app or freelancer that installs detection-and-stripping to manufacture a green score — so the merchant pays for a number, not a faster store, and often doesn't know. That shapes both the disclosure protocol and the tooling.

  • Check before you accuse. A high lab score with slow real users, or markup that changes for a Lighthouse user-agent, is a prompt to investigate — not proof of intent. Run the free PageSpeed cloaking test on a URL to see the evidence side by side.
  • Disclose responsibly. The protocol notifies platforms and owners privately with minimal reproducible evidence, allows a 60–90 day remediation window, and publishes aggregate prevalence immediately — site-level details only for large platforms or after the window.
  • Behavior, not intent. A public crawl rarely proves who commissioned a behavior. The census estimates what sites do, and says so — no accusations of motive.
  • Measure the real thing. If your CrUX is poor but your lab score is perfect, the fix isn't a better trick — it's a real reduction in payload and main-thread work. That is what our savings-materialization study and a real audit are about.

Limitations — read before quoting

  1. The pilot is a floor, by construction

    It detects only server-side branching on the UA string that changes raw HTML. Client-side JS cloaking, IP/reverse-DNS cloaking, UA-Client-Hints branching, and render-time metric tricks are all invisible to it. The true prevalence of cloaking is at least the pilot's number and almost certainly higher.

  2. One IP, one country, one window

    All fetches leave from a single egress. Geographic and IP-based cloaking can't be seen from one vantage point; the full protocol uses multiple egress countries by design.

  3. No prevalence number is claimed for “cloaking” overall

    The pilot speaks only to the server-side-UA slice on the top 2,000. The population estimate the title asks for requires running the registered crawl; we deliberately do not extrapolate the pilot to “the web.”

  4. The head of the web isn't the tail

    Top sites are the least likely to cloak and the best instrumented. Prevalence almost certainly rises down-rank and on specific platforms — which is why the census stratifies by rank band and CMS.

  5. Raw HTML ≠ rendered page

    We measure delivered markup, a structural proxy. A real census renders and traces both profiles to catch metric-layer manipulation; that is in the protocol, not the pilot.

Data, code & sources

Everything needed to re-run the pilot and to execute the full census is published under CC BY 4.0: the fixed sampling frame, the pilot crawler, the registered analysis plan and labeling protocol, the precision tables, and the result-shell that lists exactly which tables must exist before any numeric prevalence claim.

Key sources

Cite this study

PageSpeedAudit Research (2026). How many sites cheat PageSpeed? A registered
census protocol and user-agent-flip pilot for Lighthouse/PageSpeed Insights
cloaking. https://pagespeedaudit.com/research/how-many-sites-cheat-pagespeed

@misc{pagespeedaudit2026cloaking,
  title  = {How many sites cheat PageSpeed? A registered census protocol and
            user-agent-flip pilot for Lighthouse/PageSpeed Insights cloaking},
  author = {{PageSpeedAudit Research}},
  year   = {2026},
  url    = {https://pagespeedaudit.com/research/how-many-sites-cheat-pagespeed},
  note   = {Tranco-frame pilot + preregistered census protocol, CC BY 4.0}
}

Free 4-part email series

Score theater — the series behind this study

Four short emails, then it stops. The series lives in email only — it isn't published on the site:

  1. Part 1How fake scores are made — the incentive, the score arithmetic, the documented playbook.
  2. Part 2The five-minute fake-score check — lab vs field, Google's screenshot, the UA flip.
  3. Part 3What the top-2,000 pilot found — and why "mostly null" is the honest headline.
  4. Part 4What to do — whether the score is fake, or real but slow.

Double opt-in: we email a confirmation link first. Four emails, then it stops — unsubscribe any time.

Worried a site is cheating its PageSpeed score?

Run the free PageSpeed cloaking test to compare what Google's PageSpeed Insights sees against what a normal visitor gets — the same probe this pilot runs at scale. For a real, code-level diagnosis of your field performance, a PageSpeedAudit report separates genuine fixes from score theater. See also whether the web actually got faster and whether Lighthouse's promised savings materialize.