# Website Security Audit - Headers, SSL & Exposure Scanner (`smart-digital/website-security-vulnerability-audit`) Actor

Scan any website and get a 0-100 security score with the findings behind it: missing HTTP security headers, SSL/TLS issues, exposed files and server banners, CMS admin exposure, each with a severity and a concrete fix.

- **URL**: https://apify.com/smart-digital/website-security-vulnerability-audit.md
- **Developed by:** [My Smart Digital](https://apify.com/smart-digital) (community)
- **Categories:** Developer tools, SEO tools, Automation
- **Stats:** 40 total users, 3 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

Pay per event

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/actors/running/actors-in-store.md#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

## Website Security Audit

Scan a website and get a 0-100 security score with the exact findings behind it: missing or weak HTTP security headers, SSL/TLS configuration, information the server leaks about itself, exposed configuration files, and common risky patterns. Every finding comes with a severity and a concrete fix.

One run audits one URL and returns one JSON record. No login, no setup, no agent to install on the site.

### What you get

Real output, trimmed, for `https://example.com`:

```json
{
  "url": "https://example.com/",
  "title": "Example Domain",
  "timestamp": "2026-08-13T14:58:14.397Z",
  "overallScore": 81.5,
  "headers": {
    "contentSecurityPolicy": { "present": false, "value": "", "hasUnsafeInline": false, "hasUnsafeEval": false, "recommendation": "Add Content-Security-Policy header" },
    "strictTransportSecurity": { "present": false, "maxAge": 0, "includeSubDomains": false, "preload": false },
    "xFrameOptions": { "present": false, "isDeny": false },
    "score": 36,
    "issues": [ "... 10 findings ..." ]
  },
  "ssl": {
    "isHttps": true,
    "certificateValid": true,
    "protocols": { "tls10": false, "tls11": false, "tls12": true, "tls13": false },
    "mixedContent": { "detected": false },
    "score": 95
  },
  "cms": { "adminAccessible": false, "score": 100, "issues": [] },
  "vulnerabilities": { "score": 100, "issues": [] },
  "exposed": {
    "serverVersion": "cloudflare",
    "robotsTxt": { "present": true, "exposesSensitivePaths": false },
    "sitemap": { "present": false, "exposesSensitivePaths": false },
    "score": 90
  },
  "allIssues": [
    {
      "severity": "medium",
      "category": "Exposed Information",
      "title": "Server Version Exposed",
      "description": "Server version is exposed in headers: cloudflare",
      "recommendation": "Hide server version information in HTTP headers to prevent attackers from targeting known vulnerabilities."
    }
  ]
}
```

`allIssues` gathers every finding of the run in one list, sorted by severity (`critical`, `high`, `medium`, `low`, `info`), so you can pipe it straight into a report or a ticket.

### What it checks

**HTTP security headers** — Content-Security-Policy (including `unsafe-inline` and `unsafe-eval` directives), Strict-Transport-Security (with `max-age`, `includeSubDomains`, `preload`), X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy, Permissions-Policy, and the three Cross-Origin policies (COEP, COOP, CORP). Each header is reported present or absent, with its value and what to set.

**SSL/TLS** — HTTPS in use, certificate validity, mixed content on the page, and the TLS versions observed during the audit.

**Exposed information** — server and technology banners returned in headers, error messages that reveal the stack, `robots.txt` and sitemap analysed for sensitive paths, and directory listings left enabled.

**CMS-side exposure** — reachable admin panels (`/wp-admin/`, `/admin`), sensitive files served over HTTP (`.env`, `.git/config`, `wp-config.php`, `config.php`, `configuration.php`, `.htaccess`), WordPress REST API user enumeration, and CMS version numbers left in the page source.

**Risky patterns** — login pages exposed without protection, forms without CSRF tokens, unprotected API endpoints, and injection-prone patterns in the page. These are pattern checks, not exploitation attempts: nothing is ever sent to break the target.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `startUrl` | string | `https://example.com` | URL to audit |
| `timeout` | integer | `30000` | Page load timeout, in milliseconds (5000-120000) |
| `checkHeaders` | boolean | `true` | Run the security headers checks |
| `checkSSL` | boolean | `true` | Run the SSL/TLS checks |
| `checkCMS` | boolean | `true` | Run the CMS exposure checks |
| `checkVulnerabilities` | boolean | `true` | Run the risky pattern checks |
| `checkExposed` | boolean | `true` | Run the information disclosure checks |
| `userAgent` | string | `Mozilla/5.0 (compatible; Security-Audit/1.0)` | User agent sent to the site |

Turning a section off skips its requests, which makes the run faster on large sites.

```json
{
  "startUrl": "https://example.com/",
  "timeout": 30000,
  "checkHeaders": true,
  "checkSSL": true,
  "checkCMS": true,
  "checkVulnerabilities": true,
  "checkExposed": true
}
```

### How the score works

`overallScore` is a weighted average of the five section scores, each starting at 100 and losing points per finding: headers 25%, SSL/TLS 30%, CMS 15%, risky patterns 20%, exposed information 10%. A site with clean headers and a valid certificate typically lands between 85 and 100; a site missing CSP, HSTS and X-Frame-Options drops to the low 80s or below.

### Limits, stated up front

- **One URL per run.** The Actor audits the page you give it, not the whole site. To cover several pages, run it once per URL.
- **No vulnerability database.** Findings come from what the site exposes over HTTP, not from CVE, WPScan or any advisory feed. A plugin with a known CVE will not be flagged as such.
- **No exploitation.** Nothing is injected, brute-forced or logged into. This is an exposure audit, not a penetration test, and it does not replace one.
- **The `cms.cms` label is a best-effort guess** from page signatures and can be wrong on sites that mix technologies. The CMS checks themselves (admin panel, sensitive files, REST API, version disclosure) run regardless of the label.
- **TLS versions are observed, not probed.** When they cannot be confirmed, the Actor says so in an `info` finding rather than guessing.
- **Pages behind a login or a strict bot protection** cannot be audited.

### Good uses

Pre-launch checks before a site goes live, a recurring security posture check on the sites you maintain, a quick exposure report for a client or a prospect, and scoring a batch of domains by running the Actor once per URL from your own script.

### Support

Found a wrong result or a site that fails? Open an issue on the Actor page with the URL and the run ID — that is the fastest way to get it fixed.

# Actor input Schema

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

URL of the website to audit (required)

## `timeout` (type: `integer`):

Timeout for page load in milliseconds

## `checkHeaders` (type: `boolean`):

Audit HTTP security headers (CSP, HSTS, X-Frame-Options, etc.)

## `checkSSL` (type: `boolean`):

Audit SSL certificate and TLS configuration

## `checkCMS` (type: `boolean`):

Detect CMS and check for CMS-specific security issues

## `checkVulnerabilities` (type: `boolean`):

Scan for common vulnerabilities (SQL injection, XSS, CSRF, etc.)

## `checkExposed` (type: `boolean`):

Check for exposed information (versions, error messages, sensitive files)

## `userAgent` (type: `string`):

User agent string to use for requests

## Actor input object example

```json
{
  "startUrl": "https://example.com/",
  "timeout": 30000,
  "checkHeaders": true,
  "checkSSL": true,
  "checkCMS": true,
  "checkVulnerabilities": true,
  "checkExposed": true,
  "userAgent": "Mozilla/5.0 (compatible; Security-Audit/1.0)"
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("smart-digital/website-security-vulnerability-audit").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("smart-digital/website-security-vulnerability-audit").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 '{}' |
apify call smart-digital/website-security-vulnerability-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,smart-digital/website-security-vulnerability-audit"
        }
    }
}

```

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/NTqvfckeGX4hsFvu2/builds/TN5y6kFE3sW9juvfP/openapi.json
