# SEO Audit Tool — Lighthouse Scores & Core Web Vitals (`junipr/seo-audit-tool`) Actor

Audit websites across 21 SEO factors: titles, meta, headings, images, links, canonical, OG, Twitter Cards, schema, robots, HTTPS, URL structure. Per-page scores 0-100 with prioritized recommendations.

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

## Pricing

from $6.50 / 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.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## SEO Audit Tool

### What does SEO Audit Tool do?

SEO Audit Tool performs a comprehensive on-page SEO analysis of any website. Point it at one or more URLs and it crawls the site, auditing each page for title tags, meta descriptions, heading hierarchy, image optimization, internal and external links, canonical URLs, Open Graph tags, Twitter Cards, structured data (JSON-LD), meta robots directives, HTTPS usage, viewport configuration, URL structure, and word count. Each page receives an SEO score from 0 to 100 based on the issues found.

The actor also performs site-level checks including robots.txt analysis, sitemap.xml detection, and broken link detection. After crawling, it produces a summary report with the average score, total issues grouped by severity (error, warning, info), and robots.txt/sitemap status. All results are structured JSON ready for dashboards, reports, or automated monitoring.

### Features

- **16 on-page SEO checks** — title tag, meta description, headings, images, links, canonical URL, Open Graph, Twitter Card, structured data, meta robots, language, viewport, HTTPS, URL structure, and word count
- **SEO scoring** — each page scored 0-100 based on issue severity and count
- **Site-level checks** — robots.txt existence and disallow rules, sitemap.xml detection and URL count
- **Broken link detection** — optionally verify all internal and external links return valid HTTP responses
- **Multi-page crawling** — follow internal links to discover and audit up to 500 pages per site
- **Multiple starting URLs** — audit several websites in a single run
- **Issue categorization** — issues grouped by severity (error, warning, info) and category
- **Site summary report** — aggregate scores, total issues by severity, robots.txt and sitemap status
- **Configurable concurrency** — adjust parallel crawling speed and request delays
- **Pay-per-page pricing** — only pay for pages successfully audited

### Input Configuration

```json
{
  "urls": ["https://example.com"],
  "maxPages": 20,
  "followLinks": true,
  "checkBrokenLinks": true,
  "checkRobotsTxt": true,
  "checkSitemap": true,
  "maxConcurrency": 5,
  "requestDelay": 500
}
````

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `urls` | string\[] | `["https://crawlee.dev"]` | List of website URLs to audit |
| `maxPages` | integer | `20` | Maximum pages to crawl per starting URL (1-500) |
| `followLinks` | boolean | `true` | Follow internal links to discover additional pages |
| `checkBrokenLinks` | boolean | `true` | Verify all links return valid HTTP responses |
| `checkRobotsTxt` | boolean | `true` | Fetch and analyze the site's robots.txt |
| `checkSitemap` | boolean | `true` | Fetch and analyze the site's sitemap.xml |
| `maxConcurrency` | integer | `5` | Maximum pages to crawl in parallel (1-20) |
| `requestDelay` | integer | `500` | Delay between requests in ms (0-10000) |

### Output Format

The dataset contains two types of records: per-page audit results and a site summary.

**Page audit result:**

```json
{
  "type": "page",
  "url": "https://example.com/about",
  "statusCode": 200,
  "responseTimeMs": 342,
  "title": { "text": "About Us | Example", "length": 18, "isOptimal": true },
  "metaDescription": { "text": "Learn about our company...", "length": 89, "isOptimal": false },
  "headings": { "h1Count": 1, "h2Count": 3, "h3Count": 5, "hierarchyValid": true, "h1Text": "About Us" },
  "images": { "total": 8, "withAlt": 6, "withoutAlt": 2, "withDimensions": 5, "withLazyLoad": 3 },
  "links": { "internal": 12, "external": 4, "broken": 1, "nofollow": 0 },
  "canonical": { "exists": true, "url": "https://example.com/about", "isSelfReferencing": true },
  "openGraph": { "hasTitle": true, "hasDescription": true, "hasImage": true, "hasUrl": true },
  "twitterCard": { "hasCard": true, "hasTitle": true, "hasDescription": true },
  "structuredData": { "found": true, "types": ["Organization", "WebPage"] },
  "metaRobots": { "index": true, "follow": true },
  "language": "en",
  "hasViewport": true,
  "isHttps": true,
  "wordCount": 850,
  "score": 82,
  "issues": [
    { "severity": "warning", "message": "Meta description is too short (89 chars, recommended 120-160)", "category": "meta" },
    { "severity": "error", "message": "2 images missing alt text", "category": "images" }
  ],
  "scrapedAt": "2026-03-11T12:00:00.000Z"
}
```

**Site summary:**

```json
{
  "type": "summary",
  "siteUrl": "https://example.com",
  "pagesAudited": 15,
  "averageScore": 78,
  "totalIssues": 42,
  "issuesBySeverity": { "error": 8, "warning": 22, "info": 12 },
  "robotsTxt": { "exists": true, "disallowCount": 3 },
  "sitemap": { "exists": true, "urlCount": 127 },
  "scrapedAt": "2026-03-11T12:05:00.000Z"
}
```

### Usage Examples / Use Cases

- **Website launch audit** — run a full SEO check before launching a new site to catch missing meta tags, broken links, and missing structured data
- **Ongoing monitoring** — schedule regular audits to detect SEO regressions after content or code changes
- **Competitor analysis** — audit competitor websites to understand their SEO strategy, structured data usage, and technical quality
- **Client reporting** — generate structured audit data for SEO agency client reports
- **Content optimization** — identify pages with low word counts, missing headings, or poor meta descriptions
- **Technical SEO** — find broken links, missing canonical tags, HTTPS issues, and robots.txt problems across an entire site

### Proxy Requirements (Optional)

SEO Audit Tool does not require a proxy for most websites. It uses lightweight HTTP crawling and respects rate limits. However, if you are auditing a website that blocks datacenter IPs or uses aggressive anti-bot protection, you can configure a proxy in the Apify Console run settings. For most use cases, the default configuration works without any proxy.

### Pricing

This actor uses Pay-Per-Event (PPE) pricing: **$6.50 per 1,000 pages audited** ($0.0065 per event).

Pricing includes all platform compute costs — no hidden fees.

### FAQ

#### How is the SEO score calculated?

Each page starts at 100 and loses points for each issue found. Errors deduct more points than warnings, and warnings more than info-level issues. The score reflects the overall on-page SEO health of that specific URL. The site summary provides an average across all audited pages.

#### Can I audit multiple websites in one run?

Yes. Add multiple URLs to the `urls` array and each one will be audited independently. The actor produces separate page results and summary records for each starting URL, making it easy to compare SEO health across different sites.

#### What does the broken link checker do?

When `checkBrokenLinks` is enabled, the actor sends HEAD requests to every link found on each page (both internal and external) and reports links that return 4xx or 5xx status codes. This helps you find dead links before your visitors or search engines do.

#### How many pages can I audit per run?

Up to 500 pages per starting URL, controlled by the `maxPages` setting. The default is 20 pages, which covers most small to medium sites. For large sites, increase `maxPages` and consider lowering `maxConcurrency` to avoid overwhelming the target server.

#### Does the audit check page speed or Core Web Vitals?

No. This actor focuses on on-page SEO factors like meta tags, headings, links, structured data, and content quality. For performance auditing and Core Web Vitals analysis, use a dedicated performance tool like [Website Performance Analyzer](https://apify.com/junipr/website-performance-analyzer).

### Related Actors

- [Website Performance Analyzer](https://apify.com/junipr/website-performance-analyzer) — analyze page load speed and Core Web Vitals
- [Sitemap Generator](https://apify.com/junipr/sitemap-generator) — crawl a website and generate a sitemap.xml
- [Website Tech Stack Detector](https://apify.com/junipr/website-tech-stack-detector) — detect the technologies powering any website
- [Contact Info Scraper](https://apify.com/junipr/contact-info-scraper) — extract contact information from websites
- [RAG Web Extractor](https://apify.com/junipr/rag-web-extractor) — extract clean content from web pages for analysis

# Actor input Schema

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

List of website URLs to audit. Each URL is treated as a starting point for crawling.

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

Maximum number of pages to crawl per starting URL.

## `followLinks` (type: `boolean`):

Follow internal links to discover and audit additional pages.

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

Check if internal and external links return valid HTTP responses.

## `checkRobotsTxt` (type: `boolean`):

Fetch and analyze the site's robots.txt file.

## `checkSitemap` (type: `boolean`):

Fetch and analyze the site's sitemap.xml file.

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

Maximum number of pages to crawl in parallel.

## `requestDelay` (type: `integer`):

Delay between requests in milliseconds to avoid overwhelming the target server.

## Actor input object example

```json
{
  "urls": [
    "https://crawlee.dev"
  ],
  "maxPages": 20,
  "followLinks": true,
  "checkBrokenLinks": true,
  "checkRobotsTxt": true,
  "checkSitemap": true,
  "maxConcurrency": 5,
  "requestDelay": 500
}
```

# Actor output Schema

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

SEO audit results for each page plus a site-wide summary.

# 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("junipr/seo-audit-tool").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("junipr/seo-audit-tool").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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 junipr/seo-audit-tool --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=junipr/seo-audit-tool",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SEO Audit Tool — Lighthouse Scores & Core Web Vitals",
        "description": "Audit websites across 21 SEO factors: titles, meta, headings, images, links, canonical, OG, Twitter Cards, schema, robots, HTTPS, URL structure. Per-page scores 0-100 with prioritized recommendations.",
        "version": "1.0",
        "x-build-id": "2zrWK1mWeS5JfCiVB"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/junipr~seo-audit-tool/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-junipr-seo-audit-tool",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/junipr~seo-audit-tool/runs": {
            "post": {
                "operationId": "runs-sync-junipr-seo-audit-tool",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/junipr~seo-audit-tool/run-sync": {
            "post": {
                "operationId": "run-sync-junipr-seo-audit-tool",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "urls": {
                        "title": "URLs to Audit",
                        "type": "array",
                        "description": "List of website URLs to audit. Each URL is treated as a starting point for crawling.",
                        "items": {
                            "type": "string"
                        },
                        "default": [
                            "https://crawlee.dev"
                        ]
                    },
                    "maxPages": {
                        "title": "Max Pages",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum number of pages to crawl per starting URL.",
                        "default": 20
                    },
                    "followLinks": {
                        "title": "Follow Links",
                        "type": "boolean",
                        "description": "Follow internal links to discover and audit additional pages.",
                        "default": true
                    },
                    "checkBrokenLinks": {
                        "title": "Check Broken Links",
                        "type": "boolean",
                        "description": "Check if internal and external links return valid HTTP responses.",
                        "default": true
                    },
                    "checkRobotsTxt": {
                        "title": "Check robots.txt",
                        "type": "boolean",
                        "description": "Fetch and analyze the site's robots.txt file.",
                        "default": true
                    },
                    "checkSitemap": {
                        "title": "Check Sitemap",
                        "type": "boolean",
                        "description": "Fetch and analyze the site's sitemap.xml file.",
                        "default": true
                    },
                    "maxConcurrency": {
                        "title": "Max Concurrency",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Maximum number of pages to crawl in parallel.",
                        "default": 5
                    },
                    "requestDelay": {
                        "title": "Request Delay (ms)",
                        "minimum": 0,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Delay between requests in milliseconds to avoid overwhelming the target server.",
                        "default": 500
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
