# Website Audit: SEO, Lighthouse, Accessibility, Security, Links (`webskan/website-audit`) Actor

Deterministic technical audit of a public website: per-page SEO checks, Lighthouse (mobile + desktop), axe-core accessibility, security headers and TLS, robots/sitemap, broken links and customer-journey checks. One dataset item per finding, JSON + HTML report in the key-value store. By Webskan.

- **URL**: https://apify.com/webskan/website-audit.md
- **Developed by:** [webskan](https://apify.com/webskan) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.05 / audit completed

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?

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

## Website Audit – SEO, Lighthouse, Accessibility, Security & Broken Links

Audit any public website in one run and get a prioritised list of concrete findings. The Actor crawls up to 30 pages, checks each page's SEO, runs Lighthouse (mobile and desktop) on the home page, tests accessibility with axe-core, inspects security headers and TLS, finds broken links, and walks through typical customer journeys (404 page, mobile menu, site search, contact forms, product → cart → checkout).

Every check is **automated and deterministic** – no language model is involved. The same site audited twice gives the same findings, and every finding has a **stable `id`**, so you can diff audits over time or re-check a site after fixes.

Built and maintained by [Webskan](https://webskan.com). Developers: the same engine is available as an MCP server, see [webskan.com/developers](https://webskan.com/developers/).

### What it checks

About 70 distinct finding types in seven categories:

- **Security (`sec`)** – TLS validity and expiry, http → https and www redirects, missing security headers (HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy), version-leaking headers, publicly exposed files that should never be in the web root (`.git`, `.env`, `wp-config` backups, SQL dumps, backup archives, phpinfo, PHP logs, Adminer – content-signature checked, so soft-404 pages do not trigger it), mixed content, forms posting over http.
- **Performance (`perf`)** – Lighthouse mobile score, LCP, CLS, TBT, page weight, heaviest scripts, render-blocking scripts, Lighthouse opportunities with estimated savings, oversized images, images without dimensions, slow server response, missing compression.
- **SEO (`seo`)** – missing, too long or duplicate titles and meta descriptions, H1 problems, `noindex`, robots.txt and sitemap issues, canonical problems, missing Open Graph, invalid JSON-LD, missing structured data, missing `lang` or viewport, zoom disabled – for every crawled page.
- **Accessibility (`a11y`)** – axe-core (WCAG 2.0/2.1 A + AA and best-practice rules) on the key pages, home page in light and dark colour schemes, with sample selectors per rule; plus the Lighthouse accessibility score.
- **Mobile UX (`ux`)** – cookie banner covering the page or without a reject button, horizontal overflow, small text, JavaScript errors, failed requests, non-clickable phone numbers and e-mails, contact-form problems (too many fields, unlabelled fields, no validation, no spam protection, no data-processing notice).
- **Customer journeys (`journey`)** – soft 404s and dead-end 404 pages, mobile menu that does not open, broken site search, and for shops: product → cart → checkout (guest checkout? payment methods visible? form length?). No order is ever placed.
- **Links (`links`)** – up to 500 internal and external links checked; broken links report the status and the pages they were found on.

The Actor also detects the platform (WordPress, Shopify, WooCommerce, Webflow, …) and records Lighthouse metrics (FCP, LCP, TBT, CLS, Speed Index, TTI) for mobile and desktop.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `url` | string | – | Public website to audit, e.g. `https://example.com`. Localhost and private networks are rejected. |
| `maxPages` | integer 1–30 | `10` | Pages to crawl and analyse (home page included), picked from home-page links and the sitemap, preferring key pages (contact, pricing, shop, product, blog…). |
| `lighthouse` | boolean | `true` | Run Lighthouse mobile + desktop on the home page. |
| `language` | `en` / `pl` | `en` | Language of findings and the HTML report. |

### Output

**Dataset** – one item per finding, sorted by severity (`high`, `medium`, `low`, `info`):

```json
{
  "id": "sec.header.hsts",
  "severity": "medium",
  "category": "sec",
  "title": "Missing Strict-Transport-Security (HSTS) header",
  "description": "The browser does not know it should always use https; a connection-downgrade attack is possible on the first visit.",
  "fix": "Add the \"strict-transport-security\" HTTP response header to every response.",
  "pages": []
}
```

`id` is stable between runs (per-page findings carry the page path after `@`, e.g. `seo.desc.missing@/contact`). `description` contains the explanation and the recommended fix; `fix` is set when the engine has a separate one-line hint, otherwise `null`. `pages` lists affected URLs when a finding spans several pages.

**Key-value store**

- `SUMMARY` (JSON) – pages crawled, links checked, findings by severity and category, Lighthouse scores and metrics, axe results per page, TLS status, per-step timings, step errors.
- `REPORT` (JSON) – the full raw engine report (per-page SEO data, headers, Lighthouse details, axe violations with sample nodes, journey results).
- `REPORT_HTML` – a self-contained HTML report with findings, scores, link check, accessibility details and mobile screenshots of the key pages.

### Pricing (pay per event)

The Actor uses pay-per-event pricing: you pay only for the events below, and Apify platform usage (compute, proxy, storage) is included – there is no separate usage charge. The current price is always the one shown on this Actor's page in Apify Store.

| Event | Price | When |
|---|---|---|
| `page-audited` | $0.02 | per crawled and analysed page |
| `lighthouse-audit` | $0.10 | per Lighthouse run pair (mobile + desktop) on the home page |
| `audit-completed` | $0.05 | once, when findings and reports are saved |

Example – a 10-page audit with Lighthouse: 10 × $0.02 + $0.10 + $0.05 = **$0.35**. A 30-page audit costs $0.75; a 3-page audit without Lighthouse $0.11. Platform usage is included in these prices.

If a run's spending limit is reached, the Actor stops gracefully: it never crawls more pages than it can charge, skips Lighthouse if the limit does not cover it, and still saves the findings it has.

### Limits and notes

- Maximum 30 pages per run; public websites only.
- Lighthouse runs on the home page only. Typical run time: about 1 minute for 3 pages, 3–6 minutes for 10–30 pages.
- Sites that block headless browsers may give partial results; `SUMMARY.errors` lists failed steps.
- Automated testing finds roughly 30–40 % of WCAG barriers – treat `a11y` findings as a starting point.
- Recommended memory: 4 GB.

Questions or bugs: [webskan.com](https://webskan.com) or the Issues tab of this Actor.

# Actor input Schema

## `url` (type: `string`):

Public website to audit, e.g. https://example.com. The crawl stays on this host (www and non-www are treated as the same site). Localhost and private networks are rejected.

## `maxPages` (type: `integer`):

How many pages to crawl and analyse (home page included). Each page is billed as one page-audited event.

## `lighthouse` (type: `boolean`):

Run Lighthouse (mobile + desktop) on the home page: performance, Core Web Vitals, accessibility, best practices, SEO scores. Billed as one lighthouse-audit event. Adds roughly 1–2 minutes.

## `language` (type: `string`):

Language of finding titles, descriptions and the HTML report.

## Actor input object example

```json
{
  "url": "https://example.com",
  "maxPages": 10,
  "lighthouse": true,
  "language": "en"
}
```

# Actor output Schema

## `findings` (type: `string`):

One item per finding: id, severity, category, title, description, fix, pages.

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

Scores, metrics, counts and timings of the audit.

## `reportHtml` (type: `string`):

Human-readable report with all findings.

## `report` (type: `string`):

Complete engine output used to compute the findings.

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

// Run the Actor and wait for it to finish
const run = await client.actor("webskan/website-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 = { "url": "https://example.com" }

# Run the Actor and wait for it to finish
run = client.actor("webskan/website-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 '{
  "url": "https://example.com"
}' |
apify call webskan/website-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,webskan/website-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/RrC1sKIG6wgyS6rAu/builds/gFoiBf4dFJF8o7C6a/openapi.json
