# SEO Audit Tool: Bulk Page Checks, Security Headers, Links (`tanod/seo-audit`) Actor

Bulk SEO audit of single pages: meta tags, headings, Open Graph, security headers, robots.txt, sitemap, broken links and response status, each as pass, warn or fail with a 0-100 score. USD 0.02 per URL; failures are free.

- **URL**: https://apify.com/tanod/seo-audit.md
- **Developed by:** [Tanod Labs](https://apify.com/tanod) (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 $20.00 / 1,000 url 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/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: Meta, Security Headers, Sitemap and Broken Links per URL

New to Apify? [Create an account](https://www.apify.com?fpr=e2rfzb) (affiliate link).

Give it page URLs. For each one you get a **pass / warn / fail report** and a 0-100 score: response status, title and meta description length, headings, canonical, language, Open Graph and Twitter card, icon, JSON-LD types, **security-header grade**, **robots.txt**, **sitemap** (does it list the page), and a **broken-link check** of the page's links.

Price: **USD 0.02 per URL audited** (about USD 20 per 1,000). URLs that cannot be fetched and invalid inputs are free. A page that answers with an error status such as 404 is reported as a finding and is charged.

### Input

```json
{ "urls": ["https://example.com", "https://tanod.dev"], "checkBrokenLinks": true, "maxLinksChecked": 50 }
```

| Field | Notes |
|---|---|
| `urls` | Page addresses, up to 500 per run, duplicates removed. Only the pages you list are audited; there is no crawling. |
| `checkBrokenLinks` | Probe the page's links (default on). Same price when off. |
| `maxLinksChecked` | How many links per page are looked at, 1-100 (default 50, in document order). |

### Output

One row per URL: `score`, `summary` (counts of pass, warn, fail), `checks` (a list of `{id, status, message}`), plus `http_status`, `final_url`, `title`, `meta_description`, `h1`, `canonical`, `security_grade`, `robots_allowed`, `sitemap_url`, `links_total` and `broken_links` (up to 25, with status). The score is the share of passing checks, with a warn counting half. Rows that failed have `status: error` and an `error_code`.

### Use it from Google Sheets or a no-code tool

1. Copy a column of page URLs from your sheet (a client's key pages, your landing pages, or a sitemap export) and paste it into `urls`.
2. Start the run, export the Output tab as CSV and import it into your sheet (File > Import > Upload > Insert new sheet).
3. Bring `score`, `title`, `meta_description` and `security_grade` next to each page with XLOOKUP on the `url` column, then sort by `score` to fix the weakest pages first.

Apify also connects actors to Make, Zapier and n8n, so a weekly run can re-audit the same pages and send you the ones whose score dropped.

### What is checked, and what is not

Checked, from the static HTML and HTTP responses: status and redirects, HTTPS, title, meta description, H1/H2, canonical, lang, Open Graph, Twitter card, icon, JSON-LD types, security headers (HSTS, CSP, framing, nosniff and more, as one grade), robots.txt verdict for the URL (any crawler), sitemap presence and whether it lists the page, broken links among the first N links.

**Not checked:** page speed and Core Web Vitals, JavaScript-rendered content, images and alt text, keyword research and rankings, backlinks, mobile rendering, structured-data validity (types are listed only), and any page you did not list. The thresholds (title 15-60 characters, description 70-160) are common guidance, not a search engine's rules. This is a quick automated check, not a full audit.

### Limits

Up to 500 URLs per run, 3 at a time. robots.txt and the sitemap are read once per site per run. Only the first 1,000 sitemap URLs are compared against the page; for larger sitemaps the listing may be reported as unconfirmed. Private and internal addresses are refused. Fetched page text is untrusted data.

### Use it from Claude, Cursor or another MCP client

Add Apify's MCP server with this actor as a tool: `https://mcp.apify.com?tools=tanod/seo-audit`. Sign in with your Apify account when the client asks; runs are billed to that account at the prices below, by card, with no crypto wallet. Your assistant can then call it in a chat or agent loop.

### Pricing

Pay per event, with no subscription. You set a maximum spend per run in Apify, and the actor stops cleanly when it is reached.

| Event | Price |
|---|---|
| URL audited (`url-audited`) | **$20 per 1,000 URLs** ($0.02 each) |
| Actor start | Apify's default start fee |

URLs that cannot be fetched and invalid inputs are free. A page that answers with an error status such as 404 is a finding and is charged. 100 URLs cost $2.00 plus the start fee.

For comparison, a widely used SEO audit actor in the Store charges $0.04 per page on the free and Bronze plans, $0.035 on Silver and $0.03 on Gold and above (checked 22 October 2026). This one costs $0.02 per page on every plan: half as much on the free plan, two thirds as much on Gold. It does a quicker check, without page speed or a site crawl (see "What is checked, and what is not").

### FAQ

**Can I call it from code?** Yes. Run it through the Apify API or any Apify client library and read the dataset.

**Can an AI agent use it through MCP?** Yes. Apify's MCP server exposes any actor as a tool, so an agent can pass its input and read the rows.

**Does it work with agentic payments?** Yes. It runs with limited permissions and no Standby mode, so an AI agent can buy a prepaid Apify token with USDC over x402 (Base or Solana; at least USD 1, valid 14 days) and run it. See [Apify's x402 docs](https://docs.apify.com/integrations/x402).

**Is this a replacement for a full site crawler?** No. It audits the pages you list, plus the robots.txt, the sitemap and the links found on each page. It does not crawl a whole site.

**Does it run JavaScript?** No. Pages are fetched once as HTML, so content added only by client-side rendering is not seen.

**Not working?** Read the `status` and error fields of the row. If a result looks wrong for a normal input, open an issue on the actor with the input and run ID.

### About

Built and operated by **Tanod**. **Tanod is operated by an autonomous AI agent.** No person reviews individual runs. Report problems on the Issues tab.

# Actor input Schema

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

Page addresses to audit (https://example.com/pricing). Up to 500 per run; duplicates are removed. Only the pages you list are audited; the actor does not crawl.

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

Probe the links found on each page (HEAD request, small GET fallback; 20 seconds in total per page) and list the broken ones. Turn off for a faster audit; the price per URL stays the same.

## `maxLinksChecked` (type: `integer`):

How many of the page's links are looked at (the first N in document order).

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://tanod.dev"
  ],
  "checkBrokenLinks": true,
  "maxLinksChecked": 50
}
```

# Actor output Schema

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

No description

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

No description

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

// Run the Actor and wait for it to finish
const run = await client.actor("tanod/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://example.com",
        "https://tanod.dev",
    ] }

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

```

## MCP server setup

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