# Website SEO Audit & Checker: 0-100 Score + Client Report (`pewterdesk/website-audit-report`) Actor

SEO audit and website checker in one: a 0-100 score for SEO, speed, security, accessibility and email/DNS health, a prioritized fix list and a white-label HTML report for clients. Audit sites in bulk, no API key needed. Unreachable sites are free.

- **URL**: https://apify.com/pewterdesk/website-audit-report.md
- **Developed by:** [PewterDesk](https://apify.com/pewterdesk) (community)
- **Categories:** SEO tools, Lead generation, Developer tools
- **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

## Website SEO Audit & Checker: 0-100 Score + Client Report

**Website SEO audit tool and site checker** for agencies and freelancers: run an SEO audit on one site or hundreds and get a score, a fix list and a client-ready report.&#x20;

Audit one website or hundreds in a single run. For every site you get a **0–100 score**, a **grade (A–F)**, **five category scores**, a **prioritized fix list** in plain English, and a **white-label HTML report** you can send to a client or save as PDF.

Built for **agencies, freelancers and consultants who sell website audits**, for **prospecting** ("your site scores 58/100, here are the 3 fixes"), and for **monitoring client sites** on a schedule.

**No API key needed.** Sites that can't be audited are **free**.

### What you get for each site

| Category | Weight | What's checked |
|---|---|---|
| **SEO** | 30% | Title and meta description (presence and length), H1, noindex, canonical, mobile viewport, robots.txt, XML sitemap (auto-discovered), http/https and www/non-www consolidation, **broken internal links**, **sitemap URLs that redirect or 404**, duplicate or missing titles across sampled pages, structured data (schema.org), Open Graph, thin content |
| **Performance** | 25% | Server response time (TTFB), gzip/Brotli compression, render-blocking scripts, HTML weight, script and stylesheet count, image dimensions (layout shift), lazy loading. **With your free Google key:** Lighthouse performance score, real-user **Core Web Vitals** (LCP, INP, CLS) and Lighthouse's top opportunities |
| **Security** | 20% | HTTPS, HTTP→HTTPS redirect, valid SSL certificate, **days until certificate expiry**, TLS version, HSTS, CSP, clickjacking protection, nosniff, Referrer-Policy, **mixed content**, software versions leaked in headers |
| **Accessibility** | 15% | Page language, image alt text, form labels, links and buttons with no accessible name, zoom disabled, page title (homepage plus sampled pages). With a Google key, the Lighthouse accessibility score is added too |
| **Email & domain** | 10% | **SPF** and **DMARC** (spoofing and deliverability), DMARC enforcement and reporting, CAA, and **domain expiry** from the official RDAP registry |

Each report also lists **site facts**, which make good sales openers: the detected **tech stack** (CMS, e-commerce platform, analytics, CDN, and 135+ other technologies), the email provider, DNS provider, registrar, domain age, social profiles, whether the site has an `llms.txt`, and which **AI crawlers** (GPTBot, ClaudeBot, PerplexityBot, Google-Extended and others) its robots.txt blocks.

#### The fix list

Every failed check becomes a fix with a **severity** (critical, high, medium or low), an **effort** estimate, the **affected URLs** and **a concrete instruction**, such as "Send 'Strict-Transport-Security: max-age=31536000; includeSubDomains'". Fixes are ranked by impact, and quick wins go first when the impact is equal. A rule-based executive summary is always included, so no AI is required.

#### White-label HTML report

Each site gets its own report in the run's key-value store (`report-<host>`), with a link in the dataset row. Runs with several sites also get a **comparison table** (`REPORT`), which is useful for "you vs. your 3 competitors" pitches. Add your **agency name, brand color and logo** in the input. The report is self-contained and print-friendly, so you can open it and use *Save as PDF*.

### Input example

```json
{
  "urls": ["acme-plumbing.com", "https://www.competitor-one.com/", "competitor-two.com"],
  "maxPagesPerSite": 10,
  "checkBrokenLinks": true,
  "agencyName": "Bright Pixel Studio",
  "brandColor": "#7c3aed",
  "logoUrl": "https://brightpixel.example/logo.png"
}
```

Optional settings:

- **`googleApiKey`**: adds Lighthouse and Core Web Vitals (one PageSpeed call per site). The key is free, gives you 25,000 requests a day, and takes 2 minutes to create: in Google Cloud Console, open **APIs & Services → Library**, enable **PageSpeed Insights API**, then go to **Credentials → Create API key**. It's stored encrypted.
- **`aiSummary`** (off by default): a client-friendly AI-written summary using **your own** OpenAI, Anthropic or OpenAI-compatible key (OpenRouter, Groq and others). Only scores and the fix list are sent, never page content. If the call fails, you still get the rule-based summary.

### Output (shortened)

```json
{
  "finalUrl": "https://basecamp.com/",
  "overallScore": 86,
  "grade": "B",
  "scores": { "seo": 87, "performance": 86, "security": 80, "accessibility": 82, "emailDomain": 96 },
  "summary": "basecamp.com scores 86/100 (grade B). Strongest area: Email & domain (96). Weakest area: Security (80). 11 issues found, 1 of them high or critical priority. Top fixes: 1) Sitemap pages are indexable; 2) HSTS header; 3) Form fields have labels.",
  "topFixes": [
    { "priority": 1, "severity": "high", "issue": "Sitemap pages are indexable",
      "detail": "1 sampled page(s) listed in the sitemap carry noindex.",
      "fix": "Either remove noindex or drop those URLs from the sitemap; the two signals contradict each other.",
      "affected": ["https://basecamp.com/2"] },
    { "priority": 2, "severity": "medium", "issue": "HSTS header", "fix": "Send 'Strict-Transport-Security: max-age=31536000; includeSubDomains'." }
  ],
  "topFixesText": "1. Sitemap pages are indexable | 2. HSTS header | 3. Form fields have labels | …",
  "reportUrl": "https://api.apify.com/v2/key-value-stores/…/records/report-basecamp.com",
  "site": { "technologies": [{ "name": "Cloudflare", "category": "CDN" }], "aiCrawlers": { "GPTBot": "allowed" } },
  "emailDomain": { "securityGrade": "B", "dmarcPolicy": "quarantine", "registrar": "Cloudflare, Inc." }
}
```

See `sample_output.json` for a full row. Every check is also listed with its status, weight and details, so the score is fully explainable. The dataset's **Overview** table (site, scores, top fixes, report link) exports cleanly to CSV, Excel or Google Sheets for mail merges.

### Pricing

**$0.02 per site audited**, which includes the homepage, up to 25 sampled pages, the link check, DNS, SSL and registry lookups, and the HTML report. Volume tiers bring it down to $0.01.

**Free:** sites that are unreachable, blocked by bot protection (HTTP 403/429/503), disallowed by robots.txt, invalid input lines and duplicates. Set a maximum cost per run and the Actor stops cleanly at your limit.

### Use cases

- **Sell audits.** Run a prospect's site, attach the branded HTML report, and quote the fixes.
- **Cold outreach at scale.** Audit 500 local businesses and sort by score. Use `topFixesText` as a personalised first line.
- **Competitor benchmarks.** Put your client and 3–5 competitors in one run to get a comparison table.
- **Client retainers.** Schedule a monthly run per client and show the score improving.
- **Pre-launch QA.** Catch noindex, broken links, mixed content and a missing sitemap before go-live.

### How it works

The Actor fetches robots.txt, the homepage and the sitemap, then samples pages spread across site sections and HEAD-checks internal links. It also runs public DNS, RDAP and TLS lookups. **It respects robots.txt by default**, sends a clearly identified user agent, never logs in, and **doesn't collect personal data**. The work runs on a handful of polite parallel requests per site, and a typical site takes 5–20 seconds.

### FAQ

**Is this a replacement for Lighthouse?** It's broader: it covers SEO, security headers, SSL, email and domain health, and multi-page sampling. Add your Google key to include Lighthouse and Core Web Vitals as well. Without the key, performance is scored with fast server-side checks.

**Is the accessibility score a WCAG audit?** No. It runs automated heuristics that catch common, high-impact problems. Treat it as a screening tool, not a compliance certificate.

**Why does a JavaScript-heavy site show low word count?** The Actor reads the HTML that the server returns, as most crawlers first do. Content rendered only in the browser isn't counted.

**Can I change the weights?** Every check's raw result is in the `checks` array, so you can re-weight it in a spreadsheet. Configurable weights are on the roadmap. Requests are welcome in the **Issues** tab.

***

Built by **PewterDesk** ([pewterdesk.pages.dev](https://pewterdesk.pages.dev)). We also make [Bulk PageSpeed & Core Web Vitals](https://apify.com/pewterdesk/bulk-pagespeed-core-web-vitals), [Bulk Domain Intel](https://apify.com/pewterdesk/bulk-domain-intelligence) and [Sitemap URL Inventory](https://apify.com/pewterdesk/sitemap-url-inventory-diff).

# Actor input Schema

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

One site per line: domains (acme.com) or URLs (https://www.acme.com/). Each site gets its own scored report. Duplicates and invalid lines are skipped and never charged.

## `maxPagesPerSite` (type: `integer`):

Besides the homepage, this many pages are sampled from the sitemap (spread across site sections) and checked for titles, descriptions, H1s, alt text and status codes. Same price whatever you choose.

## `checkBrokenLinks` (type: `boolean`):

HEAD-request internal links found on the homepage to find 404s and server errors.

## `maxLinksPerSite` (type: `integer`):

Upper limit on internal links checked per site.

## `includeEmailDomainChecks` (type: `boolean`):

Public DNS and RDAP registry lookups: email spoofing protection, DMARC policy, CAA and domain expiry.

## `agencyName` (type: `string`):

Shown as 'Prepared by …' on every HTML report (white-label). Leave empty for an unbranded report.

## `brandColor` (type: `string`):

Hex color for report accents, e.g. #2f6fed.

## `logoUrl` (type: `string`):

Optional https:// link to your logo, shown in the report header.

## `googleApiKey` (type: `string`):

Adds Lighthouse scores and real-user Core Web Vitals (one PageSpeed call per site). Free key, 25,000 requests/day: see README. Without it, performance is scored from fast built-in checks (server response time, compression, render-blocking scripts, page weight).

## `pageSpeedStrategy` (type: `string`):

Device used for the Lighthouse run when a Google key is given.

## `aiSummary` (type: `boolean`):

Off by default. Every report already includes a rule-based summary and fix list at no extra cost. Turn on to add a client-friendly AI-written summary using your own OpenAI, Anthropic or OpenAI-compatible key. Only scores and the fix list are sent, never page content.

## `llmProvider` (type: `string`):

Which API your key belongs to. OpenAI-compatible covers OpenRouter, Groq, Together, local servers and similar.

## `llmApiKey` (type: `string`):

Your own key. Stored encrypted, never logged or written to the output.

## `llmModel` (type: `string`):

Optional. Defaults: gpt-4o-mini (OpenAI), claude-3-5-haiku-latest (Anthropic). Required for OpenAI-compatible.

## `llmBaseUrl` (type: `string`):

e.g. https://openrouter.ai/api/v1

## `respectRobotsTxt` (type: `boolean`):

Skip pages the site's robots.txt disallows. A site whose homepage is disallowed is skipped and not charged.

## `maxConcurrency` (type: `integer`):

Each site uses a handful of polite parallel requests.

## `maxSites` (type: `integer`):

Optional cap on how many sites from the list are audited.

## `dnsMode` (type: `string`):

auto = system DNS with DNS-over-HTTPS fallback. Usually leave on auto.

## Actor input object example

```json
{
  "urls": [
    "https://www.python.org/"
  ],
  "maxPagesPerSite": 10,
  "checkBrokenLinks": true,
  "maxLinksPerSite": 30,
  "includeEmailDomainChecks": true,
  "pageSpeedStrategy": "mobile",
  "aiSummary": false,
  "llmProvider": "openai",
  "respectRobotsTxt": true,
  "maxConcurrency": 3,
  "dnsMode": "auto"
}
```

# Actor output Schema

## `htmlReport` (type: `string`):

White-label HTML report (comparison table when several sites were audited). Per-site reports are linked from each dataset row (reportUrl).

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

One scored audit per site: overall and category scores, prioritized fix list, site facts (default dataset).

## `runSummary` (type: `string`):

Counts for this run (processed, failed, stopped at spending limit) as JSON.

# 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://www.python.org/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pewterdesk/website-audit-report").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://www.python.org/"] }

# Run the Actor and wait for it to finish
run = client.actor("pewterdesk/website-audit-report").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://www.python.org/"
  ]
}' |
apify call pewterdesk/website-audit-report --silent --output-dataset

```

## MCP server setup

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

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/1kTTmQyHvzJNZsavo/builds/RdwlpecqAeVPsTZzx/openapi.json
