# HSTS Preload Auditor (`phoenix2810/hsts-preload-auditor`) Actor

Audit a public HTTPS URL's HSTS header against hstspreload.org submission requirements. Returns max-age, includeSubDomains, preload eligibility, redirect verification, score, grade, and recommendations.

- **URL**: https://apify.com/phoenix2810/hsts-preload-auditor.md
- **Developed by:** [Sanskar Jaiswal](https://apify.com/phoenix2810) (community)
- **Categories:** Developer tools, SEO tools, Open source
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## HSTS Preload Auditor

Audits the Strict-Transport-Security (HSTS) configuration of any public HTTPS URL against the hstspreload.org submission requirements and returns a preload readiness score, letter grade, issues, and recommendations as structured JSON.

### Use cases

- Security teams verifying HSTS posture before submitting a domain to the HSTS preload list
- DevOps engineers checking that HSTS headers survive deploys, CDN cutovers, and origin migrations
- Site migration QA confirming the plain-HTTP virtual host still redirects to HTTPS on the same host
- Agency consultants running recurring transport-security checks across client domains
- CI pipelines gating releases on transport security regressions

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| startUrl | string | (required) | Public HTTPS URL to audit. A bare hostname gets the https scheme prepended. |
| timeoutSeconds | integer | 10 | Request timeout per request, from 3 to 30 seconds. |
| checkHttpRedirect | boolean | true | Also request the plain-HTTP version of the host and verify it redirects to HTTPS on the same host, as required for preload submission. |
| checkWwwSubdomain | boolean | false | Also request the www subdomain (or the bare domain when the input is www) over HTTPS and verify it responds successfully, since preloading covers all subdomains. |

### Output

One dataset item per run:

| Field | Type | Description |
| --- | --- | --- |
| inputUrl | string | URL as provided in the input. |
| normalizedInputUrl | string | URL after scheme normalization and validation. |
| finalUrl | string | Final URL after redirects of the HTTPS request. |
| https | boolean | Whether the final response was served over HTTPS. |
| ok | boolean | Whether the audit completed without a fetch or validation error. |
| checkedAt | string | ISO 8601 timestamp of the check. |
| httpStatus | integer or null | HTTP status of the HTTPS response. |
| hasHsts | boolean | Whether a Strict-Transport-Security header was served. |
| rawHsts | string or null | Raw header value. |
| maxAge | integer or null | Parsed max-age in seconds. |
| maxAgeMeetsPreload | boolean | Whether max-age is at least 31536000 (1 year). |
| includeSubDomains | boolean | Whether the includeSubDomains directive is present. |
| preloadDirective | boolean | Whether the preload directive is present. |
| hasExtraDirectives | boolean | Whether unrecognized directives (for example report-uri) are present. |
| extraDirectives | array | Names of unrecognized directives. |
| multipleMaxAge | boolean | Whether more than one max-age directive was sent. |
| classification | string | One of: preload-eligible, missing, invalid, short-max-age, missing-include-subdomains, missing-preload. |
| validCertificate | boolean | Whether the HTTPS request completed with a valid certificate chain. |
| httpRedirectChecked | boolean | Whether the HTTP redirect check ran. |
| httpRedirectOk | boolean or null | Whether plain HTTP redirected to HTTPS on the same host. |
| httpRedirectStatus | integer or null | Final HTTP status of the redirect check. |
| httpRedirectTarget | string or null | Final URL of the redirect check. |
| wwwSubdomainChecked | boolean | Whether the www subdomain check ran. |
| wwwSubdomainOk | boolean or null | Whether the subdomain responded successfully over HTTPS. |
| wwwSubdomainStatus | integer or null | HTTP status of the subdomain check. |
| preloadEligible | boolean | Whether every performed check passed the hstspreload.org requirements. |
| submissionReady | boolean | Alias of preloadEligible. |
| score | integer | Readiness score from 0 to 100. |
| grade | string | Letter grade from A+ to F. |
| issues | array | Concrete problems found. |
| recommendations | array | Actionable fixes. |
| error | string or null | Error message when the audit could not complete. |

### Example input

```json
{
    "startUrl": "https://www.google.com/",
    "timeoutSeconds": 10,
    "checkHttpRedirect": true,
    "checkWwwSubdomain": false
}
```

### Example output

```json
{
    "inputUrl": "https://www.google.com/",
    "finalUrl": "https://www.google.com/",
    "https": true,
    "ok": true,
    "hasHsts": true,
    "maxAge": 31536000,
    "maxAgeMeetsPreload": true,
    "includeSubDomains": true,
    "preloadDirective": true,
    "classification": "preload-eligible",
    "httpRedirectOk": true,
    "preloadEligible": true,
    "score": 100,
    "grade": "A+",
    "issues": [],
    "recommendations": [
        "HSTS preload requirements are met. Submit the domain at hstspreload.org, then monitor that the header never regresses after deploys."
    ],
    "error": null
}
```

### Security

- Fetches public HTTP/HTTPS URLs only; URLs with credentials are rejected.
- Private IPv4, private IPv6, and loopback targets are blocked, hostnames are DNS-resolved, and resolutions to private ranges are rejected (SSRF defense).
- Every redirect hop is revalidated through the same checks before being followed.
- No login, no cookies are stored, no JavaScript is executed, and no page content is retained.

### Pricing

| Event | Price |
| --- | --- |
| Actor start | $0.005 per run |
| Domain audited | $0.01 per result |

A typical single-domain audit costs $0.015.

### FAQ

**Does this actor submit my domain to the preload list?**
No. It audits readiness only. Submission happens at hstspreload.org.

**Why does a valid HSTS header still not score A+?**
Preload submission requires more than a header: the HTTP virtual host must redirect to HTTPS on the same host, the certificate chain must be valid, and every subdomain must serve HTTPS. The actor verifies the checks it can perform and reports each one.

**What counts as extra directives?**
Anything other than max-age, includeSubDomains, and preload. RFC 6797 tells browsers to ignore unknown directives, but hstspreload.org expects a clean header, so they are reported as issues.

# Actor input Schema

## `startUrl` (type: `string`):

Public HTTPS URL to audit. The actor fetches this page and inspects the Strict-Transport-Security response header.

## `timeoutSeconds` (type: `integer`):

Request timeout from 3 to 30 seconds per request.

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

Also request the plain-HTTP version of the host and verify it redirects to HTTPS on the same host, as required for preload submission.

## `checkWwwSubdomain` (type: `boolean`):

Also request the www subdomain (or the bare domain if the input is www) over HTTPS and verify it responds successfully, since preloading covers all subdomains.

## Actor input object example

```json
{
  "startUrl": "https://example.com/",
  "timeoutSeconds": 10,
  "checkHttpRedirect": true,
  "checkWwwSubdomain": false
}
```

# Actor output Schema

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

No description

# 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 = {
    "startUrl": "https://example.com/"
};

// Run the Actor and wait for it to finish
const run = await client.actor("phoenix2810/hsts-preload-auditor").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 = { "startUrl": "https://example.com/" }

# Run the Actor and wait for it to finish
run = client.actor("phoenix2810/hsts-preload-auditor").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 '{
  "startUrl": "https://example.com/"
}' |
apify call phoenix2810/hsts-preload-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,phoenix2810/hsts-preload-auditor"
        }
    }
}
```

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/EHvUisqVWxchE8p7j/builds/webFwq5I29r7Y0QaB/openapi.json
