# Bulk On-Page SEO Audit - 26 Checks, Meta Robots, Hreflang (`smiling_jubilance/website-seo-tech-audit`) Actor

On-page SEO audit and technical SEO audit at scale: meta robots, canonical tag, hreflang, XML sitemap, redirect chain, heading hierarchy, image alt and page speed. 0-100 score, severity-ranked issues, 235-signature tech detection. Pure HTTP, no browser.

- **URL**: https://apify.com/smiling\_jubilance/website-seo-tech-audit.md
- **Developed by:** [Lake Sky](https://apify.com/smiling_jubilance) (community)
- **Categories:** SEO tools, Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $13.00 / 1,000 page auditeds

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

### What is Bulk On-Page SEO Audit?

**Bulk On-Page SEO Audit** crawls a list of pages and scores each one across **26 on-page checks**,
then hands back a **0–100 score**, a letter grade, and a severity-ranked issue list you can act on.

It is deliberately **pure HTTP — no headless browser**. That single design choice is why it runs at
roughly **12,000 pages per hour** instead of a few hundred, and why it is affordable enough to point
at an entire sitemap rather than a handful of landing pages.

Every page also gets **technology detection** from 235 signatures, so the same run tells you which
CMS, analytics, payment and tag-manager stack sits behind the site.

Pages that fail to fetch are still returned with their `httpStatus` and an error field — the run
stays successful, you see a complete record, and **you are not charged for them**.

### What can this Actor do?

- ✅ **26 on-page checks** — titles, meta description, headings, canonical, robots directives,
  Open Graph, images, links, language, viewport and more
- ✅ **0–100 score with a letter grade** so you can rank pages against each other at a glance
- ✅ **Severity-ranked issues** — every finding carries a severity, so fixes sort themselves
- ✅ **Tech stack detection** (235 signatures) with a tunable confidence floor
- ✅ **Sitemap input** — point it at a `sitemap.xml` and let it expand the URL list
- ✅ **No browser** — cheap, fast and stable at thousands of pages per hour
- ✅ Runs on the Apify platform: schedule it weekly, push results through a webhook, or pull the
  dataset from the API — monitoring, retries and storage are handled for you

### How to use it

1. Open the **Input** tab.
2. Add pages to `startUrls`, or paste plain URLs into `urls`, or point `sitemapUrls` at one or more
   `sitemap.xml` files.
3. Set `maxPages` to the ceiling you are willing to pay for (default `20000`).
4. Click **Start** and collect the dataset as JSON, CSV or Excel.
5. Sort by `score` ascending to get your worst pages first.

```json
{
  "startUrls": [{ "url": "https://example.com" }],
  "concurrency": 24,
  "maxPages": 20000,
  "includeTechStack": true
}
```

### Pricing

This Actor is **pay-per-event**. You are billed **per page successfully audited** — never per request,
never per minute, and never for pages that could not be fetched.

| Event | When it is charged | Price |
|---|---|---|
| **Page audited** | A page was fetched, parsed and scored | **$25** per 1,000 pages ( = $0.025 each ) |
| **Actor start** | Once per run, per GB of memory | **$0.00005** per GB |

Pages that fail to fetch or produce no output are **not charged**. Apify's BRONZE, SILVER, GOLD,
PLATINUM and DIAMOND plans reduce the unit price automatically.

Rough budgeting, assuming every page audits successfully:

| Pages in | Cost |
|---|---|
| 1,000 | $25 |
| 5,000 | 5 × $25 |
| 10,000 | 10 × $25 |

If half your URLs 404, your real bill is roughly half of that.

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `startUrls` | array | example.com | Request objects, e.g. `{ "url": "..." }` |
| `urls` | array | empty | Plain URL strings |
| `sitemapUrls` | array | empty | Sitemaps to expand into page URLs |
| `concurrency` | integer | `24` | Parallel page fetches |
| `timeoutMs` | integer | `12000` | Per-request timeout |
| `maxPages` | integer | `20000` | Hard cap per run |
| `includeTechStack` | boolean | `true` | Run technology detection |
| `minTechConfidence` | integer | `60` | Minimum confidence for a tech match |

### Output

One dataset item per audited page:

```json
{
  "inputUrl": "https://example.com",
  "finalUrl": "https://example.com/",
  "httpStatus": 200,
  "score": 82,
  "grade": "B",
  "issues": [
    { "check": "meta-description", "severity": "medium", "message": "Missing meta description" }
  ],
  "techs": [{ "name": "Cloudflare", "category": "cdn", "confidence": 90 }]
}
```

Unreachable pages keep `inputUrl` and `httpStatus` and add an `error` field, so nothing silently
disappears from your report.

### Other Actors you may like

- **[Bulk Tech Stack Detector - BuiltWith/Wappalyzer Alternative](https://apify.com/store)** — a deeper technology
  fingerprint when you only care about the stack, not the SEO score.
- **[Bulk Email Verifier](https://apify.com/store)** — clean the contact list you are about to email.
- **[ATS Job Board Feed Sync - Greenhouse, Lever, Ashby](https://apify.com/store)** — track career pages across every major ATS.

### FAQ

**Do I need a browser to audit JavaScript-rendered pages?** No, and that is the trade-off: this Actor
reads the server's HTML. That covers the overwhelming majority of on-page SEO issues and is what makes
the throughput — and the price — possible.

**What does the score mean?** It is a weighted 0–100 composite across all 26 checks, mapped to a
letter grade. Use it to rank pages against each other, not as an absolute SEO guarantee.

**Can I audit a whole site?** Yes — pass the `sitemapUrls` field and raise `maxPages`. Start with a
small `maxPages` on the first run to see what a full site costs you.

**What if a page times out?** It is returned with an `error` field and is not billed.

# Actor input Schema

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

要审计的页面 URL 列表。可写完整 URL，也可只写域名（会自动补 https://）。

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

纯字符串 URL 数组，供 API 直接调用时用（与 startUrls 等价，会合并去重）。

## `sitemapUrls` (type: `array`):

sitemap.xml 地址，会自动展开为页面 URL（支持 sitemap index，最多递归 20 个子 sitemap）。

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

并发抓取数。实测 24 并发 ≈ 9,400 页/小时；超过 32 收益递减且易被目标站限流。

## `timeoutMs` (type: `integer`):

单页抓取超时。调低可显著提高大批量任务的吞吐。

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

单 run 最大页数硬上限，防止超时后「没产出却已扣费」。建议 ≤ (超时秒数 × 2.6)。

## `includeTechStack` (type: `boolean`):

是否附送技术栈识别（235 条签名 / 19 类，含资产级证据）。关闭可略微提速。

## `minTechConfidence` (type: `integer`):

技术栈置信度阈值，低于此值不输出。实测 60 为精确率/召回率的平衡点。

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://example.com"
    },
    {
      "url": "https://apify.com"
    }
  ],
  "urls": [],
  "sitemapUrls": [],
  "concurrency": 24,
  "timeoutMs": 12000,
  "maxPages": 20000,
  "includeTechStack": true,
  "minTechConfidence": 60
}
```

# Actor output Schema

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

Per-page record: inputUrl, finalUrl, httpStatus, score, grade, issues (severity-ranked), techs (detected signatures).

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

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

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

```

## MCP server setup

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