# Security Headers Checker: Bulk HTTP Header Scan & A-F Grade (`datawright-labs/security-headers-checker`) Actor

Security headers checker for any list of URLs: HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, cookie flags, HTTP to HTTPS redirect and server disclosure, with an A-F grade and fix list. Callable by AI agents via MCP. $1 per 1,000 URLs.

- **URL**: https://apify.com/datawright-labs/security-headers-checker.md
- **Developed by:** [Datawright Labs](https://apify.com/datawright-labs) (community)
- **Categories:** Developer tools, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 url checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

**For AI agents:** Use when asked to check a website's security headers, HTTP headers, HSTS, Content-Security-Policy, clickjacking protection, cookie flags or HTTP to HTTPS redirect, or to grade site security. Call with `urls` (URLs or domains; required), optional `outputFilter` (`all`, `problems`, `below-grade`) and `gradeThreshold`. Returns one row per URL: `grade` (A-F), `score` (0-100), `finalUrl`, `missingHeaders`, `problems`, `recommendations`, `checks` (per header), `headers`, `cookies`, `httpToHttps`, `tlsValid`, `techDisclosure`, `securityTxt`. Cost: $0.001 per URL ($1 per 1,000); unreachable URLs and invalid inputs free.

**For people:** Tell your AI agent "check the security headers of our 40 client websites and list the ones graded C or worse with what to fix" and it hands the list to this tool, then reads back a clean table. No browser extensions, no one-site-at-a-time scanners, and 1,000 URLs cost $1.

**Bulk security headers checker for hundreds or thousands of websites in one run.** Paste a list of URLs or domains and this HTTP header scanner fetches each page like a browser, follows the **redirect chain**, and grades the final response's **security headers**: **Strict-Transport-Security (HSTS)**, **Content-Security-Policy (CSP)** with `unsafe-inline` / `unsafe-eval` / wildcard detection, **X-Frame-Options** or CSP `frame-ancestors` (clickjacking), **X-Content-Type-Options**, **Referrer-Policy** and **Permissions-Policy**. It also checks that **http:// redirects to https://**, that **cookies** have Secure / HttpOnly / SameSite, that the **TLS certificate** is valid, that the server doesn't **disclose its software version** (Server, X-Powered-By, X-AspNet-Version) and whether a **security.txt** is published. Every URL gets an **A-F grade**, a **0-100 score** and a plain-English **problems list** with the fix.

No proxies, no API keys and no browser: results export to **CSV, Excel, JSON or Google Sheets** or run on a **schedule** as a security header monitor for your sites or your clients'.

### What does this security headers checker do?

- 🛡️ **Six key security headers** graded with the details that matter: HSTS `max-age` (180 days minimum), `includeSubDomains` and `preload`; CSP that doesn't restrict scripts, allows `'unsafe-inline'` without a nonce or hash, `'unsafe-eval'` or `*` / `https:` script sources, or is Report-Only; obsolete `ALLOW-FROM`; unsafe Referrer-Policy values; deprecated Feature-Policy.
- 🔀 **Redirects**: the full **redirect chain** (every hop with status code, location and timing), the **HTTP to HTTPS redirect** of the plain-http version, HTTPS-to-HTTP downgrades, redirect loops.
- 🍪 **Cookie flags** for every Set-Cookie along the chain: missing **Secure**, session-like cookies without **HttpOnly**, missing or invalid **SameSite**.
- 🔐 **TLS certificate validity** (expired, self-signed, wrong host and untrusted certificates are flagged and graded F, while the headers are still read).
- 🕵️ **Information disclosure**: `Server: nginx/1.18.0`, `X-Powered-By: PHP/8.1`, `X-AspNet-Version` and similar version leaks.
- 📄 **security.txt** (RFC 9116): contacts and expiry date, expired files flagged.
- 🅰️ **A-F grade and 0-100 score** per URL, `missingHeaders`, `problems` (scored) and `recommendations` (optional hardening such as COOP, SameSite, deprecated X-XSS-Protection), plus the raw header values.
- 🧹 **Bulk-friendly input**: full URLs, bare domains (`example.com` -> `https://example.com/`) or emails, de-duplicated; up to 50 checks in parallel, at most 4 per host.

### How the grade is calculated

| Check | Points |
|---|---|
| Strict-Transport-Security (max-age >= 180 days) | 20 |
| Content-Security-Policy that restricts scripts safely | 20 |
| Clickjacking protection (X-Frame-Options or CSP frame-ancestors) | 15 |
| X-Content-Type-Options: nosniff | 10 |
| Referrer-Policy (safe value) | 10 |
| HTTP redirects to HTTPS | 10 |
| Permissions-Policy | 5 |
| Cookies with Secure (+ HttpOnly on session cookies) | 5 |
| No server version disclosure | 5 |

**A** 90-100, **B** 75-89, **C** 60-74, **D** 45-59, **F** below 45. A page that ends on plain HTTP or has an invalid TLS certificate is always **F**.

### Use cases

- **Website security audits** for agencies, MSPs and freelancers: grade every client site in one run and hand over a fix list.
- **Security header monitoring**: schedule a weekly run with **Only URLs graded below the threshold** and get alerted when a deploy drops HSTS or CSP.
- **Vendor and third-party risk**: check the public sites of suppliers, SaaS vendors or acquisition targets for basic hygiene.
- **Lead generation for security services**: find prospects with missing headers, plain HTTP or outdated server software.
- **Pentest and bug bounty recon**: map CSP weaknesses, cookie flags, version leaks and security.txt contacts across many hosts.
- **Compliance evidence** (SOC 2, ISO 27001, PCI DSS, OWASP ASVS): export a dated CSV of headers for every public endpoint.

### How to use it

1. Paste URLs or domains into **URLs or domains**, one per line.
2. Optionally choose **Which URLs to save** (all, only problems, only below a grade) and keep the HTTP-to-HTTPS and security.txt checks on.
3. Click **Start**, then open the **Overview** table or export the results. For monitoring, add a **Schedule** plus an email, Slack or webhook integration in Apify Console.

#### Input example

```json
{
  "urls": ["apify.com", "https://github.com/login", "example.com"],
  "checkHttpRedirect": true,
  "checkSecurityTxt": true,
  "outputFilter": "all"
}
```

### Output example

```json
{
  "url": "https://example.com/",
  "status": "ok",
  "grade": "F",
  "score": 30,
  "finalUrl": "https://example.com/",
  "finalStatusCode": 200,
  "https": true,
  "tlsValid": true,
  "redirectCount": 0,
  "httpToHttps": { "url": "http://example.com/", "redirectsToHttps": false, "firstHopStatus": 200, "note": "Served over plain HTTP without a redirect to HTTPS" },
  "missingHeaders": ["strict-transport-security", "content-security-policy", "x-frame-options", "x-content-type-options", "referrer-policy", "permissions-policy"],
  "problems": [
    "Missing Strict-Transport-Security (HSTS) header",
    "Missing Content-Security-Policy header",
    "No clickjacking protection (missing X-Frame-Options and CSP frame-ancestors)",
    "Missing X-Content-Type-Options: nosniff",
    "Missing Referrer-Policy header",
    "Missing Permissions-Policy header",
    "HTTP version does not redirect to HTTPS (page served over plain HTTP)"
  ],
  "recommendations": ["Consider Cross-Origin-Opener-Policy: same-origin (isolates your window from cross-origin popups)", "Publish a /.well-known/security.txt with a Contact (RFC 9116)"],
  "checks": { "hsts": { "pass": false, "points": 0, "max": 20, "maxAgeSeconds": null }, "csp": { "pass": false, "points": 0, "max": 20 } },
  "cookies": [],
  "server": "cloudflare",
  "techDisclosure": [],
  "securityTxt": { "found": false, "url": "https://example.com/.well-known/security.txt" },
  "checkedAt": "2026-10-24T22:30:00.000Z"
}
```

`checks` has one entry per scored check (shortened above) and `headers` holds the raw values of every security-relevant header. URLs that can't be reached (DNS failure, timeout, refused) come back as `status: "error"` and are **free**. A **SUMMARY** record in the key-value store has counts per grade.

### How much does a security headers check cost?

You pay **$0.001 per URL checked** ($1 per 1,000 URLs). **Unreachable URLs and invalid inputs are free**, URLs skipped by **Which URLs to save** are **free** too, and the HTTP-to-HTTPS and security.txt requests are included. No start fee.

| Job | URLs | Cost |
|---|---|---|
| Your 10 sites, weekly header monitor | ~40/month | **~$0.04/month** |
| Agency: 300 client sites, monthly audit | 300/month | **$0.30/month** |
| Scan 20,000 company websites for missing headers | 20,000 | **$20** |

- Apify's **free plan includes $5 of monthly credit**, enough for about **5,000 URLs a month**.
- Paid Apify plans get automatic discounts: **Silver -10%**, **Gold and above -20%**.
- Set **Maximum cost per run** to cap spend; the Actor stops cleanly at the limit.

### Bulk security headers checker vs. the alternatives

| | This Actor | securityheaders.com / browser extensions | curl -I by hand | Security scanner subscriptions |
|---|---|---|---|---|
| Many URLs in one go | ✅ thousands per run | ❌ one at a time | ✅ after you write the script | ✅ |
| Grade + plain-English fix list | ✅ | ✅ | ❌ | ✅ |
| CSP quality (unsafe-inline, unsafe-eval, wildcards) | ✅ | partly | ❌ | ✅ |
| HTTP to HTTPS redirect, redirect chain, cookies, TLS validity | ✅ in one row | partly | DIY | ✅ |
| CSV / Excel / JSON / Sheets export, schedules, webhooks | ✅ | ❌ | DIY | varies |
| Callable by AI agents (MCP) | ✅ | ❌ | ❌ | rarely |
| Cost model | $1 per 1,000 URLs, no subscription | free, manual | free + your time | monthly plan |

### Use it as an API (Python, JavaScript, cURL)

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("datawright-labs/security-headers-checker").call(run_input={"urls": ["example.com", "https://github.com/login"]})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["url"], item.get("grade"), item.get("score"), item.get("missingHeaders"))
```

#### JavaScript / Node.js

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('datawright-labs/security-headers-checker').call({ urls: ['example.com'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/datawright-labs~security-headers-checker/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" -d '{"urls":["example.com"],"outputFilter":"all"}'
```

### Use it from your AI agent (MCP)

Your AI assistant or agent can run this Actor as a tool through [Apify's MCP server](https://docs.apify.com/platform/integrations/mcp), so it can audit security headers on its own while you chat. Add this server to any MCP client that supports remote (Streamable HTTP) servers:

```json
{
  "mcpServers": {
    "datawright-security-headers-checker": {
      "url": "https://mcp.apify.com?tools=datawright-labs/security-headers-checker"
    }
  }
}
```

On first use your browser opens to sign in to Apify (OAuth). If your client can't do OAuth, add `"headers": { "Authorization": "Bearer <YOUR_APIFY_TOKEN>" }` instead. The tool shows up as `datawright-labs--security-headers-checker`, with the same input fields as above, and the agent reads the results with `get-dataset-items`. Then just ask, for example:

> Check the security headers of these 25 websites and list the ones graded C or worse, with the top fix for each.

Want several Datawright tools at once? Comma-separate them: `https://mcp.apify.com?tools=datawright-labs/security-headers-checker,datawright-labs/ssl-certificate-checker`. Runs are billed per result, exactly like normal runs.

### FAQ

#### How do I check the security headers of a website?

Paste the URL (or just the domain) and run. Each row shows the grade, which of the six key headers are missing or weak, and why. Use `headers` for the exact values the server sent after all redirects.

#### Which security headers should every website have?

At minimum Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options: nosniff, clickjacking protection (X-Frame-Options or CSP frame-ancestors) and Referrer-Policy, plus Permissions-Policy. X-XSS-Protection is deprecated and Expect-CT is obsolete; this checker recommends removing them rather than rewarding them.

#### Does it check whether HTTP redirects to HTTPS?

Yes. With **Check HTTP to HTTPS redirect** on, it also requests the http:// version and records whether (and after how many hops) it reaches HTTPS. Hosts that don't answer on port 80 at all serve nothing unencrypted and pass.

#### Why did a well-known site get a low grade?

Many big sites skip headers like CSP or Permissions-Policy on their home page. The grade only reflects the headers on the URL you gave; check login or app pages separately. If a site answers with a bot-protection page (403/503), the headers of that page are graded and a note is added to `recommendations`.

#### Is this a vulnerability scanner?

No. It sends normal GET requests (plus one for http:// and one for security.txt) and reads response headers, like a browser does. It doesn't probe for vulnerabilities, so it's safe to run on any public site.

#### Does it handle invalid or expired SSL certificates?

Yes. The page is still fetched so its headers can be graded, the certificate error (expired, self-signed, wrong host, untrusted) is added to `problems`, `tlsValid` is false and the grade is F. For full certificate details and expiry monitoring use the SSL Certificate Checker below.

### More tools from Datawright Labs

- [SSL Certificate Checker](https://apify.com/datawright-labs/ssl-certificate-checker): bulk SSL certificate and domain expiry checks with alerts for expiring, invalid or outdated TLS.
- [SPF, DMARC & DKIM Checker](https://apify.com/datawright-labs/email-domain-dns-checker): bulk email domain audit of SPF (10-lookup limit), DMARC, DKIM, MX provider, BIMI and MTA-STS.
- [WHOIS Domain Lookup (RDAP)](https://apify.com/datawright-labs/whois-rdap-domain-lookup): bulk registrar, domain age, expiry date, nameservers, EPP status and availability from official registry RDAP.
- [Broken Link Checker](https://apify.com/datawright-labs/broken-link-checker): find broken links, images and redirects across a whole site.
- [Sitemap URL Extractor](https://apify.com/datawright-labs/sitemap-url-extractor): get every URL of a site from its sitemaps.
- [Bulk PageSpeed & Core Web Vitals Checker](https://apify.com/datawright-labs/pagespeed-auditor): audit PageSpeed / Lighthouse scores for many URLs.
- [Website Screenshot API](https://apify.com/datawright-labs/website-screenshot): bulk full-page screenshots and PDFs.
- [Google Autocomplete Keyword Scraper](https://apify.com/datawright-labs/autocomplete-keyword-scraper): long-tail keyword ideas from Google, YouTube and Bing.
- [Greenhouse, Lever & Ashby Jobs Scraper](https://apify.com/datawright-labs/ats-jobs-scraper): normalized job feeds from 5 ATS platforms.
- [App Store Top Charts & Rank Tracker](https://apify.com/datawright-labs/app-store-top-charts): daily top free/paid/grossing app rankings with rank changes.

Tip: pair it with the **SSL Certificate Checker** and the **SPF, DMARC & DKIM Checker** for a full domain security audit.

Made by **Datawright Labs**: reliable, fairly priced web data tools. Questions or a missing feature? Open an issue on the Issues tab; we usually reply within a day.

# Actor input Schema

## `urls` (type: `array`):

One per line: full URLs (https://example.com/login) or bare domains (example.com, checked as https://example.com/). Each URL is fetched with a normal browser request, redirects are followed and the final response headers are graded. Duplicates are merged.

## `checkHttpRedirect` (type: `boolean`):

Also request the plain http:// version of each URL and check that it redirects to HTTPS (no extra charge).

## `checkSecurityTxt` (type: `boolean`):

Look for /.well-known/security.txt (RFC 9116) on the final host and report its contacts and expiry (no extra charge).

## `outputFilter` (type: `string`):

URLs that don't match are skipped and not charged. Use "below the threshold" for scheduled alert runs.

## `gradeThreshold` (type: `string`):

Used with "Only URLs graded below the threshold".

## `maxRedirects` (type: `integer`):

How many redirects to follow before giving up.

## `includeRawHeaders` (type: `boolean`):

Add every response header of the final page to each row (rawHeaders).

## `timeoutSecs` (type: `integer`):

Timeout per request.

## `concurrency` (type: `integer`):

How many URLs to check at the same time (never more than 4 at once per host).

## Actor input object example

```json
{
  "urls": [
    "apify.com",
    "github.com",
    "example.com"
  ],
  "checkHttpRedirect": true,
  "checkSecurityTxt": true,
  "outputFilter": "all",
  "gradeThreshold": "B",
  "maxRedirects": 10,
  "includeRawHeaders": false,
  "timeoutSecs": 20,
  "concurrency": 10
}
```

# Actor output Schema

## `results` (type: `string`):

Per-URL security header results.

## `summary` (type: `string`):

SUMMARY record: URLs checked and counts per grade.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "apify.com",
        "github.com",
        "example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("datawright-labs/security-headers-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": [
        "apify.com",
        "github.com",
        "example.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("datawright-labs/security-headers-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "apify.com",
    "github.com",
    "example.com"
  ]
}' |
apify call datawright-labs/security-headers-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datawright-labs/security-headers-checker"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/pffzAfsLUWekZX3Ro/builds/5aLLCKtnQyK9h2CfA/openapi.json
