HTTP Headers & Redirect Checker
Pricing
$0.90 / 1,000 results
HTTP Headers & Redirect Checker
Check HTTP headers and redirect chains: security score with values to set, CSP, HSTS, CORS and cache checks. Use when you need to audit headers or redirects.
Pricing
$0.90 / 1,000 results
Rating
0.0
(0)
Developer
Plain Pipe
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Security
Limited permissionsShare
Check URLs for their full redirect chain, final status code and response headers. Every URL gets a 0-100 security-header score with an A+ to F grade, the exact value to set for each weak or missing header, and CSP, HSTS, CORS, caching, compression and HTTP/2 / HTTP/3 checks.
Use this when: you need to verify redirects, final status codes, or security, CORS and cache headers for a list of URLs, and want to know what to change.
What it does
Give it a list of URLs (or an Apify dataset of URLs). For each one it follows redirects hop by hop and returns one row with:
- Redirect chain: every hop with status code,
Location, response time and server; redirect loops and over-long chains are detected and reported, HTTPS-to-HTTP downgrades and temporary (302/307) redirects are flagged. - Security score and grade: seven headers are scored with partial credit for weak values (see the table below), minus up to 10 points for version disclosure in
Server/X-Powered-By. Each header comes with its status (good,weak,invalid,missing), notes and the value to set. - CSP parsing: directives found,
'unsafe-inline'(ignored when a nonce, hash or'strict-dynamic'is present),'unsafe-eval', wildcard or scheme-only script sources, missingdefault-src,object-src,base-uri,frame-ancestors. - HSTS details:
max-agein seconds and days,includeSubDomains,preload, and whether the header meets preload-list rules. - CORS:
Access-Control-Allow-Origin, methods, headers, max-age, plus warnings (any origin, thenullorigin, echoed origin withoutVary: Origin). Send your ownOriginto see how the server answers it. - Caching:
Cache-Controlsplit into fields (max-age,s-maxage,no-store,private,immutableand more),ETag,Last-Modified,Age,Vary, CDN cache status, and whether the response is cacheable in browsers and in shared caches. - Compression and protocol:
Content-Encoding(br, gzip) for an offeredbr, gzip, deflate, HTTP/2 support (TLS ALPN handshake), HTTP/3 advertised inAlt-Svc, TLS version. - Plain lists:
issues(every finding as a sentence) andrecommendations(header, value to set, points gained), plus all final response headers.
Use cases
- Verify 301 redirects after a site migration or a domain change, including multi-hop chains and loops.
- Confirm that
http://and bare-domain URLs upgrade to HTTPS, with HSTS set correctly. - Audit security headers across many sites and hand developers the exact values to set.
- Check
Cache-Control, CDN hits and compression on key pages or assets after a deploy. - Test CORS answers for a given origin, or compare desktop and mobile responses.
How to use it
- Paste URLs into URLs, one per line, or set Read URLs from a dataset to the ID of a dataset (for example the output of a sitemap run). Start a URL with
http://to test the HTTPS upgrade. - Optionally pick a Request method, a User-Agent, extra request headers or an Origin.
- Choose Output format:
fullfor nested JSON orflatfor spreadsheet-ready columns. - Run the Actor. Results land in the dataset; export them as JSON, CSV or Excel, or read them through the Apify API. The Issues and fixes view lists findings and values to set per URL.
Input
| Field | What it is | Default | Example |
|---|---|---|---|
urls | URLs to check. A bare domain is read as https://. Invalid entries are skipped with a log warning. | none | ["http://example.com/old-page", "example.org"] |
datasetId | ID or name of an Apify dataset to read URLs from (combined with urls). | none | "aBcD1234efGh5678" |
datasetUrlField | Field of each dataset item that holds the URL. | url | loc |
method | HEAD (lighter) or GET. If a server refuses HEAD (405 or 501), that URL is retried with GET. | HEAD | GET |
userAgent | bot, desktop or mobile. The browser-shaped strings still end in SiteCheckBot/1.0 (Apify Actor). | bot | mobile |
headers | Extra request headers as a JSON object. Headers carrying secrets (Authorization, API keys, tokens) are refused. | {} | {"Accept-Language": "de-DE"} |
origin | Sent as the Origin request header to test CORS. | none | example.org |
maxRedirects | Stop following after this many redirects (0 to 30). | 10 | 5 |
includeHopHeaders | Add all response headers to every hop of the chain. | false | true |
checkHttp2 | One TLS handshake to the final host to read HTTP/2 (ALPN) and the TLS version. | true | false |
outputFormat | full (nested) or flat (plain columns, lists joined with |). | full | flat |
maxConcurrency | URLs checked in parallel (1 to 5). The same host still gets at most one request per second. | 5 | 3 |
timeoutSecs | Timeout per request in seconds (1 to 120). | 15 | 30 |
maxItems | Check at most this many URLs. | 100 | 1000 |
Either urls or datasetId must give at least one valid URL.
Example input:
{"urls": ["http://apify.com", "https://docs.apify.com"],"method": "HEAD","userAgent": "bot","outputFormat": "full","maxItems": 2}
Scoring
| Header | Max points | Full points when |
|---|---|---|
| Strict-Transport-Security | 25 | max-age of at least one year (180 days or more gives 20, less gives 10) |
| Content-Security-Policy | 25 | enforced policy without 'unsafe-inline', 'unsafe-eval', broad script sources, and with default-src, object-src, base-uri (Report-Only alone gives 5) |
| X-Frame-Options | 15 | DENY or SAMEORIGIN, or CSP frame-ancestors |
| X-Content-Type-Options | 10 | nosniff |
| Referrer-Policy | 10 | no-referrer, same-origin, strict-origin or strict-origin-when-cross-origin |
| Permissions-Policy | 10 | present (legacy Feature-Policy alone gives 5) |
| Cross-Origin-Opener-Policy | 5 | same-origin or same-origin-allow-popups |
Version numbers in Server, X-Powered-By and similar headers cost up to 10 points. Grade: A+ 95 or more, A 85, B 70, C 55, D 40, F below 40. A final URL on plain HTTP is always F. Deprecated headers (X-XSS-Protection other than 0, Expect-CT, Public-Key-Pins) are listed in issues without changing the score.
Output
One row per URL. A real row from a run on http://apify.com on 2026-11-04 (the long CSP value, scriptSources and headers are shortened here; the dataset holds every value):
{"url": "http://apify.com/","finalUrl": "https://apify.com/","finalStatusCode": 200,"redirectCount": 1,"redirectLoop": false,"tooManyRedirects": false,"redirectChain": [{ "url": "http://apify.com/", "statusCode": 301, "location": "https://apify.com/", "timeMs": 125, "server": "CloudFront" },{ "url": "https://apify.com/", "statusCode": 200, "location": null, "timeMs": 1214, "server": null }],"httpsUpgrade": true,"method": "HEAD","userAgent": "bot","responseTimeMs": 1214,"totalTimeMs": 1340,"contentType": "text/html; charset=utf-8","cacheControl": "private, no-cache, no-store, max-age=0, must-revalidate","contentEncoding": null,"securityGrade": "C","securityScore": 62,"securityHeadersPresent": ["Strict-Transport-Security", "Content-Security-Policy", "X-Frame-Options", "X-Content-Type-Options"],"securityHeadersMissing": ["Referrer-Policy", "Permissions-Policy", "Cross-Origin-Opener-Policy"],"issues": ["Referrer-Policy is missing.","Cross-Origin-Opener-Policy is missing.","Strict-Transport-Security: max-age is 182 days; one year (31536000) is the common baseline.","Strict-Transport-Security: No includeSubDomains: subdomains can still be reached over HTTP.","Content-Security-Policy: script-src allows 'unsafe-inline' without a nonce or hash, so injected inline scripts run.","Content-Security-Policy: script-src allows 'unsafe-eval' (eval and new Function).","Permissions-Policy: Only the legacy Feature-Policy header is sent.","X-XSS-Protection \"1; mode=block\" is deprecated and can introduce leaks; set \"0\" or remove it, and rely on CSP.","Expect-CT is obsolete; it can be removed.","CORS allows any origin (*): fine for public assets, review it for private APIs.","no-store: nothing is cached, every visit is a full request.","No Content-Encoding on the HEAD response; some servers only compress GET, re-check with method GET."],"recommendations": [{ "header": "Strict-Transport-Security", "set": "max-age=31536000; includeSubDomains", "gain": 5 },{ "header": "Content-Security-Policy", "set": "replace 'unsafe-inline' in script-src with nonces or hashes; remove 'unsafe-eval'", "gain": 13 },{ "header": "Referrer-Policy", "set": "strict-origin-when-cross-origin", "gain": 10 },{ "header": "Permissions-Policy", "set": "camera=(), microphone=(), geolocation=()", "gain": 5 },{ "header": "Cross-Origin-Opener-Policy", "set": "same-origin (or same-origin-allow-popups if you open third-party windows)", "gain": 5 }],"securityHeaders": [{"header": "Strict-Transport-Security", "present": true, "value": "max-age=15768000","score": 20, "maxScore": 25, "status": "weak","notes": ["max-age is 182 days; one year (31536000) is the common baseline.", "No includeSubDomains: subdomains can still be reached over HTTP."],"recommendation": "max-age=31536000; includeSubDomains"},{ "header": "X-Frame-Options", "present": true, "value": "SAMEORIGIN", "score": 15, "maxScore": 15, "status": "good", "notes": [], "recommendation": null }],"hsts": { "maxAge": 15768000, "maxAgeDays": 182, "includeSubDomains": false, "preload": false, "preloadReady": false },"csp": {"directives": ["default-src", "connect-src", "img-src", "frame-src", "style-src", "style-src-elem", "style-src-attr", "script-src", "script-src-elem", "font-src", "form-action", "child-src", "media-src", "frame-ancestors", "base-uri"],"scriptSources": ["'self'", "'unsafe-eval'", "..."],"unsafeInline": true, "unsafeEval": true, "usesNonceOrHash": false, "strictDynamic": false,"broadScriptSources": [], "missingDirectives": [],"frameAncestors": "'self' https://cms.apify.com", "upgradeInsecureRequests": false, "reportsTo": false},"cors": {"enabled": true, "allowOrigin": "*", "allowCredentials": null, "allowMethods": null, "allowHeaders": null,"exposeHeaders": "Link", "maxAge": null, "crossOriginResourcePolicy": null, "crossOriginEmbedderPolicy": null,"warnings": ["CORS allows any origin (*): fine for public assets, review it for private APIs."]},"caching": {"cacheControl": "private, no-cache, no-store, max-age=0, must-revalidate", "maxAge": 0, "sMaxAge": null,"noStore": true, "noCache": true, "private": true, "public": false, "immutable": false, "mustRevalidate": true,"etag": null, "lastModified": null, "age": null, "vary": "Accept-Encoding", "cacheStatus": "Miss from cloudfront","servedFromCache": false, "browserCacheable": false, "sharedCacheable": false, "revalidatable": false},"compression": { "contentEncoding": null, "compressed": false, "brotli": false, "compressible": true },"protocol": { "altSvc": "h3=\":443\"; ma=86400", "http3Advertised": true, "alpn": "h2", "tlsVersion": "TLSv1.3", "http2Supported": true },"disclosure": { "penalty": 0 },"headers": { "content-type": "text/html; charset=utf-8", "strict-transport-security": "max-age=15768000", "x-frame-options": "SAMEORIGIN" },"checkedAt": "2026-11-04T09:46:15.860Z"}
In the same run https://docs.apify.com scored 40/100 (grade D): no CSP, X-Content-Type-Options, Referrer-Policy, Permissions-Policy or Cross-Origin-Opener-Policy. The same URL https://apify.com with "method": "GET" reports contentEncoding: "gzip", which HEAD did not show.
With "outputFormat": "flat" the same facts come as plain columns, for example redirectChain: "301 http://apify.com/ -> 200 https://apify.com/", hstsMaxAge, cspUnsafeInline, corsAllowOrigin, cacheMaxAge, http2Supported, issues and recommendations as |-joined text.
A redirect loop is a result too: the row has redirectLoop: true, the hops up to the repeated URL, finalUrl / finalStatusCode of the last response received (a 3xx), no security grade, and the loop in issues. Chains longer than maxRedirects look the same with tooManyRedirects: true.
| Field | Meaning |
|---|---|
finalUrl, finalStatusCode | Where the chain ends and that response's status code. |
redirectCount, redirectChain | Number of redirects and every hop with status, Location, time and server (all headers with includeHopHeaders). |
redirectLoop, tooManyRedirects | The chain revisits a URL, or is longer than maxRedirects. |
httpsUpgrade | true when an http:// URL ended on https://. |
securityScore, securityGrade | 0-100 and A+ to F, see Scoring. |
securityHeaders | Per-header value, score, status, notes and the value to set. |
recommendations | Only the headers to change: value to set and points gained. |
issues | Every finding as one sentence: chain, security, CORS, cache, compression. |
hsts, csp, cors, caching, compression, protocol, disclosure | Parsed details per area. |
headers | All final response headers, lower-cased. |
Pricing
Pay per result: $0.90 per 1,000 results ($0.0009 per result). You only pay for results the Actor returns. Set a maximum total charge on the run to cap your spend.
Limits
- Follows HTTP redirects only (status 3xx with
Location). Meta-refresh and JavaScript redirects are not followed. - Up to 30 hops per URL (
maxRedirects, default 10). Loops and over-long chains are reported as rows. - Unreachable URLs (DNS failure, refused connection, timeout, TLS error) produce no result and cost nothing; the run log names the reason. If no URL can be checked, the run fails with zero results.
- Checks what is publicly served. Headers carrying secrets (Authorization, API keys, tokens) are not sent.
- At most 5 URLs in parallel and at most one request per second to the same host.
- HEAD responses do not always show compression; use GET for that check.
- Internationalised domain names (for example
münchen.de) are converted to their ASCII form before the request.
FAQ
How much does it cost? $0.90 per 1,000 checked URLs. Unreachable URLs are free.
Is the score the same as other header graders? No. It is this Actor's own weighting, documented in the Scoring table, so every point can be traced to a header value.
Why do HEAD and GET give different results? Some servers or CDNs answer HEAD with different headers or status codes, and many only report compression on GET. Switch Request method to GET to see what a browser gets.
Why is a URL missing from the results? The domain did not resolve, the connection failed or timed out, or the certificate was invalid. The run log names the reason for each skipped URL.
Can I check URLs from another run? Yes. Set Read URLs from a dataset to that run's dataset ID and Dataset URL field to the field holding the URL.
How do I get a spreadsheet? Set Output format to flat and export the dataset as CSV or Excel.
Need DNS records, TLS certificate expiry or indexability? See Plain Pipe's DNS Records Lookup, Website Status Checker and Indexability Checker. For on-page tags, see Plain Pipe's SEO Page Audit & On-Page Checker.
Can I monitor headers on a schedule? Yes. Use Apify Schedules for recurring runs and the Apify API, webhooks or integrations to compare securityScore or issues over time.
Why this one
- $0.90 per 1,000 results ($0.0009 per checked URL); unreachable URLs are not charged.
- Each row gives the value to set for every weak or missing header and the points it adds, plus parsed CSP (unsafe-inline, unsafe-eval, missing directives) and HSTS (max-age, includeSubDomains, preload readiness).
- Redirect chain with per-hop timing and loop detection, CORS, cache, compression, HTTP/2 and HTTP/3 checks in the same row;
flatoutput for spreadsheets. - HEAD requests by default with automatic GET fallback, 5 URLs in parallel; no browser and no proxy. The 2-URL prefill run finishes in under 5 seconds (about 2 s in our tests), and the prefilled input is test-run daily.
Legal and data
This Actor processes only what you give it or public, non-personal technical data. It does not log in anywhere, does not collect personal data, and does not bypass paywalls, CAPTCHAs or access controls. You are responsible for having the right to process the inputs you provide.
Support
Open an issue on the Issues tab. Issues are answered within 14 days.
Built and maintained by Plain Pipe.