# SEO Audit Crawler & Website SEO Checker (`goldish_fireplace/seo-audit-crawler`) Actor

Technical SEO site audit for whole websites: missing or duplicate titles and meta descriptions, H1s, canonicals, noindex, thin content, alt text. Score per page.

- **URL**: https://apify.com/goldish_fireplace/seo-audit-crawler.md
- **Developed by:** [goldish_fireplace](https://apify.com/goldish_fireplace) (community)
- **Categories:** SEO tools, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 page auditeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## SEO Audit Crawler: Website SEO Checker & Technical Site Audit Tool

**Run a full technical SEO site audit online, with no software to install.** This SEO checker crawls every page of a website and finds missing or duplicate title tags and meta descriptions, missing H1s, wrong canonicals, accidental noindex, thin content, missing alt text and missing structured data. You get a 0 to 100 SEO score per page, a site-wide score and a client-ready HTML report.

**SEO Audit Crawler** crawls an entire website and runs a **technical on-page SEO audit on every page**. In seconds you get a 0–100 SEO score for each page, a clear list of issues with fix hints, and a site-wide summary showing what to fix first.

It's a fast, low-cost alternative to desktop SEO spiders and expensive SaaS site audits. It fetches plain HTML over HTTP with no headless browser, so a 500-page audit costs cents, not dollars.

### What does SEO Audit Crawler check?

For **every page** it finds by following internal links:

| Area                       | Checks                                                                                                                                                                      |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Titles**                 | Missing title, too long (>60 chars), too short (<30), multiple title tags, **duplicate titles across the site**                                                             |
| **Meta descriptions**      | Missing, too long (>160), too short (<70), **duplicate descriptions**                                                                                                       |
| **Headings**               | Missing H1, multiple H1s, duplicate H1s, H2 count                                                                                                                           |
| **Indexability**           | HTTP status (404s, 5xx), `noindex` in meta robots **and** the `X-Robots-Tag` header, page-level `nofollow`, canonical tag missing, invalid or pointing elsewhere, redirects |
| **Content**                | Visible word count, thin content (<200 words), images missing alt text                                                                                                      |
| **Mobile & i18n**          | Viewport meta tag, `<html lang>`, hreflang alternates                                                                                                                       |
| **Social & rich results**  | Open Graph (og:title, og:image, og:description), Twitter card, **schema.org structured data types** (JSON-LD and microdata), invalid JSON-LD                                |
| **Performance & security** | Server response time, HTML size, HTTPS                                                                                                                                      |
| **Links**                  | Internal, external and nofollow link counts, dead-end pages with no internal links                                                                                          |

Every issue has a **severity** (critical, warning or notice) and a plain-English message. Pages get a **score from 0 to 100**, and the whole site gets an average score.

### Why use it?

- 🔎 **Find what's hurting rankings**: missing titles, duplicate content, accidental `noindex`, broken pages and wrong canonicals.
- ⚡ **Fast and cheap**: HTTP-only crawling (no browser). Hundreds of pages per minute.
- 🖥️ **Client-ready HTML report**: open the **HTML report** in the Output tab for the site score, issues ranked by importance and every page sorted worst first. Share it as is.
- 📊 **Ready for spreadsheets**: one row per page. Export to CSV, Excel, JSON or Google Sheets, or pull results through the API.
- 🔁 **Schedule it**: run weekly and catch SEO regressions after every deploy.
- 🤝 **Agencies & freelancers**: audit client and prospect sites in bulk. Use several start URLs to audit many sites in one run.

### How to use SEO Audit Crawler

1. Enter your website's homepage in **Website URLs**.
2. Set **Max pages to audit** (this also caps your cost).
3. Click **Start**. When the run finishes, open the **Output** tab to see every page, or open the **Summary** for the site score, top issues and worst pages.

### Input example

```json
{
    "startUrls": [{ "url": "https://example.com/" }],
    "maxPagesToCrawl": 500,
    "maxDepth": 20,
    "outputMode": "all",
    "excludeUrlPatterns": ["/tag/", "\\?page="]
}
```

Set `outputMode` to `"issues"` to output only pages with critical issues or warnings.

### Output example

One dataset item per page:

```json
{
    "url": "https://example.com/pricing",
    "statusCode": 200,
    "indexable": true,
    "score": 82,
    "issueCount": 3,
    "issues": [
        {
            "code": "DUPLICATE_TITLE",
            "severity": "warning",
            "message": "Same title as 2 other page(s): https://example.com/plans, https://example.com/buy"
        },
        { "code": "IMAGES_MISSING_ALT", "severity": "warning", "message": "3 of 12 image(s) have no alt text." },
        {
            "code": "MISSING_OPEN_GRAPH",
            "severity": "notice",
            "message": "Missing og:title or og:image: links shared on social media will look plain."
        }
    ],
    "title": "Pricing | Example",
    "titleLength": 17,
    "metaDescription": "Simple, transparent pricing for teams of every size...",
    "metaDescriptionLength": 128,
    "h1": "Pricing",
    "h1Count": 1,
    "canonical": "https://example.com/pricing",
    "canonicalIsSelf": true,
    "wordCount": 640,
    "imagesMissingAlt": 3,
    "internalLinks": 48,
    "externalLinks": 5,
    "structuredDataTypes": ["Organization", "WebPage"],
    "responseTimeMs": 212,
    "pageSizeKb": 84.1,
    "depth": 1
}
```

The **SUMMARY** record in the key-value store holds the site score, the number of indexable, error and non-indexable pages, **each issue type with how many pages it affects** (and example URLs), and the 10 worst pages.

### How much does it cost?

You pay a small fixed amount **per page audited** (see the **Pricing** tab). Platform compute is included, so there are no surprise usage costs. Pages that aren't HTML (PDFs, images) are skipped and not charged.

| What you audit | Pages | Cost |
| --- | --- | --- |
| Landing site | 20 | 20 × price per page |
| Small business site | 100 | 100 × price per page |
| Blog or shop | 1,000 | 1,000 × price per page |
Set **Max pages to audit** or a maximum cost per run, and the crawler stops before going over your budget. Platform usage is minimal because no browser is used.

### Issue codes

`HTTP_ERROR`, `SERVER_ERROR`, `FETCH_FAILED`, `MISSING_TITLE` (critical) ·
`TITLE_TOO_LONG`, `TITLE_TOO_SHORT`, `MULTIPLE_TITLES`, `MISSING_META_DESCRIPTION`, `MISSING_H1`, `NOINDEX`, `INVALID_CANONICAL`, `NOT_HTTPS`, `MISSING_VIEWPORT`, `IMAGES_MISSING_ALT`, `SLOW_RESPONSE`, `INVALID_JSON_LD`, `DUPLICATE_TITLE`, `DUPLICATE_META_DESCRIPTION` (warning) ·
`META_DESCRIPTION_TOO_LONG`, `META_DESCRIPTION_TOO_SHORT`, `MULTIPLE_H1`, `DUPLICATE_H1`, `MISSING_CANONICAL`, `CANONICAL_TO_OTHER_URL`, `REDIRECTED`, `NOFOLLOW_PAGE`, `MISSING_LANG`, `THIN_CONTENT`, `MISSING_OPEN_GRAPH`, `NO_STRUCTURED_DATA`, `LARGE_HTML`, `NO_INTERNAL_LINKS` (notice)

### Use it from AI agents, Zapier, Make, n8n or the API

- **AI agents (MCP):** SEO Audit Crawler works with the [Apify MCP server](https://mcp.apify.com), so Claude, Cursor, ChatGPT and other MCP clients can find it and run it for you. Ask something like *"Run SEO Audit Crawler on example.com and tell me what to fix first."*
- **No-code:** use the Apify app in **Zapier**, **Make** or **n8n** to start an audit and send the results to Google Sheets, Slack or email.
- **API and CI:** start a run with one HTTP call (`POST https://api.apify.com/v2/acts/goldish_fireplace~seo-audit-crawler/run-sync-get-dataset-items`) and fail a deploy when `siteScore` in `SUMMARY` drops.
- **Schedules:** audit weekly and catch SEO regressions after every deploy.

### Limitations

- **No JavaScript rendering.** It audits the HTML the server sends. Content that only appears after JavaScript runs is not seen.
- **No Core Web Vitals, backlinks or keyword rankings.** It measures server response time and HTML size, not LCP or CLS, and it has no data from Google Search Console or backlink databases.
- **No logins.** Pages behind a login are not audited.
- **Scores are a guide, not a Google ranking factor.** The 0 to 100 score reflects the checks listed above, weighted by severity.
- **Outgoing links are not checked.** Use Broken Link Checker for that.

### FAQ

**How do I audit my website for SEO?** Enter your homepage, set **Max pages to audit** and click **Start**. Open the HTML report in the Output tab for the site score, the issues ranked by importance and the worst pages first.

**Does it find duplicate titles and meta descriptions?** Yes. Duplicates are compared across every page in the crawl, and each issue names up to 3 of the other pages that share the same title, description or H1.

**Does it render JavaScript?** No. It reads the HTML that the server sends, which is the HTML search engines see first. Sites that build all their content in the browser (pure client-side SPAs) will show as thin or missing content, and that is itself an SEO problem worth knowing about.

**Does it respect robots.txt?** Yes, by default. You can turn this off for your own sites.

**Can I audit several websites at once?** Yes. Add several start URLs. Each site is crawled within its own domain.

**Does it collect personal data?** No. It only reads public, technical SEO information from web pages (titles, tags, headings, links).

**Is it a broken-link checker?** It reports pages that return errors and redirects. To check every outgoing link and image, use our **[Broken Link Checker](https://apify.com/goldish_fireplace/broken-link-checker)** Actor.

### Feedback

Found a bug or want a new check? Open an issue on the Issues tab and we'll look into it.

### Related tools

- 🔗 **[Broken Link Checker](https://apify.com/goldish_fireplace/broken-link-checker)**: checks every link, image, script and stylesheet on your site for 404s, dead external links, redirect chains and timeouts, and shows the page each one is on. Use it together with SEO Audit Crawler for a complete technical SEO health check.

# Actor input Schema

## `startUrls` (type: `array`):

Homepage (or any page) of each website to audit. The crawler follows internal links from here.

## `maxPagesToCrawl` (type: `integer`):

Stop after auditing this many pages. You pay per audited page, so this also caps the cost.

## `maxDepth` (type: `integer`):

How many clicks away from the start URL to go. 0 = audit only the start URLs.

## `outputMode` (type: `string`):

All pages (full SEO data for every page) or only pages that have critical issues or warnings.

## `includeSubdomains` (type: `boolean`):

Also crawl subdomains, e.g. blog.example.com when starting from example.com.

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

Skip pages that robots.txt disallows for crawlers.

## `excludeUrlPatterns` (type: `array`):

Regular expressions (or plain text). Matching URLs are not crawled, e.g. /tag/ or ?page=

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

Maximum number of pages fetched in parallel. Lower it for small or fragile servers.

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

How long to wait for each page.

## `maxRetries` (type: `integer`):

How many times to retry a page that fails to load (network errors only).

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

Custom User-Agent header. Leave empty for a standard browser-like one.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://crawlee.dev/"
    }
  ],
  "maxPagesToCrawl": 50,
  "maxDepth": 20,
  "outputMode": "all",
  "includeSubdomains": false,
  "respectRobotsTxt": true,
  "excludeUrlPatterns": [],
  "maxConcurrency": 10,
  "requestTimeoutSecs": 30,
  "maxRetries": 2
}
```

# Actor output Schema

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

No description

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

No description

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

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://crawlee.dev/"
        }
    ],
    "maxPagesToCrawl": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("goldish_fireplace/seo-audit-crawler").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 = {
    "startUrls": [{ "url": "https://crawlee.dev/" }],
    "maxPagesToCrawl": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("goldish_fireplace/seo-audit-crawler").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 '{
  "startUrls": [
    {
      "url": "https://crawlee.dev/"
    }
  ],
  "maxPagesToCrawl": 50
}' |
apify call goldish_fireplace/seo-audit-crawler --silent --output-dataset

```

## MCP server setup

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

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/bkOZ6gKmmdf64aVDG/builds/hkp8K5PkOKHq8aWe9/openapi.json
