Security headers
HSTS passes. Missing CSP fails; missing framing protection, Referrer-Policy, nosniff, Permissions-Policy, and COOP are warnings. Missing COEP is informational.
Free, no signup. See the headers browsers and crawlers receive: every redirect hop, separate security and SEO grades, edge fingerprints, compression, and an honest HTTP/3 signal.
This makes two user-triggered requests for one URL from Cloudflare infrastructure. It compares user-agent responses, not verified crawler behavior or crawler IP access.
The report compares the final response headers from two independent checks.
Checks run from our server; we fetch the URL you enter and don't keep the results. Complete response header maps are returned to your browser. Repeating the same URL and user-agent within about ten minutes may reuse a short-lived edge cache. Anonymous run-level outcome counters may be used for aggregate research; URLs, domains, IPs, and identifiers are never included, and no statistic is released below 100 runs.
Frequency is calculated in this browser from the live final responses in this run. It is not a global popularity dataset.
| Header | Responses | Frequency | Registry status |
|---|
Illustrative example — exact grading for the fixed header map below
HTTP/2 200
strict-transport-security: max-age=31536000
cache-control: public, max-age=3600
etag: "abc123"HSTS passes. Missing CSP fails; missing framing protection, Referrer-Policy, nosniff, Permissions-Policy, and COOP are warnings. Missing COEP is informational.
Cache-Control and ETag pass. Missing X-Robots-Tag, Link canonical, and Vary are informational in this HTTP-only grade.
The displayed HTTP/2 line is illustrative input only: the live Worker cannot expose the negotiated HTTP version.
Current target
Recent checks appear below. Use the star beside any saved site, page, or list to favorite it.
Target filled from your local choices.
Saved targets, named lists, and recent check summaries remain only in this browser.
A bounded server-side checker sends the selected user-agent, records each redirect response without hiding intermediate headers, and returns normalized header maps and timings. Browser-side functions grade the final response, parse Link headers, inspect compression and protocol advertisements, identify a small set of edge fingerprints, produce a curl-style view, and diff an optional second final response. The small batch mode counts fields only across the final responses fetched in that run and labels names from a local status-preserving snapshot of the IANA HTTP Field Name Registry.
The report cannot expose negotiated HTTP version, TLS certificate details, private origin infrastructure, or headers added only inside a user's network. The Fetch Headers API may combine repeated field lines: parsed combined values are assessed, but the original field-line order and boundaries cannot be reconstructed. User-agent strings originate from a Cloudflare datacenter, not verified crawler IP ranges. It does not inspect HTML metadata, application security, or whether a 200 body is correct.
Not exactly. The Worker Fetch Headers API exposes a normalized, potentially combined value. The checker parses and assesses that combined value, but it cannot reconstruct the original order or boundaries of repeated field lines.
Workers do not expose the negotiated HTTP version. The tool only reports when Alt-Svc advertises HTTP/3; that is not proof this request used HTTP/3.
Sites can vary headers by user-agent. This sends the selected user-agent string from a Cloudflare datacenter, not from a verified crawler IP rangeA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index..
No. The URL is fetched to build this report and a short-lived edge cache may reuse the same URL and user-agent response for about ten minutes.
No. The grade covers a defined set of public response headers. It does not test application vulnerabilities, authentication, server configuration, dependency risk, or whether a policy works correctly for the application.
No. It evaluates HTTP-level signals such as X-Robots-TagThe X-Robots-Tag is an HTTP response header that carries the same indexing and serving directives as the robots meta tag (noindex, nofollow, nosnippet, and the rest). Because it lives in the header rather than the HTML, it's how you control indexing for non-HTML files like PDFs, images, and videos. and Link headers. Page-level canonical and robots elements require an HTML-aware checker.
Upvote what you want most. New ideas can be submitted from the floating Feedback menu; requests appear here once approved, and the most-wanted rise to the top.
You won't be emailed about that request anymore.
Loading…
New requests are reviewed before they appear here.
HTTP Header Checker · one finding
Recommended action: Remove noindex from the X-Robots-Tag on URLs intended for search, then verify the final response and request recrawling.
Fix principle: Remove every unintended noindex from its confirmed owner; absence of noindex is sufficient, while an explicit index directive cannot override another noindex because restrictive directives combine.
Confirm first: The final HTML or HTTP response contains a noindex directive, including one added only by client-side script during rendering. The page is intended to be an indexable canonical URL. A robots meta tag or X-Robots-Tag intended to keep the page indexable is neutralized by a conflicting directive elsewhere, because directives combine using the most restrictive rule. Robots.txt disallows the URL itself, or disallows a resource the page depends on to render, so the crawler cannot reach or fully evaluate the intended indexable page.
Do not apply when: Exclusion is intentional for the page type, environment, or workflow state. The directive appears only on a noncanonical or otherwise ineligible URL. Robots.txt does not disallow the URL or the resources it needs to render, and the effective combination of every directive already resolves to the intended indexable state.
Likely control points: cms-app · server · edge-cdn
Choose the layer that owns the final response.
Escalate when page ownership or publication intent is unclear, noindex or a robots.txt Disallow rule is applied by multiple layers, or removing it would expose private, duplicate, or staging content.
HTTP Header Checker · one finding
Recommended action: Emit exactly one HTTP Link header with rel="canonical" for the preferred URL and remove conflicting canonical targets at the edge or origin.
Fix principle: Align every canonical signal for a page — the HTML <link rel=canonical>, an HTTP Link header, the post-render DOM, and each page's self-reference inside an hreflang cluster — on one confirmed intended URL; a conflict anywhere in that chain is resolved at its owning layer, never papered over by adding another canonical downstream.
Confirm first: The page emits zero, more than one, or mutually disagreeing canonical signals across its HTML head, HTTP response header, or post-render DOM. A present canonical signal is relative, points to a URL that does not return a live 200 response, sits outside <head> where crawlers may not honor it, or only appears after client-side JavaScript runs.
Do not apply when: Exactly one absolute canonical URL is declared consistently across the HTML head, any HTTP header, and the rendered DOM, and that target itself returns 200. The apparent second reference is a distinct, valid annotation — an hreflang alternate, a pagination rel=next/prev, or another non-canonical link — not a competing canonical claim for the same page.
Likely control points: cms-app · server · edge-cdn
Choose the layer that owns the final response.
Implementation is controlled by the platform or vendor.
Escalate when ownership of the emitting layer is unclear, more than one system claims to own the canonical output, or Google's selected canonical keeps diverging from the declared canonical after every signal you control has been made consistent.
HTTP Header Checker · one finding
Recommended action: Serve Strict-Transport-Security on HTTPS responses, starting with a tested max-age and expanding to includeSubDomains only when every subdomain is HTTPS-ready.
Fix principle: Start with exactly one HTTPS-only Strict-Transport-Security header using max-age=300, then stage 300 → 604800 → 2592000 → an intentional long value; do not default to includeSubDomains or preload.
Confirm first: The final HTTPS response does not include Strict-Transport-Security. The hostname is intended to remain HTTPS-only and every hostname in the proposed scope works over HTTPS. HSTS is present but its max-age has stalled short of the value the rollout should have reached by now, leaving less durable protection than intended at this stage.
Do not apply when: A final edge or platform response already supplies HSTS, because adding another layer would duplicate ownership. Any hostname in the proposed scope still requires HTTP or has unresolved certificate, redirect, or mixed-content failures. The current max-age matches a deliberate, still-in-progress staging step (300 → 604800 → 2592000 → an intentional long value) rather than being stalled short of the intended target — a rollout genuinely in progress is not itself a defect.
Likely control points: server · edge-cdn · managed-vendor
Choose the layer that owns the final response.
Strict-Transport-Security: max-age=300 add_header Strict-Transport-Security "max-age=300" always; Header always set Strict-Transport-Security "max-age=300" async headers() {
return [{
source: '/:path*',
headers: [{ key: 'Strict-Transport-Security', value: 'max-age=300' }],
}];
} Escalate before includeSubDomains, preload, or a long max-age when hostname ownership is distributed, legacy HTTP dependencies remain, the final header owner is uncertain, or the platform cannot provide a safe rollback path.
HTTP Header Checker · one finding
Recommended action: Raise Strict-Transport-Security max-age to at least 31,536,000 seconds after confirming HTTPS works across the covered hosts.
Fix principle: Start with exactly one HTTPS-only Strict-Transport-Security header using max-age=300, then stage 300 → 604800 → 2592000 → an intentional long value; do not default to includeSubDomains or preload.
Confirm first: The final HTTPS response does not include Strict-Transport-Security. The hostname is intended to remain HTTPS-only and every hostname in the proposed scope works over HTTPS. HSTS is present but its max-age has stalled short of the value the rollout should have reached by now, leaving less durable protection than intended at this stage.
Do not apply when: A final edge or platform response already supplies HSTS, because adding another layer would duplicate ownership. Any hostname in the proposed scope still requires HTTP or has unresolved certificate, redirect, or mixed-content failures. The current max-age matches a deliberate, still-in-progress staging step (300 → 604800 → 2592000 → an intentional long value) rather than being stalled short of the intended target — a rollout genuinely in progress is not itself a defect.
Likely control points: server · edge-cdn · managed-vendor
Choose the layer that owns the final response.
Strict-Transport-Security: max-age=300 add_header Strict-Transport-Security "max-age=300" always; Header always set Strict-Transport-Security "max-age=300" async headers() {
return [{
source: '/:path*',
headers: [{ key: 'Strict-Transport-Security', value: 'max-age=300' }],
}];
} Escalate before includeSubDomains, preload, or a long max-age when hostname ownership is distributed, legacy HTTP dependencies remain, the final header owner is uncertain, or the platform cannot provide a safe rollback path.
HTTP Header Checker · one finding
Recommended action: Add a Content-Security-Policy that allowlists the scripts, styles, images, frames, and connections the page actually needs, then tighten it from report-only to enforcement.
Fix principle: Diagnose which single layer owns the final HTTP response, then add each missing or unsafe protective header there — Content-Security-Policy staged through report-only before enforcement, framing protection, a safe Referrer-Policy, and correct Vary/Cache-Control behavior for crawler requests — without layering a second, conflicting policy on top of one already emitted upstream. These headers are a security and crawl-integrity fix; they are not an SEO ranking mechanism, and nothing here should be represented as one.
Confirm first: The final HTTP response is missing Content-Security-Policy, missing framing protection (frame-ancestors or X-Frame-Options), or sends an unsafe Referrer-Policy (unsafe-url or origin-when-cross-origin) that leaks a full URL cross-origin. The response varies materially by User-Agent without a matching Vary declaration, or sends a no-store/private Cache-Control specifically to Googlebot on content that is genuinely public and not personalized.
Do not apply when: The header is already present at a layer upstream of the one being inspected (a CDN, WAF, or platform default), so adding it again would create a second, possibly conflicting, policy owner rather than fix a gap. The missing header is Strict-Transport-Security — HSTS has its own staged rollout and rollback procedure in the HSTS recipe; do not restart or duplicate that rollout here. The response is intentionally personalized or access-controlled, so a stricter caching or Vary declaration for that specific response is correct, not a defect.
Likely control points: server · edge-cdn · cms-app · managed-vendor
Choose the layer that owns the final response.
Implementation is controlled by the platform or vendor.
Implementation is controlled by the platform or vendor.
Escalate when ownership of the response-header layer is unclear, more than one layer claims to set the same header, enforcing Content-Security-Policy would block functionality that cannot be resolved during the report-only period, or removing restrictive caching for Googlebot would expose genuinely personalized or access-controlled content.
HTTP Header Checker · one finding
Recommended action: Set Content-Security-Policy frame-ancestors to the origins allowed to embed the page, or use X-Frame-Options: DENY when embedding is never allowed.
Fix principle: Diagnose which single layer owns the final HTTP response, then add each missing or unsafe protective header there — Content-Security-Policy staged through report-only before enforcement, framing protection, a safe Referrer-Policy, and correct Vary/Cache-Control behavior for crawler requests — without layering a second, conflicting policy on top of one already emitted upstream. These headers are a security and crawl-integrity fix; they are not an SEO ranking mechanism, and nothing here should be represented as one.
Confirm first: The final HTTP response is missing Content-Security-Policy, missing framing protection (frame-ancestors or X-Frame-Options), or sends an unsafe Referrer-Policy (unsafe-url or origin-when-cross-origin) that leaks a full URL cross-origin. The response varies materially by User-Agent without a matching Vary declaration, or sends a no-store/private Cache-Control specifically to Googlebot on content that is genuinely public and not personalized.
Do not apply when: The header is already present at a layer upstream of the one being inspected (a CDN, WAF, or platform default), so adding it again would create a second, possibly conflicting, policy owner rather than fix a gap. The missing header is Strict-Transport-Security — HSTS has its own staged rollout and rollback procedure in the HSTS recipe; do not restart or duplicate that rollout here. The response is intentionally personalized or access-controlled, so a stricter caching or Vary declaration for that specific response is correct, not a defect.
Likely control points: server · edge-cdn · cms-app · managed-vendor
Choose the layer that owns the final response.
Implementation is controlled by the platform or vendor.
Implementation is controlled by the platform or vendor.
Escalate when ownership of the response-header layer is unclear, more than one layer claims to set the same header, enforcing Content-Security-Policy would block functionality that cannot be resolved during the report-only period, or removing restrictive caching for Googlebot would expose genuinely personalized or access-controlled content.
HTTP Header Checker · one finding
Recommended action: Replace unsafe-url or origin-when-cross-origin with strict-origin-when-cross-origin so cross-origin requests do not expose full paths and query strings.
Fix principle: Diagnose which single layer owns the final HTTP response, then add each missing or unsafe protective header there — Content-Security-Policy staged through report-only before enforcement, framing protection, a safe Referrer-Policy, and correct Vary/Cache-Control behavior for crawler requests — without layering a second, conflicting policy on top of one already emitted upstream. These headers are a security and crawl-integrity fix; they are not an SEO ranking mechanism, and nothing here should be represented as one.
Confirm first: The final HTTP response is missing Content-Security-Policy, missing framing protection (frame-ancestors or X-Frame-Options), or sends an unsafe Referrer-Policy (unsafe-url or origin-when-cross-origin) that leaks a full URL cross-origin. The response varies materially by User-Agent without a matching Vary declaration, or sends a no-store/private Cache-Control specifically to Googlebot on content that is genuinely public and not personalized.
Do not apply when: The header is already present at a layer upstream of the one being inspected (a CDN, WAF, or platform default), so adding it again would create a second, possibly conflicting, policy owner rather than fix a gap. The missing header is Strict-Transport-Security — HSTS has its own staged rollout and rollback procedure in the HSTS recipe; do not restart or duplicate that rollout here. The response is intentionally personalized or access-controlled, so a stricter caching or Vary declaration for that specific response is correct, not a defect.
Likely control points: server · edge-cdn · cms-app · managed-vendor
Choose the layer that owns the final response.
Implementation is controlled by the platform or vendor.
Implementation is controlled by the platform or vendor.
Escalate when ownership of the response-header layer is unclear, more than one layer claims to set the same header, enforcing Content-Security-Policy would block functionality that cannot be resolved during the report-only period, or removing restrictive caching for Googlebot would expose genuinely personalized or access-controlled content.
HTTP Header Checker · one finding
Recommended action: Stop varying the full response on User-Agent where possible; use feature detection or a narrowly normalized device signal and confirm crawlers receive equivalent primary content.
Fix principle: Diagnose which single layer owns the final HTTP response, then add each missing or unsafe protective header there — Content-Security-Policy staged through report-only before enforcement, framing protection, a safe Referrer-Policy, and correct Vary/Cache-Control behavior for crawler requests — without layering a second, conflicting policy on top of one already emitted upstream. These headers are a security and crawl-integrity fix; they are not an SEO ranking mechanism, and nothing here should be represented as one.
Confirm first: The final HTTP response is missing Content-Security-Policy, missing framing protection (frame-ancestors or X-Frame-Options), or sends an unsafe Referrer-Policy (unsafe-url or origin-when-cross-origin) that leaks a full URL cross-origin. The response varies materially by User-Agent without a matching Vary declaration, or sends a no-store/private Cache-Control specifically to Googlebot on content that is genuinely public and not personalized.
Do not apply when: The header is already present at a layer upstream of the one being inspected (a CDN, WAF, or platform default), so adding it again would create a second, possibly conflicting, policy owner rather than fix a gap. The missing header is Strict-Transport-Security — HSTS has its own staged rollout and rollback procedure in the HSTS recipe; do not restart or duplicate that rollout here. The response is intentionally personalized or access-controlled, so a stricter caching or Vary declaration for that specific response is correct, not a defect.
Likely control points: server · edge-cdn · cms-app · managed-vendor
Choose the layer that owns the final response.
Implementation is controlled by the platform or vendor.
Implementation is controlled by the platform or vendor.
Escalate when ownership of the response-header layer is unclear, more than one layer claims to set the same header, enforcing Content-Security-Policy would block functionality that cannot be resolved during the report-only period, or removing restrictive caching for Googlebot would expose genuinely personalized or access-controlled content.
HTTP Header Checker · one finding
Recommended action: Remove no-store/private caching sent specifically to Googlebot unless the content is genuinely personalized, and return the same cacheable public representation users receive.
Fix principle: Diagnose which single layer owns the final HTTP response, then add each missing or unsafe protective header there — Content-Security-Policy staged through report-only before enforcement, framing protection, a safe Referrer-Policy, and correct Vary/Cache-Control behavior for crawler requests — without layering a second, conflicting policy on top of one already emitted upstream. These headers are a security and crawl-integrity fix; they are not an SEO ranking mechanism, and nothing here should be represented as one.
Confirm first: The final HTTP response is missing Content-Security-Policy, missing framing protection (frame-ancestors or X-Frame-Options), or sends an unsafe Referrer-Policy (unsafe-url or origin-when-cross-origin) that leaks a full URL cross-origin. The response varies materially by User-Agent without a matching Vary declaration, or sends a no-store/private Cache-Control specifically to Googlebot on content that is genuinely public and not personalized.
Do not apply when: The header is already present at a layer upstream of the one being inspected (a CDN, WAF, or platform default), so adding it again would create a second, possibly conflicting, policy owner rather than fix a gap. The missing header is Strict-Transport-Security — HSTS has its own staged rollout and rollback procedure in the HSTS recipe; do not restart or duplicate that rollout here. The response is intentionally personalized or access-controlled, so a stricter caching or Vary declaration for that specific response is correct, not a defect.
Likely control points: server · edge-cdn · cms-app · managed-vendor
Choose the layer that owns the final response.
Implementation is controlled by the platform or vendor.
Implementation is controlled by the platform or vendor.
Escalate when ownership of the response-header layer is unclear, more than one layer claims to set the same header, enforcing Content-Security-Policy would block functionality that cannot be resolved during the report-only period, or removing restrictive caching for Googlebot would expose genuinely personalized or access-controlled content.