GET/api/v2/http-headers
HTTP security headers API
Fetch a URL like a browser, follow its redirects, and grade the final answer's security headers with Mozilla HTTP Observatory's tests.
- 20 calls a minute per IP (IPv6 per /56)
- Same engine as the HTTP Header Checker tool
{
"query": {
"url": "https://github.com/",
"ua": "chrome"
},
"finalUrl": "https://github.com/",
"finalStatus": 200,
"redirects": 0,
"httpVersion": "1.1",
"http2": true,
"http3": false,
"headersExact": true,
"headerCount": 20,
"headers": [
{
"name": "Date",
"value": "Sun, 25 Oct 2026 08:13:40 GMT"
},
{
"name": "Content-Type",
"value": "text/html; charset=utf-8"
},
{
"name": "Vary",
"value": "X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With, X-GitHub-Client-Version, Accept-Language, Sec-Fetch-Site,Accept-Encoding, Accept, X-Requested-With"
},
{
"name": "content-language",
"value": "en-US"
},
{
"name": "ETag",
"value": "W/\"73f87ca5b67703b238ecb2e0d277aac4\""
},
{
"name": "Cache-Control",
"value": "max-age=0, private, must-revalidate"
},
{
"name": "Strict-Transport-Security",
"value": "max-age=31536000; includeSubdomains; preload"
},
{
"name": "X-Frame-Options",
"value": "deny"
},
{
"name": "X-Content-Type-Options",
"value": "nosniff"
},
{
"name": "X-XSS-Protection",
"value": "0"
},
{
"name": "Referrer-Policy",
"value": "origin-when-cross-origin, strict-origin-when-cross-origin"
},
{
"name": "Content-Security-Policy",
"value": "default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com github.githubassets.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net productionresultssa1.blob.core.windows.net productionresultssa2.blob.core.windows.net productionresultssa3.blob.core.windows.net productionresultssa4.blob.core.windows.net productionresultssa5.blob.core.windows.net productionresultssa6.blob.core.windows.net productionresultssa7.blob.core.windows.net productionresultssa8.blob.core.windows.net productionresultssa9.blob.core.windows.net productionresultssa10.blob.core.windows.net productionresultssa11.blob.core.windows.net productionresultssa12.blob.core.windows.net productionresultssa13.blob.core.windows.net productionresultssa14.blob.core.windows.net productionresultssa15.blob.core.windows.net productionresultssa16.blob.core.windows.net productionresultssa17.blob.core.windows.net productionresultssa18.blob.core.windows.net productionresultssa19.blob.core.windows.net github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com wss://alive-staging.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com wss://production-copilot-host.webpubsub.azure.com wss://production-copilot-host-centralus.webpubsub.azure.com wss://production-copilot-host-centralus-02.webpubsub.azure.com wss://production-copilot-host-westus.webpubsub.azure.com api.github.com/cmc_internal/api/ edge.fullstory.com rs.fullstory.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com www.youtube-nocookie.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com user-images.githubusercontent.com private-user-images.githubusercontent.com opengraph.githubassets.com repository-images.githubusercontent.com marketplace-screenshots.githubusercontent.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com explore-feed.github.com *.googleusercontent.com objects-origin.githubusercontent.com *.githubusercontent.com images.ctfassets.net/8aevphvgewt8/; manifest-src 'self'; media-src github.com user-images.githubusercontent.com secured-user-images.githubusercontent.com private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com github.githubassets.com assets.ctfassets.net/8aevphvgewt8/ videos.ctfassets.net/8aevphvgewt8/; script-src github.githubassets.com 'sha256-6AKuI+cDd1MoUL1u4eqrA9PXmnPAkOB4h7421hPUUm0='; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/"
},
{
"name": "Server",
"value": "github.com"
},
{
"name": "Accept-Ranges",
"value": "bytes"
},
{
"name": "Set-Cookie",
"value": "_gh_sess=‹…›; path=/; HttpOnly; secure; SameSite=Lax"
},
{
"name": "Set-Cookie",
"value": "_octo=‹…›; expires=Mon, 25 Oct 2027 08:13:49 GMT; domain=.github.com; path=/; secure; SameSite=Lax"
},
{
"name": "Set-Cookie",
"value": "logged_in=‹…›; expires=Mon, 25 Oct 2027 08:13:49 GMT; domain=.github.com; path=/; HttpOnly; secure; SameSite=Lax"
},
{
"name": "X-GitHub-Request-Id",
"value": "2F4C:10C7C1:118181:1A2B78:6ADDBA3D"
},
{
"name": "x-github-edge-region",
"value": "centralindia"
},
{
"name": "Transfer-Encoding",
"value": "chunked"
}
],
"grade": {
"letter": "A+",
"score": 115,
"graded": true,
"notGradedReason": null,
"provisional": [],
"testsPassed": 11,
"testsFailed": 1,
"basis": "mdn-http-observatory 1.7.1 (algorithm 6)"
},
"tests": [
{
"id": "content-security-policy",
"name": "Content-Security-Policy",
"result": "csp-implemented-with-unsafe-inline-in-style-src-only",
"summary": "set; 'unsafe-inline' only in style-src",
"pass": true,
"modifier": 0,
"evidence": "default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com github.githubassets.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net productionresultssa1.blob.core.windows.net productionresultssa2.blob.core.windows.net productionresultssa3.blob.core.windows.net productionresultssa4.blob…",
"fix": "Remove `'unsafe-inline'` from style-src too, for the last 5 points."
},
{
"id": "cookies",
"name": "Cookies",
"result": "cookies-secure-with-httponly-sessions-and-samesite",
"summary": "all Secure, sessions HttpOnly, SameSite set",
"pass": true,
"modifier": 5,
"evidence": "_gh_sess; Secure; HttpOnly; SameSite=lax | _octo; Secure; SameSite=lax | logged_in; Secure; HttpOnly; SameSite=lax",
"fix": null
},
{
"id": "cross-origin-embedder-policy",
"name": "Cross-Origin-Embedder-Policy",
"result": "coep-not-implemented",
"summary": "not sent",
"pass": true,
"modifier": 0,
"evidence": null,
"fix": "Send `Cross-Origin-Embedder-Policy: require-corp` (or credentialless) once embedded content allows it."
},
{
"id": "cross-origin-opener-policy",
"name": "Cross-Origin-Opener-Policy",
"result": "coop-not-implemented",
"summary": "not sent",
"pass": true,
"modifier": 0,
"evidence": null,
"fix": "Send `Cross-Origin-Opener-Policy: same-origin`."
},
{
"id": "cross-origin-resource-sharing",
"name": "Cross-Origin Resource Sharing",
"result": "cross-origin-resource-sharing-not-implemented",
"summary": "no CORS headers",
"pass": true,
"modifier": 0,
"evidence": null,
"fix": null
},
{
"id": "redirection",
"name": "Redirection to HTTPS",
"result": "redirection-all-redirects-preloaded",
"summary": "every hop on the HSTS preload list",
"pass": true,
"modifier": 0,
"evidence": "http://github.com/ → https://github.com/",
"fix": null
},
{
"id": "referrer-policy",
"name": "Referrer-Policy",
"result": "referrer-policy-private",
"summary": "a private value",
"pass": true,
"modifier": 5,
"evidence": "origin-when-cross-origin, strict-origin-when-cross-origin",
"fix": null
},
{
"id": "strict-transport-security",
"name": "Strict-Transport-Security",
"result": "hsts-preloaded",
"summary": "on the preload list",
"pass": true,
"modifier": 5,
"evidence": "max-age=31536000; includeSubdomains; preload",
"fix": null
},
{
"id": "subresource-integrity",
"name": "Subresource Integrity",
"result": "sri-not-implemented-but-external-scripts-loaded-securely",
"summary": "external scripts over HTTPS, no integrity=",
"pass": false,
"modifier": -5,
"evidence": "https://github.githubassets.com/assets/high-contrast-cookie-141c17800ca6ba23.js | https://github.githubassets.com/assets/environment-9c4682c5715f3b80.js | https://github.githubassets.com/assets/github-elements-3b31060462951f7e.js | https://github.githubassets.com/assets/element-registry-8f2242d8ab39e777.js | https://github.githubassets.com/assets/behaviors-aae3017816009922.js | https://github.githubassets.com/assets/marketing-essentials-15557679ec4049c8.js | https://github.githubassets.com/assets/landing-pages-b8f11f093a587ea8.js | https://github.githubassets.com/assets/global-banner-disable-750ad87f36b8e45f.js",
"fix": "Add `integrity=\"sha384-…\" crossorigin=\"anonymous\"` to each external script: a page change, not a header."
},
{
"id": "x-content-type-options",
"name": "X-Content-Type-Options",
"result": "x-content-type-options-nosniff",
"summary": "nosniff",
"pass": true,
"modifier": 0,
"evidence": "nosniff",
"fix": null
},
{
"id": "x-frame-options",
"name": "X-Frame-Options",
"result": "x-frame-options-implemented-via-csp",
"summary": "via CSP frame-ancestors",
"pass": true,
"modifier": 5,
"evidence": "frame-ancestors 'none'",
"fix": null
},
{
"id": "cross-origin-resource-policy",
"name": "Cross-Origin-Resource-Policy",
"result": "corp-not-implemented",
"summary": "not sent",
"pass": true,
"modifier": 0,
"evidence": null,
"fix": "Send `Cross-Origin-Resource-Policy: same-origin` (same-site if your subdomains embed it)."
}
],
"hstsPreload": {
"status": "preloaded",
"preloadedBy": null
},
"software": [
{
"id": "github",
"name": "GitHub",
"version": null,
"header": "server"
}
],
"cookies": [
{
"name": "_gh_sess",
"host": "github.com",
"secure": true,
"httpOnly": true,
"sameSite": "lax",
"partitioned": false,
"path": "/",
"domain": null,
"maxAge": null,
"valueLength": 354,
"problems": []
},
{
"name": "_octo",
"host": "github.com",
"secure": true,
"httpOnly": false,
"sameSite": "lax",
"partitioned": false,
"path": "/",
"domain": "github.com",
"maxAge": 31535999,
"valueLength": 26,
"problems": []
},
{
"name": "logged_in",
"host": "github.com",
"secure": true,
"httpOnly": true,
"sameSite": "lax",
"partitioned": false,
"path": "/",
"domain": "github.com",
"maxAge": 31535999,
"valueLength": 2,
"problems": []
}
],
"issues": [
{
"severity": "warning",
"code": "sri_not_implemented_but_external_scripts_loaded_securely",
"message": "Subresource Integrity: external scripts over HTTPS, no integrity= (-5). Add `integrity=\"sha384-…\" crossorigin=\"anonymous\"` to each external script: a page change, not a header."
},
{
"severity": "info",
"code": "permissions_policy_missing",
"message": "No Permissions-Policy. Not scored; only Chromium browsers read it, where it can switch off the camera, microphone and location for embedded content."
}
],
"tookMs": 963
}How it works
Requests the URL from our server over our own connection (so the headers are exactly as sent: order, case and duplicates), follows up to 20 redirects, and returns the final answer's status and every header line. Cookie values are never read or stored: only their names and attributes.
The grade reproduces Mozilla HTTP Observatory (its v1.7.1 code, algorithm 6): the same 12 tests (CSP, cookies, CORS, COOP/COEP/CORP, redirection, Referrer-Policy, HSTS, SRI, X-Content-Type-Options, X-Frame-Options), the same points and the same letter, read from the same two sessions (the URL's http:// and https:// forms) and the HSTS preload list. Each test comes with its evidence and a fix; deprecated or revealing headers (X-XSS-Protection, Server versions, X-Powered-By) are notes in issues.
Honest limits: sites on Cloudflare's network are read through Cloudflare (header names arrive lower-case: headersExact: false). When the HTTPS answer couldn't be read on our side, the affected tests say unknown and the grade is provisional, never failed. A bot wall is reported as such, not as a broken site.
Answers kept: The same run serves both endpoints and the HTTP Header Checker and Redirect Checker pages: a finished check is kept 2 minutes (30 seconds when a part ran out of time) per URL and user agent. A run that ended on a bot wall or whose first URL got no answer isn't kept.
Query parameters
urlstringrequiredA web address: a full URL (https://github.com/about) or a bare name (github.com, checked as https://). Private and reserved addresses are refused.uastringoptionaldefaultchromeThe user agent to send:chrome(Chrome on Windows, the default),iphone(Safari on iOS),googlebot,bingbotordnsrobot(ours). Sites answer bots and phones differently.one of
chrome,iphone,googlebot,bingbot,dnsrobot
Response fields
200 with this JSON object, plus tookMs, and incomplete with warnings when a source failed. Fields marked optional appear only when they apply.
queryobjectalwaysWhat was looked up, normalised (lower case, no trailing dot, IDNs as Punycode).urlstringalwaysThe URL checked: scheme added when missing (https), host lower case and Punycode, default port and #fragment dropped.uastringalwaysThe user agent the check sent.one of
"chrome","iphone","googlebot","bingbot","dnsrobot"
finalUrlstring or nullalwaysThe URL whose answer is shown, after following redirects; null when nothing answered.finalStatusinteger or nullalwaysIts HTTP status.redirectsintegeralwaysRedirects followed to get there.httpVersionstring or nullalwaysFrom the status line (1.1); null through Cloudflare's network.http2boolean or nullalwaysThe server offers HTTP/2 (ALPN h2); null when not known.http3boolean or nullalwaysHTTP/3 is advertised (Alt-Svc).headersExactboolean or nullalwaystrue: the headers are exactly as sent (order, case, duplicates);false: read through Cloudflare's network, names lower-cased and repeats joined.headerCountintegeralwaysHeader lines in the final answer.headersarray of objectsalwaysThe final answer's header lines, at most 100, values cut at 4,096 characters. Cookie values are replaced by‹…›(never read, never stored).namestringalwaysIts name.valuestringalwaysIts value.
gradeobject or nullalwaysThe security grade, computed with Mozilla HTTP Observatory's tests and scoring (its v1.7.1 code). Null when the tests didn't run (nothing answered, or the check ran out of time).Show 8 fields
letterstring or nullalwaysA+ to F; null when the answer isn't graded.one of
"A+","A","A-","B+","B","B-","C+","C","C-","D+","D","D-","F",nullscoreinteger or nullalwaysObservatory's score (starts at 100; bonuses can take it past 100).gradedbooleanalwaysObservatory grades this answer (only 2xx, 3xx, 401 and 403 are).notGradedReasonstring or nullalwaysWhy not:status(not a graded status),unreachable, orunknown(the HTTPS answer couldn't be read this time, on our side).one of
"status","unreachable","unknown",nullprovisionalarray of stringsalwaysWhy the grade may still change:preload(hstspreload.org didn't answer),page(the page wasn't read whole),session(a test's answer couldn't be read).testsPassedintegeralwaysTests passed.testsFailedintegeralwaysTests failed.basisstringalwaysThe method and version matched.
testsarray of objectsalwaysEach Observatory test with its result.Show 8 fields
idstringalwaysThe test.one of
"content-security-policy","cookies","cross-origin-embedder-policy","cross-origin-opener-policy","cross-origin-resource-sharing","redirection","referrer-policy","strict-transport-security","subresource-integrity","x-content-type-options","x-frame-options","cross-origin-resource-policy"namestringalwaysIts name.resultstringalwaysObservatory's own result id, e.g.hsts-implemented-max-age-at-least-six-months;unknownwhen the answer it reads couldn't be had on our side (scored 0).summarystringalwaysThe result in words.passbooleanalwaysObservatory's pass/fail.modifierintegeralwaysPoints added to or taken from the score.evidencestring or nullalwaysThe header value (or cookie names, script URLs) the result rests on, up to 1 KB.fixstring or nullalwaysHow to fix it, in a sentence; null when nothing to fix.
hstsPreloadobject or nullalwaysThe host's status on Chrome's HSTS preload list (hstspreload.org).statusstringalwaysStatus.one of
"preloaded","pending","eligible","no","unknown"preloadedBystring or nullalwaysThe parent whose entry covers this host.
softwarearray of objectsalwaysServer and CDN software the headers name.Show 4 fields
idstringalwaysStable id, e.g.nginx,cloudflare,github.namestringalwaysDisplay name.versionstring or nullalwaysThe version the header gives away.headerstringalwaysThe header that named it.
cookiesarray of objectsalwaysCookies set along the chain (values never read), at most 30.Show 11 fields
namestringalwaysIts name.hoststringalwaysThe host that set it.securebooleanalwaysSecure.httpOnlybooleanalwaysHttpOnly.sameSitestringalwaysSameSite as sent.one of
"absent","lax","strict","none","invalid"partitionedbooleanalwaysPartitioned (CHIPS).pathstring or nullalwaysPath.domainstring or nullalwaysDomain.maxAgeinteger or nullalwaysLifetime in seconds (Max-Age, else Expires; capped at 400 days as browsers do); null for a session cookie.valueLengthintegeralwaysLength of its value in bytes.problemsarray of stringsalwaysProblems browsers act on:prefix-secure,prefix-host,samesite-none-insecure,partitioned-insecure,domain-mismatch,bad-name,long-attribute,lifetime-capped.
issuesarray of objectsalwaysProblems found in the target's configuration, worst first. Empty when there are none.severitystringalwayserrorbreaks something,warningrisks it,infois worth knowing.one of
"error","warning","info"codestringalwaysStable machine-readable code.messagestringalwaysThe problem and what to do about it, in plain English.
Errors
422target_not_allowedThe URL points at a private or reserved address, port 25, or our own API.429rate_limitedOver your 20 a minute, or the target site's 40 a minute from everyone (the message says which).503unavailableThe checker's rate limiter isn't reachable: it fails closed rather than run a check uncounted.
Plus the errors every endpoint can return: 400 for a missing or unreadable parameter, 429 past the limit, 503 when every source failed.
Code samples
curl -G "https://dnsrobot.net/api/v2/http-headers" \
--data-urlencode "url=https://github.com"const params = new URLSearchParams({ url: "https://github.com" });
const res = await fetch(`https://dnsrobot.net/api/v2/http-headers?${params}`);
const data = await res.json();
if (!res.ok) throw new Error(data.error.message);
console.log(data.grade);import requests
r = requests.get(
"https://dnsrobot.net/api/v2/http-headers",
params={"url": "https://github.com"},
timeout=30,
)
data = r.json()
if not r.ok:
raise RuntimeError(data["error"]["message"])
print(data["grade"])package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
)
func main() {
q := url.Values{"url": {"https://github.com"}}
res, err := http.Get("https://dnsrobot.net/api/v2/http-headers?" + q.Encode())
if err != nil {
panic(err)
}
defer res.Body.Close()
var data map[string]any
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
panic(err)
}
if res.StatusCode != http.StatusOK {
panic(data["error"])
}
fmt.Println(data["grade"])
}<?php
$query = http_build_query(["url" => "https://github.com"]);
$context = stream_context_create(["http" => ["ignore_errors" => true, "timeout" => 30]]);
$data = json_decode(file_get_contents("https://dnsrobot.net/api/v2/http-headers?" . $query, false, $context), true);
if (isset($data["error"])) {
throw new RuntimeException($data["error"]["message"]);
}
print_r($data["grade"]);require "net/http"
require "json"
uri = URI("https://dnsrobot.net/api/v2/http-headers")
uri.query = URI.encode_www_form(url: "https://github.com")
data = JSON.parse(Net::HTTP.get(uri))
raise data["error"]["message"] if data["error"]
puts data["grade"]// Cargo.toml: reqwest = { version = "0.13", features = ["blocking", "json"] }, serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
let res = reqwest::blocking::get("https://dnsrobot.net/api/v2/http-headers?url=https%3A%2F%2Fgithub.com")?;
let ok = res.status().is_success();
let data: serde_json::Value = res.json()?;
if !ok {
return Err(data["error"]["message"].to_string().into());
}
println!("{}", data["grade"]);
Ok(())
}using System.Text.Json;
using var http = new HttpClient();
var res = await http.GetAsync("https://dnsrobot.net/api/v2/http-headers?url=https%3A%2F%2Fgithub.com");
var data = JsonDocument.Parse(await res.Content.ReadAsStringAsync()).RootElement;
if (!res.IsSuccessStatusCode)
throw new Exception(data.GetProperty("error").GetProperty("message").GetString());
Console.WriteLine(data.GetProperty("grade"));github.com: A+ with a strict CSP
GET /api/v2/http-headers?url=https%3A%2F%2Fgithub.com{
"query": {
"url": "https://github.com/",
"ua": "chrome"
},
"finalUrl": "https://github.com/",
"finalStatus": 200,
"redirects": 0,
"httpVersion": "1.1",
"http2": true,
"http3": false,
"headersExact": true,
"headerCount": 20,
"headers": [
{
"name": "Date",
"value": "Sun, 25 Oct 2026 08:13:40 GMT"
},
{
"name": "Content-Type",
"value": "text/html; charset=utf-8"
},
{
"name": "Vary",
"value": "X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With, X-GitHub-Client-Version, A…"
},
// … 17 more items
],
"grade": {
"letter": "A+",
"score": 115,
"graded": true,
"notGradedReason": null,
"provisional": [],
"testsPassed": 11,
"testsFailed": 1,
"basis": "mdn-http-observatory 1.7.1 (algorithm 6)"
},
"tests": [
{
"id": "content-security-policy",
"name": "Content-Security-Policy",
"result": "csp-implemented-with-unsafe-inline-in-style-src-only",
"summary": "set; 'unsafe-inline' only in style-src",
"pass": true,
"modifier": 0,
"evidence": "default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/wor…",
"fix": "Remove `'unsafe-inline'` from style-src too, for the last 5 points."
},
{
"id": "cookies",
"name": "Cookies",
"result": "cookies-secure-with-httponly-sessions-and-samesite",
"summary": "all Secure, sessions HttpOnly, SameSite set",
"pass": true,
"modifier": 5,
"evidence": "_gh_sess; Secure; HttpOnly; SameSite=lax | _octo; Secure; SameSite=lax | logged_in; Secure; Http…",
"fix": null
},
{
"id": "cross-origin-embedder-policy",
"name": "Cross-Origin-Embedder-Policy",
"result": "coep-not-implemented",
"summary": "not sent",
"pass": true,
"modifier": 0,
"evidence": null,
"fix": "Send `Cross-Origin-Embedder-Policy: require-corp` (or credentialless) once embedded content allo…"
},
// … 9 more items
],
"hstsPreload": {
"status": "preloaded",
"preloadedBy": null
},
"software": [
{
"id": "github",
"name": "GitHub",
"version": null,
"header": "server"
}
],
"cookies": [
{
"name": "_gh_sess",
"host": "github.com",
"secure": true,
"httpOnly": true,
"sameSite": "lax",
"partitioned": false,
"path": "/",
"domain": null,
"maxAge": null,
"valueLength": 354,
"problems": []
},
{
"name": "_octo",
"host": "github.com",
"secure": true,
"httpOnly": false,
"sameSite": "lax",
"partitioned": false,
"path": "/",
"domain": "github.com",
"maxAge": 31535999,
"valueLength": 26,
"problems": []
},
{
"name": "logged_in",
"host": "github.com",
"secure": true,
"httpOnly": true,
"sameSite": "lax",
"partitioned": false,
"path": "/",
"domain": "github.com",
"maxAge": 31535999,
"valueLength": 2,
"problems": []
}
],
"issues": [
{
"severity": "warning",
"code": "sri_not_implemented_but_external_scripts_loaded_securely",
"message": "Subresource Integrity: external scripts over HTTPS, no integrity= (-5). Add `integrity=\"sha384-……"
},
{
"severity": "info",
"code": "permissions_policy_missing",
"message": "No Permissions-Policy. Not scored; only Chromium browsers read it, where it can switch off the c…"
}
],
"tookMs": 963
}Shortened for the page: long lists show their first items.
wikipedia.org
GET /api/v2/http-headers?url=https%3A%2F%2Fwww.wikipedia.org{
"query": {
"url": "https://www.wikipedia.org/",
"ua": "chrome"
},
"finalUrl": "https://www.wikipedia.org/",
"finalStatus": 200,
"redirects": 0,
"httpVersion": "1.1",
"http2": true,
"http3": false,
"headersExact": true,
"headerCount": 23,
"headers": [
{
"name": "date",
"value": "Sun, 25 Oct 2026 05:07:59 GMT"
},
{
"name": "cache-control",
"value": "s-maxage=86400, must-revalidate, max-age=3600"
},
{
"name": "server",
"value": "ATS/9.2.15"
},
// … 20 more items
],
"grade": {
"letter": "C",
"score": 50,
"graded": true,
"notGradedReason": null,
"provisional": [],
"testsPassed": 9,
"testsFailed": 3,
"basis": "mdn-http-observatory 1.7.1 (algorithm 6)"
},
"tests": [
{
"id": "content-security-policy",
"name": "Content-Security-Policy",
"result": "csp-not-implemented",
"summary": "not sent",
"pass": false,
"modifier": -25,
"evidence": null,
"fix": "Send a Content-Security-Policy. Start it as Report-Only, read the reports, then enforce it."
},
{
"id": "cookies",
"name": "Cookies",
"result": "cookies-secure-with-httponly-sessions",
"summary": "all Secure, sessions HttpOnly",
"pass": true,
"modifier": 0,
"evidence": "WMF-Last-Access; Secure; HttpOnly | WMF-Last-Access-Global; Secure; HttpOnly | GeoIP; Secure | N…",
"fix": "Add `SameSite=Lax` (or Strict) to every cookie."
},
{
"id": "cross-origin-embedder-policy",
"name": "Cross-Origin-Embedder-Policy",
"result": "coep-not-implemented",
"summary": "not sent",
"pass": true,
"modifier": 0,
"evidence": null,
"fix": "Send `Cross-Origin-Embedder-Policy: require-corp` (or credentialless) once embedded content allo…"
},
// … 9 more items
],
"hstsPreload": {
"status": "preloaded",
"preloadedBy": "wikipedia.org"
},
"software": [
{
"id": "ats",
"name": "Apache Traffic Server",
"version": "9.2.15",
"header": "server"
}
],
"cookies": [
{
"name": "WMF-Last-Access",
"host": "www.wikipedia.org",
"secure": true,
"httpOnly": true,
"sameSite": "absent",
"partitioned": false,
"path": "/",
"domain": null,
"maxAge": 2735169,
"valueLength": 11,
"problems": []
},
{
"name": "WMF-Last-Access-Global",
"host": "www.wikipedia.org",
"secure": true,
"httpOnly": true,
"sameSite": "absent",
"partitioned": false,
"path": "/",
"domain": "wikipedia.org",
"maxAge": 2735169,
"valueLength": 11,
"problems": []
},
{
"name": "GeoIP",
"host": "www.wikipedia.org",
"secure": true,
"httpOnly": false,
"sameSite": "absent",
"partitioned": false,
"path": "/",
"domain": "wikipedia.org",
"maxAge": null,
"valueLength": 30,
"problems": []
},
// … 2 more items
],
"issues": [
{
"severity": "error",
"code": "csp_not_implemented",
"message": "Content-Security-Policy: not sent (-25). Send a Content-Security-Policy. Start it as Report-Only…"
},
{
"severity": "error",
"code": "x_frame_options_not_implemented",
"message": "X-Frame-Options: not sent (-20). Send `X-Frame-Options: DENY`, or CSP `frame-ancestors 'self'`."
},
{
"severity": "warning",
"code": "x_content_type_options_not_implemented",
"message": "X-Content-Type-Options: not sent (-5). Send `X-Content-Type-Options: nosniff`."
},
// … 2 more items
],
"tookMs": 1059
}Shortened for the page: long lists show their first items.