# SSL Certificate & Security Headers Checker (`zaden/my-actor-4`) Actor

Checks TLS certificate validity and expiry plus HTTP security headers (HSTS, CSP, X-Frame-Options, and more) for any URL. Fast, no browser needed.

- **URL**: https://apify.com/zaden/my-actor-4.md
- **Developed by:** [Zaden](https://apify.com/zaden) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 host checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## SSL Certificate & Security Headers Checker

A fast, no-browser check of your TLS certificate and HTTP security posture. Point it at one or more URLs and get back certificate expiry, validity, and which of the standard security headers (HSTS, CSP, X-Frame-Options, and more) are actually present -- plus a **letter grade**, a 0-100 score, a severity tag, and a plain-English issue list.

### What you get, per URL

- A **letter grade (A+ to F)** and 0-100 score summarizing security posture at a glance
- A one-line **executive summary** ("3 issue(s) found -- review recommended")
- A **severity** tag -- `critical` (no HTTPS, invalid/expired cert, or expiring within 7 days), `warning` (header gaps or other issues), or `ok` -- for instant triage
- **Certificate validity and trust** -- whether the certificate is trusted by standard root CAs, its issuer, subject, and validity window
- **Days until expiry** -- so you can catch a renewal before it lapses, not after
- **HTTP-to-HTTPS redirect check** -- confirms plain `http://` traffic is actually redirected to `https://`
- **Security header presence**: `Strict-Transport-Security` (HSTS), `Content-Security-Policy`, `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, `Permissions-Policy`
- Hosts are checked **in parallel** (configurable, up to 20 at once), so a batch of 50 URLs finishes in a fraction of the time a one-by-one check would take

### Why this instead of checking manually

| | Manual spot-checks | SSL & Security Headers Checker |
|---|---|---|
| Coverage | One host at a time, in a browser dev tools panel | Every host you list, automatically |
| Speed | Minutes per host | Seconds, via parallel checking |
| Triage | You read raw headers yourself | Pre-classified severity + letter grade |
| Repeatability | Forgotten until the cert expires | One click, or schedule it |
| Output | Screenshots or notes | Structured dataset, exportable to CSV/JSON/BI tools |

### Who this is for

- Developers and DevOps engineers doing a pre-launch or periodic security sanity check
- Anyone who's been burned by an expired certificate taking a site down unexpectedly
- Agencies auditing a client's sites for basic security hygiene
- Teams wiring a certificate-expiry or header-regression check into a scheduled monitor

### How to use it

1. Add one or more **URLs to check**.
2. Adjust **warn if certificate expires within (days)** if you want an earlier or later heads-up than the 30-day default.
3. Tune **concurrency** (default 5) to trade speed for gentleness on slow or rate-limited servers.
4. Run it once for a snapshot, or put it on an Apify **Schedule** so you get advance warning before a certificate expires or a security header regresses.

### Example output (one item)

```json
{
  "url": "https://example.com/",
  "finalUrl": "https://example.com/",
  "statusCode": 200,
  "score": 40,
  "grade": "F",
  "severity": "warning",
  "summary": "6 issue(s) found -- review recommended.",
  "issueCount": 6,
  "issues": [
    "TLS certificate expires in 45 day(s).",
    "Missing Strict-Transport-Security (HSTS) header.",
    "Missing Content-Security-Policy header.",
    "Missing X-Content-Type-Options header.",
    "Missing X-Frame-Options header (clickjacking protection).",
    "Missing Referrer-Policy header."
  ],
  "usesHttps": true,
  "certValid": true,
  "certIssuer": "DigiCert Inc",
  "certDaysRemaining": 45,
  "hsts": false,
  "csp": false,
  "checkedAt": "2026-08-22T00:00:00.000Z"
}
```

### Pricing

This Actor uses pay-per-event pricing:

- **Host checked** -- charged once per URL processed, whether the check succeeded or the connection failed (a failed connection is still a useful signal -- your certificate or server may be down).

Parallel checking doesn't cost more -- it just finishes faster.

### FAQ

**How does this read the certificate without a browser?**
It opens a raw TLS connection to the host (the same handshake a browser performs) using Node's built-in TLS module, and reads the certificate the server presents -- no headless browser needed, which keeps this fast and cheap to run.

**Does it check the full certificate chain?**
It reports on the trust result reported by Node's TLS stack against standard root certificate authorities, plus the leaf certificate's issuer, subject, and validity window. It does not enumerate every intermediate certificate individually.

**What makes something "critical" vs. a "warning"?**
`critical` covers anything that puts the site itself at risk right now: no HTTPS at all, an invalid or untrusted certificate, or a certificate expiring within 7 days. `warning` covers everything else that lowers the score, most commonly missing security headers -- worth fixing, but not an active outage risk.

**Will higher concurrency get me rate-limited?**
It can, on servers or WAFs with aggressive rate limiting. Start at the default (5) and lower it if you see timeouts spike for a particular host.

**Is the score a substitute for a full security audit?**
No. It's a fast, transparent first-pass signal covering certificate health and the most common security headers. A full security review also covers things like TLS protocol/cipher configuration, cookie flags, CORS policy, and application-level vulnerabilities, which are out of scope here by design.

**Does this send any data anywhere besides your own Apify account?**
No. It only opens standard TLS connections and HTTP requests to the URLs you provide and returns what it finds -- no login, no third-party analytics calls.

# Actor input Schema

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

One or more URLs. The TLS certificate and HTTP security headers of each host are checked once.

## `warnDaysBeforeExpiry` (type: `integer`):

Certificates expiring sooner than this many days from now are flagged as an issue.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for the TLS handshake and HTTP response before giving up.

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

How many hosts to check in parallel. Higher values finish faster at the same cost; lower values are gentler on slow or rate-limited servers.

## Actor input object example

```json
{
  "urls": [
    "https://example.com/"
  ],
  "warnDaysBeforeExpiry": 30,
  "requestTimeoutSecs": 10,
  "concurrency": 5
}
```

# Actor output Schema

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

TLS certificate details and security header presence for each checked URL.

# 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": [
        "https://example.com/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zaden/my-actor-4").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": ["https://example.com/"] }

# Run the Actor and wait for it to finish
run = client.actor("zaden/my-actor-4").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": [
    "https://example.com/"
  ]
}' |
apify call zaden/my-actor-4 --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zaden/my-actor-4"
        }
    }
}

```

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/W0e6lw2QQdp5ckDMv/builds/6qg3DOnqgmsmMpNSD/openapi.json
