# SEO On-Page Audit - Title Meta H1 Canonical OG Schema (`tinyrex/seo-on-page-audit`) Actor

On-page SEO audit for user-supplied URLs: title, meta description, H1/H2, canonical, hreflang, Open Graph, Twitter cards, JSON-LD, link & image counts, issue flags. ~$1.50/1k pages; failed/unreachable free.

- **URL**: https://apify.com/tinyrex/seo-on-page-audit.md
- **Developed by:** [TinyRex](https://apify.com/tinyrex) (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.20 / 1,000 page audits

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 On-Page Audit: title, meta, H1, canonical, OG & schema in one pass

**Audit any list of page URLs for on-page SEO signals** — title and meta description (with lengths), H1/H2, canonical, hreflang, Open Graph, Twitter cards, JSON-LD types, internal/external/nofollow link counts, images missing alt, approximate word count, plus a short `issues` list. Paste URLs you already have (or pipe output from the [Sitemap Scraper](https://apify.com/tinyrex/sitemap-scraper)); the Actor fetches only those pages. No site-wide crawl, no login, no paywall bypass. **~$1.50 per 1,000 pages audited; failed or unreachable URLs are free.**

### What you get from the SEO On-Page Audit

- **Core tags** — `title`, `metaDescription`, `metaRobots`, `metaViewport`, `charset`, `html lang`, with character lengths for title and description.
- **Canonical & hreflang** — `canonical`, `canonicalMatchesUrl`, and every `hreflang` alternate found in `<link rel="alternate">`.
- **Social + structured data** — Open Graph (`og:*`), Twitter card tags, and JSON-LD `@type` values (raw snippet truncated if huge).
- **Structure signals** — H1/H2 texts and H1–H6 counts, internal vs external vs nofollow link counts, images total / missing alt, approximate body word count.
- **Actionable `issues`** — short flags like `missing title`, `title too long >60`, `multiple h1`, `missing canonical`, `missing meta description`.

### Sample output (JSON)

```json
{
  "url": "https://apify.com",
  "finalUrl": "https://apify.com/",
  "statusCode": 200,
  "redirected": true,
  "title": "Apify: Full-stack web scraping and data extraction platform",
  "titleLength": 58,
  "metaDescription": "Apify is the largest ecosystem of web scraping and automation tools.",
  "metaDescriptionLength": 70,
  "canonical": "https://apify.com/",
  "canonicalMatchesUrl": true,
  "headings": { "h1": ["Get data. Automate anything."], "h1Count": 1, "h2Count": 2 },
  "links": { "internal": 42, "external": 8, "nofollow": 2 },
  "images": { "total": 12, "missingAlt": 1 },
  "wordCount": 850,
  "issues": ["1 image(s) missing alt"],
  "error": null
}
```

Download the dataset as **CSV, Excel or JSON**, or pipe it to Google Sheets, Make, Zapier, n8n, webhooks or the Apify API.

### How to configure the SEO On-Page Audit

1. Paste **page URLs**, one per line (or pass `[{ "url": "…" }]` from another Actor / sitemap export).
2. Optional: raise *Max URLs* (default 100, max 5000) or turn off *Respect robots.txt*.
3. Run. Every page that returns an HTTP status (including 4xx/5xx) is charged; unreachable / robots-blocked rows are free.

#### Example input

```json
{
  "startUrls": ["https://example.com", "https://apify.com"],
  "maxUrls": 100,
  "respectRobotsTxt": true
}
```

| Setting | Default | Notes |
|---|---|---|
| startUrls | (required) | Pages you supply — not discovered via search |
| maxUrls | 100 | Hard cap per run (max 5000) |
| respectRobotsTxt | true | Skip disallowed paths |
| maxConcurrency | 5 | Pages in parallel (keep low for politeness) |

### Common use cases

- **Bulk SEO QA** — check title/meta/H1/canonical across a sitemap export before a migration or redesign.
- **Agency reporting** — attach `issues` columns to client sheets without opening each URL by hand.
- **Content ops** — find missing OG/Twitter tags and thin pages (low `wordCount`) on a URL list.
- **Pipeline with TinyRex** — [Sitemap Scraper](https://apify.com/tinyrex/sitemap-scraper) → this Actor → export CSV; pair with [Contact Details Extractor](https://apify.com/tinyrex/contact-details-extractor) or [Tech Stack Detector](https://apify.com/tinyrex/tech-stack-detector) for enrichment.

### Pricing (failed = free)

Pay per event:

- **Page audit** (`page-audit`): ~$0.0015 per page that returns an HTTP status (including 4xx/5xx — you still get the audit row). ≈ **$1.50 / 1k pages**.
- **Free:** network failures / unreachable hosts (`statusCode` 0), robots.txt blocks.

Bronze/Silver/Gold tier discounts apply on the Store. Set a max cost per run; the Actor stops gracefully when it is reached.

### Limitations

- Public HTML only. Heavy JS-rendered titles/meta may be missed (no headless browser).
- Datacenter IP blocks may need a proxy.
- Issue rules are heuristic defaults (title ≤60, description 50–160, single H1) — adjust your process if your style guide differs.

### FAQ — SEO On-Page Audit

**How do I audit every URL in a sitemap?**
Run [Sitemap Scraper](https://apify.com/tinyrex/sitemap-scraper) first, then pass its `url` field into `startUrls` (string list or `{ url }` objects). Cap with `maxUrls` if needed.

**Do 404 pages cost money?**
Yes — if the server responds with a status code, you get a dataset row (`statusCode`, `issues`) and pay the page-audit event. Unreachable hosts (DNS/timeout) are free.

**Does it respect robots.txt?**
Yes by default (`respectRobotsTxt: true`). Disallowed URLs are skipped, recorded with an error, and not charged.

**Is this a full site crawl?**
No. It only fetches the URLs you supply. For site-wide coverage, feed it a sitemap export.

**Does it work with AI agents / MCP?**
Yes. Connect Claude, Cursor, VS Code, n8n or any MCP client to `https://mcp.apify.com?tools=tinyrex/seo-on-page-audit` and ask e.g. *"Audit on-page SEO for https://example.com and https://apify.com"*.

### Related actors

- [Sitemap Scraper](https://apify.com/tinyrex/sitemap-scraper) — every URL from XML sitemaps (ideal input for this Actor)
- [Contact Details Extractor](https://apify.com/tinyrex/contact-details-extractor) — emails, phones and socials from the same domains
- [Tech Stack Detector](https://apify.com/tinyrex/tech-stack-detector) — technologies used on the page / domain

Built by **TinyRex**. Questions or feature requests? Open an issue on the Actor page.

# Actor input Schema

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

Pages to audit. Full URLs (https://example.com/page). Also accepts objects with a .url field (e.g. sitemap-scraper dataset items). Duplicates are removed. One charge per page that returns an HTTP status (including 4xx/5xx); unreachable pages are free.

## `maxUrls` (type: `integer`):

Hard cap on how many unique URLs are audited in this run.

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

Skip paths disallowed by robots.txt for user-agent \* (default on).

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

How many pages are fetched in parallel. Keep it low to be polite.

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

How long to wait for each page before giving up.

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

Optional proxy, only needed for sites that block datacenter IPs.

## Actor input object example

```json
{
  "startUrls": [
    "https://example.com",
    "https://apify.com"
  ],
  "maxUrls": 100,
  "respectRobotsTxt": true,
  "maxConcurrency": 5,
  "requestTimeoutSecs": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `audits` (type: `string`):

On-page SEO signals and issues per URL.

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

Totals for the run.

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

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

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tinyrex/seo-on-page-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/Pd8J9hPjvRPlT5ZWf/builds/WOGmYiImpXDaCb2AL/openapi.json
