The scoring, explained
How the Lighthouse score is actually calculated
Every explanation I found was either three sentences or the source code. This is the middle. Which five things carry marks, how a timing becomes points, and why fixing a slow page often wins you nothing.
What Lighthouse actually is
Lighthouse is a program that loads your page and times what happens. That is genuinely all it is.
- Opens your page on a pretend slow phone
- On a pretend slow connection
- Writes down how long various things took
- Turns those timings into a score out of 100
- Separately runs some yes-or-no checks about accessibility, security and search
It is built into Chrome. Open DevTools, click the Lighthouse tab, press the button. Same program.
Lighthouse does not test your page on your fast laptop and fast broadband. It deliberately simulates a cheap Android phone on a poor mobile connection, because that is closer to what a lot of real people have.
This is why your site always scores worse in Lighthouse than it feels in your own browser. That is not a bug, it is the point.
What PageSpeed Insights adds
PageSpeed Insights, usually shortened to PSI, is a website that runs Lighthouse for you on Google's machines instead of yours. So the bottom half of a PSI report is a Lighthouse report. Same tool, same score.
But it adds one thing Lighthouse cannot do alone.
PSI also shows what real visitors to your site actually experienced.
Google quietly collects timings from real Chrome users. If enough people visit your site, Google has a record of how it performed for them, and PSI shows that at the top.
PageSpeed Insights
├── Real visitor data only PSI has this. Google's records.
└── Lighthouse test result the same thing you can run yourself
If your site is small, that top section says No data. Not enough traffic for Google to have collected anything.
The two numbers everyone confuses
This is the biggest source of confusion in the whole subject, so it comes early.
| The Lighthouse test | Real visitor data | |
|---|---|---|
| Also called | the Performance score | Core Web Vitals |
| Comes from | one test on a pretend phone | thousands of real visits |
| How fast you see it | instantly | a rolling 28 day average |
| Reacts to a fix | immediately | takes weeks |
| Used for search ranking | no | yes |
The score out of 100 is a diagnostic. It exists to show you problems, on purpose, on a slow phone. It is not your grade.
The real visitor data is the grade. That is what affects ranking, and it takes about a month to react to anything you do.
You can score 40 in Lighthouse and still pass Core Web Vitals, if your real visitors are all on fast phones. And the reverse.
The four scores do not add up
A report gives you four numbers.
60 Performance
79 Accessibility
92 Best Practices
100 SEO
These are four separate reports. They do not add up, they do not average, and there is no overall score. Getting 100 on SEO says nothing about your speed.
They also work in two completely different ways. Performance measures things: how many seconds did this take, with partial credit for being a bit slow. The other three are checklists: did you put alt text on your images, yes or no, no partial credit.
The rest of this is about Performance, because that is the one you will spend your life on.
Performance is five numbers added up
One hundred points, split between five timings. Nothing else in the section is scored.
| What it measures | Points | Short name |
|---|---|---|
| How long the page was frozen | 30 | TBT |
| How long until the biggest thing appeared | 25 | LCP |
| How much the page jumped about | 25 | CLS |
| How long until anything appeared | 10 | FCP |
| How quickly the page filled in | 10 | SI |
| How fast it reacts when you tap | 0 | INP |
What each one means
How long the page was frozen. 30 points. While a page loads, JavaScript runs, and while JavaScript runs the page cannot respond to you. Tap a button and nothing happens. This measures the total time the page was unresponsive, in milliseconds.
How long until the biggest thing appeared. 25 points. Usually a large image or heading. If it is missing, the page looks broken to a visitor.
How much the page jumped about. 25 points. You go to tap a button, an image loads above it, everything shifts down, you tap the wrong thing. Not a time. A number where 0 means nothing moved.
How long until anything appeared. 10 points. How long the visitor stared at a blank screen before anything showed up.
How quickly the page filled in. 10 points. Not a single moment, but how steadily the page filled up.
Your report also shows INP, how quickly the page reacts when you tap something. It is worth zero points. It is displayed and never scored, because a load test never taps anything. It only means something in the real visitor data.
How a timing turns into points
Two steps, and this is the part that trips everyone up.
Step one: your timing becomes a percentage
Every one of the five has its own scale, built from two reference points taken from what real websites actually manage.
| Measurement | scores 90% | scores 50% |
|---|---|---|
| How long the page was frozen | 200ms | 600ms |
| Until the biggest thing appeared | 2.5s | 4.0s |
| How much the page jumped about | 0.10 | 0.25 |
| Until anything appeared | 1.8s | 3.0s |
| How quickly it filled in | 3.4s | 5.8s |
Read the first row as: a page frozen for 200ms scores 90%, a page frozen for 600ms scores 50%. Roughly, the 90% point is what a good site manages and the 50% point is average.
Step two: percentage times points available
your timing -> look it up on its scale -> a percentage
-> times the points available -> your points
So a page frozen for 320ms sits between 200 and 600, closer to 200. On the scale that comes out at 77%. And 77% of 30 points is 23 points.
Do that five times, add them up, and that is your score. Nothing more clever than that.
The five scales in full
Worked out by running Lighthouse's own scoring function. Find your number in the left column and read across.
How long the page was frozen, out of 30
| Your timing | Percent | Points |
|---|---|---|
| 0ms | 100% | 30.0 |
| 100ms | 98% | 29.5 |
| 200ms | 90% | 27.0 |
| 320ms | 77% | 23.0 |
| 400ms | 68% | 20.5 |
| 600ms | 50% | 15.0 |
| 800ms | 37% | 11.1 |
| 1200ms | 21% | 6.3 |
| 2000ms | 8% | 2.4 |
Until the biggest thing appeared, out of 25
| Your timing | Percent | Points |
|---|---|---|
| 1.5s | 100% | 24.9 |
| 2.5s | 90% | 22.5 |
| 3.0s | 78% | 19.6 |
| 4.0s | 50% | 12.5 |
| 5.0s | 27% | 6.8 |
| 6.0s | 13% | 3.4 |
| 7.3s | 5% | 1.3 |
| 9.0s | 1% | 0.3 |
| 12.0s | 0% | 0.0 |
How much the page jumped about, out of 25
| Your number | Percent | Points |
|---|---|---|
| 0 | 100% | 25.0 |
| 0.05 | 99% | 24.7 |
| 0.10 | 90% | 22.5 |
| 0.15 | 76% | 19.1 |
| 0.20 | 62% | 15.6 |
| 0.25 | 50% | 12.5 |
| 0.35 | 32% | 8.0 |
| 0.50 | 17% | 4.2 |
Until anything appeared, out of 10
| Your timing | Percent | Points |
|---|---|---|
| 1.0s | 100% | 10.0 |
| 1.8s | 90% | 9.0 |
| 2.4s | 71% | 7.1 |
| 2.9s | 53% | 5.3 |
| 3.0s | 50% | 5.0 |
| 4.0s | 24% | 2.4 |
| 5.0s | 10% | 1.0 |
How quickly it filled in, out of 10
| Your timing | Percent | Points |
|---|---|---|
| 2.0s | 99% | 9.9 |
| 3.4s | 90% | 9.0 |
| 4.5s | 73% | 7.3 |
| 5.4s | 57% | 5.7 |
| 5.8s | 50% | 5.0 |
| 7.0s | 33% | 3.3 |
| 9.0s | 15% | 1.5 |
These are the phone scales. Desktop is stricter, because desktops are faster. Lighthouse picks the right one for you.
One whole report, worked out
A real site, on a phone, on a slow connection. Here is what it measured.
frozen for 320ms
biggest thing appeared 7.3s
jumped about 0
anything appeared 2.9s
filled in 5.4s
Each timing looked up on its own scale:
| Timing | On its scale | Available | Earned |
|---|---|---|---|
| 320ms frozen | 77% | 30 | 23 |
| 7.3s biggest thing | 5% | 25 | 1 |
| 0 jumping | 100% | 25 | 25 |
| 2.9s anything appeared | 53% | 10 | 5 |
| 5.4s filled in | 57% | 10 | 6 |
23 + 1 + 25 + 5 + 6 = 60
Performance: 60 out of 100
At the top of every report Lighthouse prints this as
FCP +5 LCP +1 TBT +23 CLS +25 SI +6. Those plus numbers are the last column
of that table. Add them up and you have your score.
Where the 40 missing points went
24 missing biggest thing appeared
7 missing page frozen
5 missing anything appeared
4 missing filled in
0 missing jumping
24 of the 40 are in one place. Everything else put together is 16. That is the number worth acting on, and no report ranks them for you like this.
Why the scale bends, and why small fixes win nothing
The scales are not straight lines. Look at the biggest-thing scale again.
7.3s -> 1 point
6.0s -> 3 points 1.3 seconds faster won 2 points
4.0s -> 12 points 2.0 seconds faster won 9 points
2.5s -> 22 points 1.5 seconds faster won 10 points
The same improvement is worth wildly different amounts depending on where you start. At the slow end the scale is nearly flat. Shaving a second off a seven second page wins almost nothing. The points are all bunched at the fast end.
Two things follow from that.
On a page like this, a small improvement to the biggest-thing timing is worth about nothing. You have to roughly halve it before points appear. Half an afternoon of work can move the score by one, which reads as failure and is really just the shape of the curve.
Three changes that each save half a second win almost nothing separately. Together they move 7.3s to 5.8s, which crosses into the steep part and is worth real points.
No report tells you this. You get a list of savings in kilobytes, in no particular order, with no indication of which ones cross a threshold.
The 44 items that score nothing
The Performance section lists 49 items. Only 5 are scored, the five timings. The other 44 are worth zero points. Including all of these:
Render-blocking requests save 1,150 ms 0 points
Improve image delivery save 149 KiB 0 points
Reduce unused JavaScript save 98 KiB 0 points
Reduce unused CSS save 32 KiB 0 points
Use efficient cache lifetimes save 2 KiB 0 points
They are not useless. They are the advice, and fixing one often speeds up one of the five that count. But that only happens sometimes, and nothing in the report tells you which.
The trap, worked through
The report above says improve image delivery, save 149 KiB. Images mostly affect how long the biggest thing takes to appear. On this page that measurement was already at 7.3 seconds, earning 1 point of 25.
Saving 149 KiB might take it from 7.3s to 6.8s. Look that up on the scale and it is worth about one extra point.
So you would spend an afternoon compressing images, watch the score go from 60 to 61, and reasonably conclude the tool is lying to you. It is not. You were on the flat part of the curve and nothing said so.
The short version
- PSI is Lighthouse plus real visitor data. Nothing more.
- The
+23 +1 +25 +5 +6at the top of a report is your score broken down. Add them up. - Only 5 of the 49 items are scored. The other 44 are suggestions.
- The scale is flat at the slow end. A small improvement to a very slow timing is worth nothing.
- The score is a lab test. Google ranks you on real visitor data, a different number that takes a month to react.
Where these numbers came from
Nothing here is from memory. Run these against your own report:
# points for each timing
jq -r '.categories.performance.auditRefs[]
| select(.weight>0) | "\(.weight) \(.id)"' report.json
# how many items are shown versus scored
jq -r '.categories.performance.auditRefs
| "shown: \(length), scored: \(map(select(.weight>0))|length)"' report.json
# the scale reference points, from Lighthouse's own source
grep -A6 "defaultOptions" \
node_modules/lighthouse/core/audits/metrics/largest-contentful-paint.js
Then the harder question
Once you know which of the five to aim at, the next problem is telling whether your fix actually worked. Run the same untouched page twice and the score moves on its own, often by more than a real fix is worth. That is what I am building PafCore to settle.
See what it does