# Website SEO Audit & Schema Checker (`vex_workflow/website-seo-audit`) Actor

On-page SEO audit for any list of URLs or whole websites: title, meta description, headings, canonical, indexability, alt text, links, word count, Open Graph and JSON-LD structured data validation. 0-100 score with a clear issue list per page.

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

## Pricing

Pay per event

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

### What does Website SEO Audit & Schema Checker do?

It audits pages the way a technical SEO would, in bulk, and gives every page a **0-100 score** and a **plain fix list**. Paste a list of URLs, or one home page and let it crawl the site.

Each page is checked for:

- **Title and meta description**: missing, too short, too long
- **Headings**: missing H1, several H1s, H2 count
- **Indexability**: canonical tag, robots meta, X-Robots-Tag noindex, HTTPS, redirects
- **Structured data**: every JSON-LD block parsed, broken JSON reported, and the main schema types (Product, Offer, Article, Organization, LocalBusiness and its subtypes, FAQPage, BreadcrumbList, Event, Recipe, JobPosting, VideoObject, Review, SoftwareApplication, Course, HowTo, WebSite) checked for missing required and recommended properties. Microdata types are listed too.
- **Content and media**: word count, thin content, images without alt text
- **Links**: internal and external link counts
- **Social previews**: Open Graph title, description, image, Twitter card
- **Speed signal**: server response time and HTML size

### Who is it for?

- **Agencies** running quick audits for prospects and monthly checks for clients
- **In-house SEO and dev teams** catching regressions after a release
- **Schema / rich results work**: find every page where Product, LocalBusiness or Article markup is missing fields
- **AI agents and automations** that need a structured page audit in one call

### How to use it

1. Add pages to **Page URLs**.
2. Leave **Max pages per website** at 1 to audit only those URLs, or raise it (for example 200) to crawl each site from that page.
3. Start the run, then sort by `score` or filter `issues` in the dataset. Export to CSV or Excel for a client report.

#### Input example

```json
{
  "urls": ["https://apify.com/", "https://wordpress.org/"],
  "maxPagesPerSite": 3
}
```

#### Output example (shortened)

```json
{
  "url": "https://www.example.com/",
  "status": "ok",
  "score": 83,
  "title": "Example Widgets | Example Inc.",
  "metaDescriptionLength": 0,
  "h1": ["Widgets for everyone"],
  "canonical": "https://www.example.com/",
  "indexable": true,
  "wordCount": 850,
  "imagesMissingAlt": 3,
  "schemaTypes": ["Organization", "WebSite"],
  "schemaIssues": ["Organization: missing recommended \"logo\""],
  "issues": [
    "error: Missing meta description",
    "warning: 3 of 12 images have no alt text",
    "notice: Schema Organization: missing recommended \"logo\""
  ]
}
```

### How much does it cost?

| Event | Price |
|---|---|
| Actor start | $0.001 per run |
| Page audited | **$0.006** per page |

A 500-page site audit costs about **$3**. Pages that fail to load or are blocked by robots.txt are not charged. Set a maximum cost per run in the run options if you want a hard cap.

### How the score works

Start at 100. Each **error** takes off 10 points, each **warning** 4, each **notice** 1. Errors are things that usually hurt rankings or rich results (missing title, noindex, broken JSON-LD, missing required schema property). Notices are polish.

### Good to know

- Pages are read as raw HTML. Content that only appears after JavaScript runs is not seen, which is also how many crawlers first see a page.
- robots.txt is respected by default. No logins and no anti-bot circumvention.
- Schema checks follow publicly documented required and recommended properties. A passing check here does not guarantee a rich result.

### FAQ

**Can it audit a whole site?** Yes. Set Max pages per website up to 2,000. It follows internal links from your start page.

**Can I schedule it?** Yes. Schedule weekly runs and compare scores over time.

# Actor input Schema

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

Pages to audit, one per line. With 'Max pages per website' above 1, these are also the starting points for a crawl.

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

1 = audit only the URLs you entered. Higher = also follow internal links and audit up to this many pages per website.

## `concurrency` (type: `integer`):

How many pages to fetch at the same time. Keep low for small websites.

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

Skip pages the website asks crawlers not to visit.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com/"
  ],
  "maxPagesPerSite": 1,
  "concurrency": 8,
  "respectRobotsTxt": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

One row per audited page with score, issues and on-page SEO fields.

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

Run summary with pages audited, failures and average score.

# 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://apify.com/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("vex_workflow/website-seo-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 = { "urls": ["https://apify.com/"] }

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

```

## MCP server setup

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