Security headers are the cheapest defence a website has. A few lines of server config, no code changes, no performance cost, and they shut down whole categories of attack.
So I wondered how many of the world's most-visited sites actually bother. I have a scanner — I built one for a site I run — so instead of guessing, I pointed it at the Tranco top 1,000 and graded every one.
The results were worse than I expected, and the worst offenders were not who I expected either.
The headline
Of the 648 domains that returned a scannable page:
| 55.7% | send no Content-Security-Policy at all |
| 52 | median score out of 100 — a grade C |
| 19.1% | score an outright F |
| 8 | scored a perfect 100 |
Eight. Out of 648.
Google scores an E
This is the bit I keep coming back to.
google.com E 28
microsoft.com E 32
office.com F 12
wikipedia.org E 32
youtube.com A 92
github.com A 95
amazon.com A 92
google.com and youtube.com are the same company. One scores 28, the other 92.
office.com — Microsoft's productivity suite, where a very large number of people keep their working lives — scores 12 out of 100. So does cloud.microsoft. So does office365.com.
I want to be fair about this, because it would be easy to be cheap. Google's homepage is an unusual artefact: it is one of the most performance-tuned pages ever built, it has been iterated on for twenty-five years, and a strict CSP on it would be a genuinely hard retrofit. These companies employ superb security teams.
That is sort of the point. If organisations with that much security expertise haven't retrofitted headers onto their older properties, the odds your side project has them are not good.
Which headers people actually use
| Header | Correct | Partial | Absent |
|---|---|---|---|
| Content-Security-Policy | 23.3% | 21.0% | 55.7% |
| Strict-Transport-Security | 56.9% | 6.2% | 36.9% |
| Clickjacking protection | 58.6% | 0.8% | 40.6% |
| X-Content-Type-Options | 52.0% | — | 48.0% |
There's a clear pattern: the headers that are one line and have no side effects get adopted. X-Content-Type-Options: nosniff is a single value with no configuration and roughly half the web sends it.
CSP is the one that requires you to actually understand your own page — every script source, every style, every frame — and it is the one most people skip. 155 sites send a correct HSTS header but no CSP at all. They did the easy one and stopped.
Having a CSP is not the same as being protected
This was the finding I didn't anticipate.
Of the 287 sites that send any Content-Security-Policy, 102 of them — 35.5% — still allow unsafe-inline for scripts.
That directive re-opens the exact hole CSP exists to close:
Content-Security-Policy: script-src 'self' 'unsafe-inline'
An attacker who can inject a <script> tag into your page runs their code. The policy is present, it shows up green in a lot of checking tools, and it is not stopping the attack it was deployed to stop.
It's usually not negligence — it's the pragmatic outcome of retrofitting CSP onto a site with inline handlers everywhere. unsafe-inline makes the page work again. But it should be understood as a migration step, not a destination. Nonces and hashes are the way out.
Being popular doesn't mean being secure
| Tranco rank | Sites | Mean score |
|---|---|---|
| 1–100 | 70 | 59.4 |
| 101–250 | 94 | 52.8 |
| 251–500 | 148 | 52.7 |
| 501–1000 | 336 | 50.0 |
Under ten points of spread across the entire top thousand. Sixteen of the 35 scannable sites in the top 50 score a D or worse.
I expected a much steeper curve — that the biggest sites would be dramatically better resourced and it would show. It barely does.
What I'd actually do with this
If you run anything, the useful takeaway isn't the statistics, it's that this is unusually cheap to fix relative to how much it buys you.
Start with the two that have no side effects and cannot break your site:
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Then HSTS, once you're confident every subdomain is HTTPS-only:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Then CSP, which is the real work. Deploy it in report-only mode first:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
Collect violations for a week, see what actually breaks, then enforce. And if you land on unsafe-inline to get it shipping — fine, but write yourself a ticket. You are in the 35.5%.
Method, and the data
Because a statistic you can't check is worthless:
- Source list: Tranco top 1,000, retrieved 30 August 2026. Tranco averages several ranking providers over 30 days, which makes it far more stable than any single list.
- One HTTPS GET per domain, homepage only, following redirects. No crawling.
-
648 of 1,000 scanned. 259 were excluded because they have no A record at the apex — Tranco ranks by DNS query volume, so CDN and resolver infrastructure like
akamai.netandcloudfront.netfloods the list without serving any website. The rest were TLS failures, timeouts and redirect loops. - Scanned from a single vantage point, so sites that geo-block that region are under-represented. A cluster of Russian and Chinese domains timed out.
- Headers are one dimension of security. A site can score an A here and be insecure in ways this measures nothing about.
One thing worth mentioning because it nearly wrecked the results: 161 domains initially failed with certificate has expired, including Wikipedia and OpenAI. Their certificates were fine — my machine's certificate store carried an expired root, and OpenSSL was building chains that terminated in it. Had I not checked, I'd have published a study that silently dropped Wikipedia. If you ever do measurement work like this, verify your failures, not just your successes.
Full write-up and the complete dataset (CSV, CC BY 4.0)
The scanner is open source, so this is reproducible rather than something you have to take my word for. You can also run it against your own site — which, given the numbers above, is probably worth five minutes.
I'd genuinely like to know what your own site scores. Post it below, good or bad.
Top comments (0)