Lightscore

Speed Index (SI)

Speed Index measures how fast the visible part of a page fills in. It isn't one moment in the load. Lighthouse rates the frames of the load for how finished they look, then adds up the time the screen spends incomplete. It marks 3.4 seconds or less green on the mobile profile, and 1.3 seconds or less on desktop. The metric carries 10 percent of the performance score.

Those frames form a filmstrip, and the filmstrip has a Speed Index of its own. The number Lighthouse prints is a different one. On the mobile profile it's at least 1.4 times higher, and sometimes it's exactly your FCPTime until the browser paints the first text or image..

What is a good Speed Index?

Device Fast Moderate Slow
Mobile 0–3.4 s 3.4–5.8 s over 5.8 s
Desktop 0–1.3 s 1.3–2.3 s over 2.3 s

The control points sit in the Lighthouse source. On mobile, 3,387 ms scores 90 and 5,800 ms scores 50. On desktop those two scores land at 1,311 ms and 2,300 ms. Both pairs are quantiles of real pages from the HTTP Archive, and both crawls are from 2018 — April for mobile, December for desktop. The curve you're graded on is calibrated against the web of 2018.

There's no field threshold to compare against. Google collects LCPTime until the largest thing in view (hero image, headline) has painted., INPHow long the page takes to visibly respond to a tap, click or key press., CLS and FCP from real Chrome users. It doesn't collect Speed Index.

How the filmstrip number works

Chrome writes screenshots into the trace. Speedline takes the first frame and the last frame as the two ends of the load. Every frame in between gets a progress percentage on that scale. Speed Index is then the first paint, plus the time the page spends short of finished:

SI = firstPaint + Σ (elapsed × (1 − progress))

So a page that paints most of itself early scores better than one that finishes in a late rush.

That scale is a colour histogram match, not a measure of meaning. Speedline counts the pixels at each intensity, per colour channel, and compares those counts. Two frames with the same colours in different places look identical to it. Each frame is also scored on its own, against the two ends, so progress can go down as well as up. In the run below it reads 54 percent at 3 ms, then 4 percent at 102 ms.

Visual progress (%) Time since navigation start (ms) 0 20 40 60 80 100 0 200 400 600 800 1,000
bbc.com on the mobile profile, Lighthouse 12.8.2. The filmstrip reaches 100 percent at 812 ms. The same run reports a Speed Index of 7,418 ms.

That curve gives a Speed Index of 536 ms. You'll find your own at audits.metrics.details.items[0].observedSpeedIndex, in any Lighthouse performance run.

Why is my Speed Index higher than the page looked?

Because Lighthouse doesn't report the filmstrip. Its default throttling method is simulate. Chrome loads your page over the real connection, and Lantern — Lighthouse's simulator — replays the request graph on a modelled slow one. The screenshots belong to the load that happened, not to the modelled one. So Lantern estimates the rest.

The estimate blends two numbers:

On the mobile profile the weights are 1.4 and 0.4. On desktop they're 0.575 and 0.492. They scale with the round-trip time of the throttling profile — a 50/50 blend at 30 ms, moving to the tuned pair at 150 ms. Then one last step raises the result to at least the simulated FCP.

Filmstrip
observedSpeedIndex

Blend
1.4 × filmstrip
+ 0.4 × layout

Simulated Layout tasks
log2-weighted end time

Raise to at least
the simulated FCP

speed-index
in your report

How Lighthouse builds the Speed Index it reports. The filmstrip is one of two inputs to the blend, and the step after it can replace the result with FCP.

I ran five pages on the mobile profile with Lighthouse 12.8.2, one run each, on a laptop on 2026-08-14. All three columns come out of the same JSON file:

Page Filmstrip SI Reported SI Reported FCP
bbc.com 536 ms 7,418 ms 7,418 ms
en.wikipedia.org 573 ms 2,159 ms 1,488 ms
web.dev 1,103 ms 3,733 ms 2,926 ms
vercel.com 1,643 ms 6,122 ms 4,744 ms
github.com 2,694 ms 12,038 ms 12,038 ms

Two rows carry the same number twice, and not because I rounded them. On bbc.com and github.com the reported Speed Index and the reported FCP are the same number, digit for digit. Four of my ten runs came out that way, mobile and desktop together.

So I read Speed Index as the least informative number in the performance section. On a page slow enough to worry about, it often tells you nothing that FCP hasn't. It still moves 10 percent of the score.

That's an opinion built on ten runs on one laptop, so your ratios will differ from mine. The relationship won't. Both numbers sit in the JSON you already have, so go and check your own. A separate page covers the wider version of that question — why two Lighthouse scores disagree.

How to improve it

  1. Cut TTFBHow long the browser waited before the first byte of the response arrived. and delete redirects on the entry URL. Nothing paints until the first byte arrives.
  2. Take render-blocking CSS and JavaScript off the critical path. Inline the styles the first screen needs, and defer the rest.
  3. Set font-display: swap, so text paints in a fallback font.
  4. Load the images on the first screen at a real priority. Lazy-load only what sits below it.
  5. Cut Main-thread workTotal time the browser’s single UI thread spent parsing, compiling and running code. work. The layout half of the estimate is built from main-thread tasks, so work that lays the page out late pushes the value up.

The first three also move FCP, which is the floor under this metric. That's the efficient order to work in.

What we do about it

Every Lightscore result carries speed_index_ms per region, next to LCP, CLS, TBT, FCP and TTITime until the page reliably responds to input., plus the raw Lighthouse JSON and HTML. observedSpeedIndex is in that JSON. The Lighthouse and Chromium versions are pinned and recorded with the run, so two of our numbers are comparable to each other.

What we won't do is hand you a corrected Speed Index. We run stock Lighthouse and report what it says, because a number only we produce is a number you can't check against anything. If you want the measured version, pull observedSpeedIndex out of the JSON and track that across builds instead.

Common questions