# Website SEO Audit Scraper (`neuro-scraper/website-seo-audit-scraper`) Actor

SEO Audit Scraper SD - SEO Audit Scraper is an on-page SEO tool that extracts titles, meta descriptions, headings, canonicals, indexability, hreflang, Open Graph, structured data, image alt and link data per URL, with issues and a score.

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

## Pricing

from $2.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Scraper — on-page SEO checks for URLs or whole sites

SEO Audit Scraper audits each page you give it (or every page of a site it crawls) and returns one row per page with the on-page SEO facts, a list of **issues with severity** and a **0–100 score**:

status code and redirect chain, response time, page size, HTTPS · title and meta description with lengths · H1–H6 counts and outline · canonical (self-referencing?), meta robots, X-Robots-Tag and robots.txt for Googlebot → **indexable or not, and why** · hreflang (x-default, self reference), html lang, viewport, charset, favicon · Open Graph and Twitter card tags · JSON-LD types (with parse errors) and microdata · images without alt · internal, external and nofollow links, links without text · mixed content · word count and text-to-HTML ratio · optional **broken link check**.

#### Input

| Field | Type | Default | Meaning |
|---|---|---|---|
| `startUrls` | URL list | python.org/about/, crawlee.dev/python/ (prefill) | Pages to audit (crawl starting points in crawl mode) |
| `crawl` | boolean | false | Also audit same-domain pages linked from them |
| `maxPages` | integer | 20 | Pages audited |
| `maxCrawlDepth` | integer | 2 | Crawl depth (crawl mode) |
| `checkLinks` | boolean | false | Check each page's links (404/410/5xx/unreachable = broken; 401/403/429 = blocked) |
| `maxLinksToCheckPerPage` | integer | 30 | Links checked per page (each link once per run) |
| `slowResponseMs` | integer | 2000 | SLOW_RESPONSE threshold |
| `respectRobotsTxt` | boolean | true | Do not fetch pages robots.txt disallows |
| `requestDelayMs` | integer | 1000 | Pause between requests to one host |
| `proxyConfiguration` | proxy | Apify datacenter | RESIDENTIAL for sites that block datacenter IPs |

#### Output (one row per page) — main fields

| Field | Meaning |
|---|---|
| `url`, `finalUrl`, `statusCode`, `redirectChain`, `redirectCount`, `responseTimeMs`, `pageSizeBytes`, `isHttps` | Fetch facts |
| `indexable`, `indexabilityIssues`, `metaRobots`, `xRobotsTag`, `robotsTxtAllowsGooglebot`, `canonicalUrl`, `canonicalIsSelf` | Indexability |
| `title`, `titleLength`, `metaDescription`, `metaDescriptionLength` | Snippet |
| `h1`, `h1Count`, `headingCounts`, `headingOutline` | Headings |
| `lang`, `viewport`, `charset`, `hreflang`, `favicon` | Locale / mobile |
| `openGraph`, `twitterCard`, `structuredDataTypes`, `jsonLdBlocks`, `jsonLdParseErrors`, `microdataTypes` | Social + structured data |
| `imagesCount`, `imagesWithoutAlt`, `imagesWithEmptyAlt`, `imagesWithoutAltSamples` | Images |
| `internalLinks`, `externalLinks`, `nofollowLinks`, `linksWithoutText`, `mixedContentResources` | Links (unique URLs) |
| `brokenLinks`, `linksBlockedOrUnauthorized`, `linksChecked` | With `checkLinks` |
| `wordCount`, `textToHtmlRatio` | Content |
| `score`, `issueCounts`, `issues` | `[{severity, code, message}]`, e.g. `TITLE_TOO_LONG`, `MISSING_H1`, `NOINDEX`, `BROKEN_LINKS` |

#### Measured (2026-10-03, see TEST_REPORT.md)

- 15-page crawl with link checking (43 links) in 24 s; a BBC article's title, description, headings, hreflang and structured data matched an independent audit of the same page.

#### Limits

- Pages are audited as served, before JavaScript; the score is a transparent heuristic, not Google's ranking.
- Response times are measured from the crawler's location. No Core Web Vitals / Lighthouse.
- Sites behind anti-bot pages return the challenge page's status; use a RESIDENTIAL proxy.

#### Example

```json
{"startUrls": [{"url": "https://books.toscrape.com/"}], "crawl": true, "maxPages": 50, "checkLinks": true}
```

# Actor input Schema

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

Pages to audit, e.g. https://www.python.org/about/. With 'Crawl the site' on, these are the starting points of the crawl.

## `crawl` (type: `boolean`):

Also audit pages of the same domain linked from the start URLs (breadth-first), up to 'Max pages'.

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

Maximum number of pages audited (one row per page).

## `maxCrawlDepth` (type: `integer`):

Crawl mode only: how many links away from a start URL.

## `checkLinks` (type: `boolean`):

Check the HTTP status of the links on each page (internal and external, HEAD then GET). 404/410/5xx/unreachable count as broken; 401/403/429 are listed separately as blocked.

## `maxLinksToCheckPerPage` (type: `integer`):

With 'Check links': how many links per page are checked (each link once per run).

## `slowResponseMs` (type: `integer`):

Pages slower than this get a SLOW_RESPONSE warning (time measured from the crawler, including redirects).

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

Do not fetch pages robots.txt disallows. Whether Googlebot is allowed is reported for every page either way.

## `requestDelayMs` (type: `integer`):

Pause between two requests to the same host.

## `proxyConfiguration` (type: `object`):

Apify Proxy (datacenter by default). Choose RESIDENTIAL for sites that block datacenter IPs.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.python.org/about/"
    },
    {
      "url": "https://crawlee.dev/python/"
    }
  ],
  "crawl": false,
  "maxPages": 20,
  "maxCrawlDepth": 2,
  "checkLinks": false,
  "maxLinksToCheckPerPage": 30,
  "slowResponseMs": 2000,
  "respectRobotsTxt": true,
  "requestDelayMs": 1000,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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://www.python.org/about/"
        },
        {
            "url": "https://crawlee.dev/python/"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("neuro-scraper/website-seo-audit-scraper").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://www.python.org/about/" },
        { "url": "https://crawlee.dev/python/" },
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("neuro-scraper/website-seo-audit-scraper").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://www.python.org/about/"
    },
    {
      "url": "https://crawlee.dev/python/"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call neuro-scraper/website-seo-audit-scraper --silent --output-dataset

```

## MCP server setup

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

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/mcp9dJBNq6k8zKQtB/builds/xf8VtkCGVH5bgVH10/openapi.json
