# On-Page SEO Auditor - Meta, Headings & Issues (`antishock/onpage-seo-auditor`) Actor

Audit on-page SEO for any list of URLs: title and meta description with lengths, canonical, robots meta, indexability, H1 to H6 structure, word count, image alt coverage, internal and external links, Open Graph, JSON-LD schema types, hreflang and a plain-language list of issues found.

- **URL**: https://apify.com/antishock/onpage-seo-auditor.md
- **Developed by:** [Ryan Zinburg](https://apify.com/antishock) (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.00 / 1,000 result exporteds

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

## On-Page SEO Auditor - Titles, Meta, Headings, Schema & Issues

Audit the on-page SEO of any list of URLs. The actor fetches each page and reports **titles, meta descriptions, canonicals, headings, Open Graph tags, structured data, link counts, image alt coverage** and a plain-language list of the issues it found.

No API key, no proxy needed.

### What you get per page

**Response** - `statusCode`, `finalUrl`, `redirected`, `loadTimeMs`, `pageSizeBytes`

**Indexing and meta** - `title` with `titleLength`, `metaDescription` with `metaDescriptionLength`, `canonicalUrl`, `robotsMeta`, `isIndexable`, `lang`, `charset`, `hasViewport`

**Structure** - `h1` and `h2` contents, `h1Count`, `headingCounts` for H1 to H6, `wordCount`

**Links and media** - `internalLinkCount`, `externalLinkCount`, `externalDomains`, `imageCount`, `imagesMissingAlt`

**Social and structured data** - `ogTitle`, `ogDescription`, `ogImage`, `ogType`, `twitterCard`, `schemaTypes` from JSON-LD, `hreflangs`

**Findings** - `issues`, a ready-to-read list such as "Title longer than 60 characters", "No H1 heading", "3 image(s) without alt text"

### Input

- **urls** - the pages to audit, separated by commas, spaces or newlines
- **maxResults** - how many pages to process, up to 2000

### Example input

```json
{
  "urls": "https://example.com/, https://example.com/pricing, https://example.com/blog"
}
```

### Use cases

- **SEO audits** - run a whole site list and get the issue table an audit report is built from
- **Agency prospecting** - audit a prospect's pages before the pitch and lead with concrete findings
- **Pre-launch checks** - verify titles, canonicals and indexability before a release goes live
- **Migration validation** - confirm that redirects land where they should and canonicals were updated
- **Competitor analysis** - see how competitors structure titles, schema and internal linking
- **Content QA at scale** - find thin pages, missing descriptions and duplicate H1s across hundreds of URLs

### Which checks and why

The `issues` list applies the checks that actually affect search appearance and accessibility:

- **Title 30 to 60 characters** - shorter wastes the strongest ranking signal, longer gets truncated in results
- **Meta description up to 160 characters** - beyond that it is cut off; missing means the engine writes its own
- **Exactly one H1** - zero leaves the page without a stated topic, several dilute it
- **Canonical present** - without it, parameter and duplicate URLs compete with each other
- **noindex detection** - the single most expensive accidental setting in SEO
- **Viewport tag** - its absence means the page is not treated as mobile friendly
- **Image alt text** - required for accessibility and the only signal image search has
- **Thin content under 300 words** - not a rule, but a reliable flag for pages that need work

### Notes

- Pages are fetched as HTML and parsed server-side. Content injected by JavaScript after load is not seen, so single-page applications should be audited on their server-rendered output.
- Pages that cannot be fetched return a row with an `error` field instead of failing the whole run.
- `schemaTypes` collects every `@type` found in JSON-LD, including nested ones, which is the quickest way to see whether Product, Article, FAQ or Breadcrumb markup is present.
- `wordCount` is derived from the rendered body text including navigation, so compare pages within a site rather than across different templates.

# Actor input Schema

## `urls` (type: `string`):

Pages to audit, separated by commas, spaces or newlines.

## `maxResults` (type: `integer`):

How many pages to audit.

## Actor input object example

```json
{
  "urls": "https://apify.com/\nhttps://apify.com/pricing",
  "maxResults": 100
}
```

# Actor output Schema

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

Scraped records in the default dataset.

# 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/
https://apify.com/pricing`
};

// Run the Actor and wait for it to finish
const run = await client.actor("antishock/onpage-seo-auditor").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/
https://apify.com/pricing""" }

# Run the Actor and wait for it to finish
run = client.actor("antishock/onpage-seo-auditor").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/\\nhttps://apify.com/pricing"
}' |
apify call antishock/onpage-seo-auditor --silent --output-dataset

```

## MCP server setup

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

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/hHSzIK0zXQ2ENwvQn/builds/tpFHoT47FOEYNH8Nt/openapi.json
