Security Headers & SSL Certificate Checker in Bulk · Apify
Website Security Headers & TLS Audit avatar

Website Security Headers & TLS Audit

Pricing

from $10.00 / 1,000 domain auditeds

Go to Apify Store
Website Security Headers & TLS Audit

Website Security Headers & TLS Audit

Grade any website's security from A+ to F: HTTPS redirect, HSTS, CSP, clickjacking protection, cookie flags, TLS certificate expiry, security.txt and e-mail spoofing protection (SPF, DMARC). Passive and polite.

Pricing

from $10.00 / 1,000 domain auditeds

Rating

0.0

(0)

Developer

Helvetic Labs

Helvetic Labs

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

20 days ago

Last modified

Features

Limited permissions

Share

Grade the security of up to 5,000 websites per run from A+ to F, with a concrete fix for every finding. One run checks HTTPS and the HTTP to HTTPS redirect, the security headers (HSTS, CSP, X-Frame-Options and more), cookie flags, the SSL/TLS certificate and its expiry, security.txt, and the domain's e-mail spoofing protection (SPF and DMARC). For agencies, security teams, developers and IT administrators who want a quick, passive and repeatable security check of many domains.

What is Website Security Headers & TLS Audit?

It is a bulk security headers checker, SSL certificate checker and SPF/DMARC checker in one Actor. You enter domains or URLs; for each host it looks at what every browser and every mail server can see anyway, scores the web security from 0 to 100, turns the score into a grade from A+ to F, scores the e-mail protection separately, and lists every check as pass, warn, fail or info, with a short fix for each problem.

The audit is passive. Per domain it requests the home page over HTTPS and over HTTP without reading the page body, fetches /.well-known/security.txt, makes one TLS handshake and runs a few DNS lookups. There are no port scans, no probing of paths, no login attempts and no load on the site. It respects robots.txt and identifies itself with an honest user agent.

What does it check?

Web security (score 0 to 100, graded A+ to F):

  • HTTPS: the home page answers over HTTPS with a valid certificate.
  • HTTP to HTTPS redirect: http:// ends on an HTTPS URL.
  • HSTS (Strict-Transport-Security): present, max-age, includeSubDomains and preload.
  • Content-Security-Policy: present, whether it allows inline scripts ('unsafe-inline' without nonces, hashes or 'strict-dynamic'), whether it allows 'unsafe-eval', and whether it has frame-ancestors.
  • Clickjacking protection: CSP frame-ancestors or X-Frame-Options: DENY or SAMEORIGIN.
  • X-Content-Type-Options: nosniff, Referrer-Policy and Permissions-Policy.
  • Cookie flags: how many cookies the home page sets, and how many lack Secure, HttpOnly or SameSite. Counts only, never cookie names or values.
  • Software version disclosure: whether Server or X-Powered-By shows a version number.
  • TLS and SSL certificate: TLS version, certificate issuer, expiry date and days left.
  • security.txt (RFC 9116): published at /.well-known/security.txt with a Contact field, whether it has an Expires field, and whether it is expired.

E-mail spoofing protection (scored 0 to 100 separately):

  • SPF: present, exactly one record, and how it ends (-all, ~all, ?all, +all).
  • DMARC: present, policy (none, quarantine, reject), pct, whether aggregate reports are requested (yes or no, never the address), and for subdomains the policy they inherit from a parent domain.
  • MX: the number of mail servers.

Also reported:

  • CAA records: whether the domain restricts which certificate authorities may issue certificates for it, and which ones.

Use cases

  • Client audits for agencies: run all client domains at once, sort by grade and send each client the findings with their fixes.
  • Security reviews of your own domains: find the forgotten marketing site without HSTS, the subdomain with an expiring certificate or the brand domain without DMARC.
  • SSL certificate expiry monitoring: schedule a daily run and alert on tls.days_left below your threshold, before visitors see a certificate warning.
  • E-mail spoofing checks: check SPF and DMARC across a portfolio of domains, including parked domains that should publish v=spf1 -all and a DMARC reject policy.
  • Release checks: after a deployment, confirm that the security headers are still set and that the grade did not drop.
  • Supplier and partner overviews: get a quick, passive view of the public security posture of the domains you work with, where you are allowed to check them.
  • Tracking progress: run the same list every month and compare the scores over time.

How to use Website Security Headers & TLS Audit

  1. Open the Actor in Apify Console (click Try for free or Start on this page).
  2. Enter your domains or URLs in Domains or URLs, one per line.
  3. Keep Check e-mail DNS (SPF, DMARC) on to get the e-mail score, or turn it off to audit only the web side.
  4. Optionally change the timeout.
  5. Set a maximum cost per run in the run options if you want a hard spending limit.
  6. Click Start. When the run is done, open the Output tab, sort by grade or score, and download the results as JSON, CSV, Excel, XML or HTML.
  7. Create a Schedule to repeat the audit daily, weekly or monthly.

Input

FieldTypeDefaultWhat it does
domainsarray of strings(required)Domains (example.com) or URLs (https://www.example.com/page).
checkEmailDnsbooleantrueAlso check SPF, DMARC and MX of the domain.
timeoutSecsinteger, 5 to 6015How long to wait for each response, in seconds.

Tips:

  • One host per line. From a URL only the host name is used, and the home page of that host is audited; the path is ignored. example.com and www.example.com are different hosts and are audited (and charged) separately, so enter the one your visitors use, or both if you want to compare.
  • E-mail checks use the domain without www. For www.example.com, SPF and DMARC are looked up for example.com.
  • IP addresses can be audited for HTTPS and headers; the e-mail and CAA checks are then skipped.
  • Limits: up to 5,000 entries per run; further entries are ignored. Exact duplicates are audited once.
  • API input: besides strings, you can pass objects like {"url": "https://example.com/"}.

Example input:

{
"domains": ["example.com", "https://www.example.org/", "shop.example.net"],
"checkEmailDns": true,
"timeoutSecs": 15
}

Output

One dataset item per domain, in the order of your input. A complete example:

{
"input": "example.com",
"domain": "example.com",
"checked_at": "2026-10-18T09:00:00Z",
"https": {"ok": true, "status": 200, "final_url": "https://example.com/", "http_version": "HTTP/1.1", "error": ""},
"http_to_https": true,
"tls": {"ok": true, "version": "TLSv1.3", "issuer": "Let's Encrypt", "valid_until": "2027-01-05", "days_left": 79, "error": ""},
"headers": {
"hsts": {"present": true, "max_age": 31536000, "include_subdomains": true, "preload": false},
"csp": {"present": false, "frame_ancestors": false, "unsafe_inline_scripts": false, "unsafe_eval": false},
"x_frame_options": "sameorigin",
"x_content_type_options": true,
"referrer_policy": "strict-origin-when-cross-origin",
"permissions_policy": false,
"server_version_disclosed": false
},
"cookies": {"count": 2, "without_secure": 0, "without_httponly": 1, "without_samesite": 1},
"security_txt": {"present": true, "has_contact": true, "has_expires": true, "expired": false},
"error": "",
"score": 75,
"grade": "B",
"email": {
"domain": "example.com",
"mx_count": 2,
"spf": {"present": true, "records": 1, "all": "-all"},
"dmarc": {"present": true, "policy": "quarantine", "pct": 100, "reports": true, "inherited_from": null, "invalid": false}
},
"email_score": 95,
"caa": {"present": true, "issuers": ["letsencrypt.org"]},
"findings": [
{"check": "http_redirect", "status": "pass", "detail": "HTTP redirects to HTTPS.", "fix": ""},
{"check": "hsts", "status": "pass", "detail": "HSTS max-age 31536000 s.", "fix": ""},
{"check": "csp", "status": "fail", "detail": "No Content-Security-Policy header.", "fix": "Add a Content-Security-Policy, starting with default-src 'self'."},
{"check": "framing", "status": "pass", "detail": "The site cannot be framed by others.", "fix": ""},
{"check": "nosniff", "status": "pass", "detail": "X-Content-Type-Options: nosniff is set.", "fix": ""},
{"check": "referrer", "status": "pass", "detail": "A privacy-friendly Referrer-Policy is set.", "fix": ""},
{"check": "permissions", "status": "warn", "detail": "No Permissions-Policy.", "fix": "Add a Permissions-Policy that turns off unused features (camera, microphone, geolocation)."},
{"check": "cookies", "status": "warn", "detail": "Some cookies lack HttpOnly or SameSite.", "fix": "Set HttpOnly and SameSite on every cookie scripts do not need."},
{"check": "disclosure", "status": "pass", "detail": "No software versions in the headers.", "fix": ""},
{"check": "tls", "status": "pass", "detail": "TLSv1.3, certificate valid until 2027-01-05.", "fix": ""},
{"check": "security_txt", "status": "pass", "detail": "security.txt is published.", "fix": ""},
{"check": "spf", "status": "pass", "detail": "SPF record ends with -all.", "fix": ""},
{"check": "dmarc", "status": "pass", "detail": "DMARC policy quarantine.", "fix": ""}
]
}

An entry that is not a public domain is listed like this, free of charge:

{"input": "typo-domain.example", "domain": null, "grade": null, "error": "dns_error"}

Output fields

FieldTypeMeaning
inputstringYour entry as given (trimmed, at most 500 characters).
domainstring or nullThe audited host name; null when the entry could not be audited.
checked_atstringWhen the domain was audited, in UTC.
https.okbooleanThe HTTPS home page answered (status below 500) and ended on an HTTPS URL.
https.statusinteger or nullStatus code of the HTTPS home page.
https.final_urlstring or nullWhere the HTTPS home page ends up after redirects.
https.http_versionstring or nullHTTP version of that answer.
https.errorstringWhy HTTPS did not work, for example tls_error or timeout.
http_to_httpsboolean or nullhttp:// ends on an HTTPS URL; null when the HTTP request failed (scored as no redirect).
tls.okbooleanThe TLS handshake on port 443 worked and the certificate is valid for the host.
tls.versionstring or nullNegotiated TLS version, for example TLSv1.3.
tls.issuerstring or nullThe certificate issuer's organization (or common name).
tls.valid_untilstring or nullCertificate expiry date (YYYY-MM-DD).
tls.days_leftinteger or nullDays until the certificate expires.
tls.errorstringWhy the handshake failed, for example a certificate verification message.
headers.hstsobjectpresent, max_age (seconds), include_subdomains, preload.
headers.cspobjectpresent, frame_ancestors, unsafe_inline_scripts, unsafe_eval.
headers.x_frame_optionsstring or nullThe X-Frame-Options value in lower case.
headers.x_content_type_optionsbooleanX-Content-Type-Options is nosniff.
headers.referrer_policystring or nullThe effective Referrer-Policy value.
headers.permissions_policybooleanA Permissions-Policy header is set.
headers.server_version_disclosedbooleanServer or X-Powered-By contains a version number.
cookiesobjectcount, without_secure, without_httponly, without_samesite for the cookies set by the final response of the HTTPS home page.
security_txtobjectpresent (has a Contact field), has_contact, has_expires, expired (null when there is no readable Expires date).
errorstringEmpty, or why the domain could not be audited (invalid_url, not_public_address, dns_error, blocked_by_robots, robots_unavailable, internal: ...).
scoreinteger or nullWeb security score 0 to 100; null when robots.txt did not allow reading the headers.
gradestring or nullA+, A, B, C, D or F; null as for score.
email.domainstringThe domain used for the e-mail checks (without www.).
email.mx_countinteger or nullNumber of MX records; null when no DNS resolver answered.
email.spfobjectpresent, records (number of SPF records), all (how the record ends).
email.dmarcobjectpresent, policy, pct, reports, inherited_from (the parent domain whose record applies), invalid (more than one DMARC record).
email_scoreinteger or nullE-mail protection score 0 to 100; null when the DNS answers were not available.
caaobjectpresent and issuers (up to 10 certificate authorities allowed to issue).
findingsarrayEvery check as {check, status, detail, fix}; status is pass, warn, fail or info.

The email and email_score fields are left out when checkEmailDns is off.

Dataset view

The Overview table shows domain, grade, score, email_score, the certificate expiry date, the findings and error, so you can sort a whole portfolio by grade.

How the score works

CheckPointsPartial points
HTTP redirects to HTTPS10
HSTS with max-age of at least 180 days (15,552,000 s)158 for a shorter max-age
Content-Security-Policy without inline scripts158 when it allows inline scripts
Clickjacking protection (frame-ancestors or X-Frame-Options)10
X-Content-Type-Options: nosniff10
Strict Referrer-Policy5
Permissions-Policy5
All cookies with Secure, HttpOnly and SameSite (or no cookies)105 when all have Secure but some lack the others
No software versions in Server or X-Powered-By5
TLS 1.2 or 1.3 and at least 14 days left on the certificate105 when TLS works but the version is older or the certificate expires within 14 days
security.txt with Contact, not expired5

A strict Referrer-Policy is one of no-referrer, same-origin, strict-origin, strict-origin-when-cross-origin, origin or origin-when-cross-origin. If HTTPS does not work at all, the score is 0.

ScoreGrade
95 to 100, with HSTS includeSubDomainsA+
85 to 94 (or 95 and more without includeSubDomains)A
70 to 84B
55 to 69C
40 to 54D
below 40, or no working HTTPSF

E-mail score: one SPF record gives 30 points, plus 20 when it ends with -all or 10 with ~all. A DMARC record gives 30 points, plus 20 for p=reject or 15 for p=quarantine. More than one SPF record counts as none, because receivers ignore them; more than one DMARC record is reported as invalid and scores like no DMARC record.

How much does it cost?

This Actor uses pay-per-event pricing: you pay USD 0.01 per domain audited (USD 10 per 1,000 domains), plus Apify's standard actor start event of USD 0.00005 per run. With pay-per-event pricing the platform usage of the run is included in these prices.

Domains auditedDomain eventsActor startTotal
10USD 0.10USD 0.00005USD 0.10005
100USD 1.00USD 0.00005USD 1.00005
1,000USD 10.00USD 0.00005USD 10.00005
5,000 (the maximum per run)USD 50.00USD 0.00005USD 50.00005

What is charged and what is free:

  • Charged: every domain the audit contacted, whatever the result, including a domain whose robots.txt did not allow reading the headers (the e-mail checks still run).
  • Free: entries that are not valid domains or URLs, hosts that do not resolve, hosts on non-public addresses, and entries that failed with an internal error. They are listed with their error code but not charged.

Set a maximum cost per run and the audit respects it: if your limit covers fewer domains than your list has, only the first ones are audited. Apify's free plan includes monthly platform credit, which you can use to try the Actor.

Tips and best practices

  • Start with the fails. Each finding has a fix. Fixing the fail items first gives the biggest score gains: CSP and HSTS are worth 15 points each.
  • Aim for A+ deliberately. A+ needs at least 95 points and HSTS with includeSubDomains. Add includeSubDomains only when every subdomain serves HTTPS.
  • Monitor certificates. Schedule a daily run and alert when tls.days_left is low; the TLS check already turns to warn below 14 days.
  • Check parked domains too. Domains that never send mail should publish v=spf1 -all and a DMARC record with p=reject; the e-mail score shows which ones do not.
  • Compare apex and www. Headers often differ between example.com and www.example.com; audit both when in doubt.
  • Allow the audit on your own site. It obeys robots.txt rules for the product token HelveticLabs-WebCheck. If your site blocks bots, allow that token to get a grade.

Limitations

  • It is not a penetration test. It shows common best practices that are visible from outside, not vulnerabilities in the application.
  • Home page only. Headers and cookies are read from the home page of each host; other pages may send different headers.
  • robots.txt is respected. When robots.txt disallows the home page, or answers with a server error, the headers are not read: score and grade are null, and the e-mail checks still run.
  • security.txt is read only from /.well-known/security.txt, must be served as text/plain and is read up to 64 KB.
  • TLS is checked with one handshake on port 443 with a timeout of 10 seconds; it does not list every cipher or protocol version the server supports.
  • SPF is checked for presence, count and its all ending; include: chains and the DNS lookup limit are not evaluated, and a record that ends with redirect= is shown as having no all.
  • DMARC for subdomains walks up to four parent names, never to the top-level domain.
  • Only public addresses are contacted; up to 5,000 entries per run.

FAQ

Is it legal to use? The audit only reads what every browser and mail server sees: public headers, the certificate and public DNS records. It sends no attacks and probes no paths. Audit only domains you own or may check, and see the fair use rules at the end of this page.

Does it respect robots.txt? Yes. If robots.txt disallows the home page, the headers are not read and the result says so.

Does it store personal data? No. It returns flags, dates and counts. It never returns cookie names or values, the e-mail addresses from DMARC records (it only says whether reports are requested), security.txt contacts or the CAA iodef contact.

How fast is it? Domains are audited in groups of 20 at a time, with at most 10 web requests in flight and a polite pause between requests to the same host. The duration depends on how fast the servers answer.

Can I schedule it? Yes, with a schedule in Apify Console, for example daily for certificate monitoring or monthly for a portfolio review.

Can I use it from Python, JavaScript or the API? Yes, see Integrations below.

Can AI agents use it? Yes, through Apify's MCP server, for example to answer "what is the security grade of these domains and what should we fix first?".

Why was a domain not charged? Entries that are not valid, do not resolve or point to a non-public address are free, as are entries that failed with an internal error.

Why is the grade empty? The site's robots.txt does not allow automated clients on the home page, or answered with a server error. The e-mail checks are still in the result.

How is it different from a one-domain-at-a-time online header checker? It audits thousands of domains in one run, covers headers, TLS, security.txt and e-mail DNS together, gives one consistent grade and returns structured data for spreadsheets, dashboards and automations.

What happens on errors and timeouts? A failed request becomes a finding (for example "HTTPS does not work (timeout)") and the run goes on with the next domain. Results written before a run timeout stay in the dataset.

Integrations

The actor ID is HelveticLabs/security-audit.

Python (pip install apify-client):

from decimal import Decimal
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("HelveticLabs/security-audit").call(
run_input={"domains": ["example.com", "example.org"], "checkEmailDns": True},
max_total_charge_usd=Decimal("1"), # optional spending limit for this run
)
# apify-client 3.x; with older versions use run["defaultDatasetId"]
for item in client.dataset(run.default_dataset_id).iterate_items():
print(item["domain"], item.get("grade"), item.get("email_score"))

JavaScript (npm install apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('HelveticLabs/security-audit').call(
{ domains: ['example.com', 'example.org'], checkEmailDns: true },
{ maxTotalChargeUsd: 1 },
);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) console.log(item.domain, item.grade, item.tls?.days_left);

HTTP API: POST https://api.apify.com/v2/acts/HelveticLabs~security-audit/runs with the input as the JSON body; add maxTotalChargeUsd as a query parameter to cap the cost.

No-code and automation: connect the Actor to Make, Zapier or n8n, or add a webhook that fires when a run finishes, for example to open a ticket when a grade drops or a certificate has fewer than 30 days left.

AI agents (MCP): Apify's MCP server lets AI agents and MCP clients run this Actor as a tool; pass maxTotalChargeUsd in the call options to cap the spend.

ActorWhat it does
URL Status & Redirect CheckerStatus code, redirect chain, final URL and response time for up to 100,000 URLs.
Website Health Audit: Broken Links & SEO CheckerCrawls a site for broken links, redirects and on-page SEO issues.
Sitemap URL Extractor & ValidatorEvery URL from a site's sitemaps, with lastmod dates.
AI Crawler Access CheckerWhich AI bots a site's robots.txt allows, plus llms.txt.

Support and feedback

Questions, wrong results or ideas for further checks? Open an issue in the Issues tab on this Actor's page, or write to contact@helveticlabs.org. Include the run ID if a run is involved.

Provider, privacy and fair use

Provider: HelveticLabs, sole proprietorship of Marvin Krieg, c/o SwissMailBox 170, 12 Rue Le Corbusier, 1208 Genève, Switzerland. E-mail: contact@helveticlabs.org. Imprint: https://www.helveticlabs.org/imprint

Privacy: This Actor runs on the Apify platform, in your Apify account. It processes only the URLs or domains you enter and the public technical data the checked servers return (status codes, headers, certificates, DNS records, sitemap URLs, links). It does not collect personal data: it never stores or returns page text (where a page's HTML is read, it is read in memory only, to find links and measure tags), and it leaves out e-mail addresses, cookie names and values and similar values. Your input and results stay in your Apify account and are stored by Apify under its own terms (https://apify.com/privacy-policy). The provider sees only the usage statistics Apify shows to Actor authors (such as the number of users and runs), not your input or results, unless you share a run for support. Questions about privacy: contact@helveticlabs.org.

Fair use: Check only sites you own or may check. Do not use the results to attack systems or people. The Actor respects robots.txt, identifies itself, and keeps a polite pace per site.

No warranty: The results are automated checks and can be incomplete. They are not a penetration test, legal advice or a compliance certificate.