1
At a glance the headline numbers for Iframes per page
How many iframes the page embeds.
0
on the typical site
half of sites sit at or below
2
1 in 4 sites exceed this
the top quarter
8
the heaviest 1%
the long tail
180,899
sites measured
desktop field data
The typical page embeds 0 iframes.
The State of Web Vitals · Q2 2026 · 189,915 sites · desktop field datacorewebvitals.io/state-of-cwv
2
Distribution & median INP site count and median INP at each level of iframes per page
0ms
63ms
125ms
188ms
250ms
200ms
0
51319
102637
0–0
1–1
2–2
3+
Good (≤200ms)
Needs improvement
Poor (>500ms)
Site count
The State of Web Vitals · Q2 2026 · 189,915 sites · desktop field datacorewebvitals.io/state-of-cwv
3
Passing INP by iframes per page which level passes the INP most often
Iframes per pageSitesPassing INPINP
0–0
102,637
46ms
1–1
31,433
50ms
2–2
21,235
50ms
3+
25,594
59ms
Good
Needs Improvement
Poor
Faded rows: under 100 sites
Iframes per page 0. p75 2. p99 8. At the low end (0–0): INP 46ms. At the high end (3+): INP 59ms. computed
The State of Web Vitals · Q2 2026 · 189,915 sites · desktop field datacorewebvitals.io/state-of-cwv
4
Why this matters for the Core Web Vitals, and where to start fixing it
Each iframe is a separate document with its own resources, scripts and lifecycle, and its work still competes for the same device. The count is a decent proxy for embed weight: chat widgets, videos, ad slots, forms.
Every embed should justify itself. The heavy default (always-on iframe) has a light replacement for almost every case: a facade for video and chat, a static image for maps, a reserved slot for ads.
Related signals
Responsive image markup →
Image fetchpriority →
Script coverage (used vs unused) →
Bytes by resource type →
Chrome field data from 189,915 sites, representing millions of real page loads · How we measured
Chrome field data from 189,915 sites, representing millions of real page loads. How we measured.
Live queries (2) — admin only
Query #1:
193.5 ms
SELECT COUNT(*) AS count,
quantile_disc(m.iframes.total, 0.10) AS p10,
quantile_disc(m.iframes.total, 0.25) AS p25,
quantile_disc(m.iframes.total, 0.50) AS p50,
quantile_disc(m.iframes.total, 0.75) AS p75,
quantile_disc(m.iframes.total, 0.90) AS p90,
quantile_disc(m.iframes.total, 0.99) AS p99
FROM sites WHERE m.iframes.total IS NOT NULL;
Query #2:
144.8 ms
SELECT CASE WHEN m.iframes.total >= 0 AND m.iframes.total < 1 THEN 0 WHEN m.iframes.total >= 1 AND m.iframes.total < 2 THEN 1 WHEN m.iframes.total >= 2 AND m.iframes.total < 3 THEN 2 WHEN m.iframes.total >= 3 THEN 3 END AS bucket_idx, COUNT(*) AS n,
quantile_disc(crux."desktop".inp, 0.5) AS median,
COUNT(*) FILTER (WHERE crux."desktop".inp IS NOT NULL AND crux."desktop".inp <= 200) * 1.0 / NULLIF(COUNT(*) FILTER (WHERE crux."desktop".inp IS NOT NULL), 0) AS good_pct
FROM sites WHERE m.iframes.total IS NOT NULL GROUP BY bucket_idx;
JSON file lookups (4)
20260625/meta.json
0.02 ms
20260625/types.json
0.45 ms
20260625/loaf-scripts.json
0.27 ms
20260625/menu.json
0.13 ms