# SEO Site Audit & Broken Link Checker — Meta Tags & Fix List (`signalloom/seo-site-audit`) Actor

Audit a whole website for SEO problems and broken links from its homepage: reads the sitemap, scores every page and returns a fix list (title, meta description, H1, canonical, noindex, structured data, alt text, speed) plus a site summary. $0.02 per page. Respects robots.txt.

- **URL**: https://apify.com/signalloom/seo-site-audit.md
- **Developed by:** [Signalloom](https://apify.com/signalloom) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.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.

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 Site Audit & Broken Link Checker: Meta Tags & Fix List

**Audit an entire website for on-page SEO problems** in one run. Give it a homepage: it finds the pages from the sitemap, checks each one against 25+ SEO rules, tests the links, and returns a **score and a prioritized fix list for every page**, plus a **site summary** of the most common problems.

- **Whole site, not one URL at a time**: pages come from the sitemap (including sitemap indexes and .gz sitemaps), or by following internal links, or from your own list
- **25+ checks per page**: title and meta description (missing, too long, too short, duplicated), H1 (missing or multiple), canonical, noindex (meta and X-Robots-Tag), mobile viewport, `lang`, image alt text, thin content, Open Graph, structured data (and broken JSON-LD), mixed content, slow responses, redirects
- **Broken links**: internal and outgoing links are tested; 404s, 500s and dead domains are reported with the pages they're on. Social networks that block automated checks aren't falsely reported as broken.
- **Fix list ready to hand to a developer**: every issue has a severity (error, warning, notice), a code and a plain-English message, sorted worst first
- **Site summary**: site score, top issues by number of pages affected, duplicate titles, broken links, sitemaps found, robots.txt
- **Polite crawling**: respects robots.txt by default. Fast: no browser needed.

**Price: $0.02 per audited page**; site summaries are free. The prefilled example (5 pages) finishes in under a minute for about $0.10.

### Use this when…

- you need an **SEO audit** of a whole website, not a single page
- you want a **broken link checker** that finds 404s, 500s and dead domains, with the pages they're on
- you need to **check meta tags** in bulk: missing, duplicated, too long or too short titles and meta descriptions, plus Open Graph and canonical tags
- you want a developer-ready **fix list** sorted by severity, or a site score to compare before and after a release
- an agency, script or AI agent needs SEO problems for many sites in one structured dataset

### For AI agents

- **Run** `signalloom/seo-site-audit` (Apify MCP server `call-actor`, or the Apify API) with input like `{"startUrls": ["https://www.example.com"], "maxPagesPerSite": 10}`
- **Returns** one JSON row per page in the default dataset (`recordType: "page"`: `url`, `score`, `issues` sorted worst first, `issueCodes`, `title`, `metaDescription`, `h1`, `brokenInternalLinks`) plus one `recordType: "site"` summary row (`siteScore`, `topIssues`, `brokenLinks`, `duplicateTitles`).
- **Typical cost:** 10 pages = **$0.20** ($0.02 per audited page; site summary free). Without `maxPagesPerSite` the default is 50 pages (up to $1.00).

### Who is it for?

- **SEO agencies and freelancers**: audit prospects' sites in bulk and open the sales call with a concrete fix list
- **Site owners and marketers**: a monthly health check of your own site; schedule it and compare scores
- **Developers**: catch broken links, missing titles and accidental noindex before and after a release
- **Lead-gen teams**: combine with a list of domains to find businesses with obvious SEO problems

### How to use it

1. Add websites (`https://www.example.com`) or specific pages to **Websites or pages**.
2. Set **Max pages per site** (you pay per audited page).
3. Click **Start**. Use the **Pages (worst first)** view for the fix list and **Site summaries** for the overview. Export to CSV, Excel or JSON.

**Recipe: agency prospecting.** Add 50 prospect homepages, Max pages per site 10. Sort the site summaries by `siteScore` and lead with each site's `topIssues`.

**Recipe: release check.** Schedule a weekly run on your own site with Max pages 500. Alert on any page with `errors > 0`.

### Output

One record per page (real example, from a public test site), plus one `recordType: "site"` summary per site:

```json
{
  "url": "https://the-internet.herokuapp.com/status_codes",
  "httpStatus": 200,
  "responseMs": 113,
  "title": "The Internet",
  "titleLength": 12,
  "metaDescription": null,
  "h1Count": 0,
  "canonical": null,
  "indexable": true,
  "lang": "en",
  "hasViewport": true,
  "structuredDataTypes": [],
  "wordCount": 74,
  "images": 1,
  "imagesMissingAlt": 0,
  "internalLinks": 5,
  "externalLinks": 4,
  "brokenInternalLinks": [
    { "url": "https://the-internet.herokuapp.com/status_codes/404", "status": 404 },
    { "url": "https://the-internet.herokuapp.com/status_codes/500", "status": 500 }
  ],
  "score": 77,
  "errors": 1,
  "warnings": 2,
  "notices": 5,
  "issues": [
    { "severity": "error", "code": "BROKEN_INTERNAL_LINKS", "message": "2 link(s) to your own site are broken." },
    { "severity": "warning", "code": "META_DESCRIPTION_MISSING", "message": "Missing meta description; Google will pick text from the page." },
    { "severity": "warning", "code": "H1_MISSING", "message": "No <h1> heading." },
    { "severity": "notice", "code": "TITLE_TOO_SHORT", "message": "Title is only 12 characters." }
  ]
}
```

Page records also include `metaDescriptionLength`, `headings` (h1–h4 counts), `noindex`, `nofollow`, `hreflang`, `openGraph`, `twitterCard`, `htmlBytes`, `nofollowLinks` and `brokenExternalLinks`.

**Score:** 100 minus 10 per error, 4 per warning and 1 per notice. The site score is the average over audited pages.

### Pricing

- **$20 per 1,000 pages** audited ($0.02 each), link checks included
- Site summaries are free
- Pages that can't be loaded (dead domain, network error) or that are blocked by bot protection are **free**: they're listed in the site summary under `notLoaded`, not audited as if real
- Each page is audited and charged once, even if it's reached by several URLs (e.g. `example.com` redirecting to `https://www.example.com/`)

### Limitations

- Pages are analyzed from their HTML, without running JavaScript. Sites that build their content entirely in the browser may show missing titles or text. Most sites, including Shopify, WordPress and modern frameworks with server rendering, are fine.
- Speed is measured as server response time, not a full Core Web Vitals / Lighthouse test.
- Link checking is capped per site (**Max links to check per site**). Links on sites that block automated checks are skipped, not reported as broken.
- This is an on-page audit: it doesn't measure backlinks, rankings or traffic.

### FAQ

**How do I find all broken links on my website?**

Put your homepage in **Websites or pages** and run. The Actor reads your sitemap, tests every internal and outgoing link on the audited pages, and lists each broken link (404, 500, dead domain) with the pages it appears on, in the site summary's `brokenLinks`.

**How can I check the meta title and description of every page at once?**

Each page row has `title`, `titleLength`, `metaDescription` and `metaDescriptionLength`, and issues such as `TITLE_TOO_LONG`, `META_DESCRIPTION_MISSING` or duplicate titles. Export to CSV or Google Sheets.

**Can I run an SEO audit automatically every week?**

Yes. Schedule the Actor weekly or monthly in Apify and compare `siteScore` and `topIssues` between runs, or alert on any page with `errors > 0`.

**Can it audit many websites in one run?**

Yes. Add as many homepages as you like; each gets its own pages and its own site summary row. Agencies use it for prospect audits.

**Does it render JavaScript?**

No. Pages are analyzed from their HTML, which is what most search crawlers read first. Server-rendered sites (Shopify, WordPress, most frameworks) are fully covered.

### Feedback

Want another check added? Open an issue on the **Issues** tab.

# Actor input Schema

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

A site's homepage to audit the whole site (pages are found from its sitemap), or specific page URLs. Several sites can be audited in one run. Example: \["https://www.example.com"] (whole site) or a list of page URLs with discovery "pages".

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

How many pages to audit per site. You pay per audited page. Example: 10 for a quick check ($0.20); the default 50 costs up to $1 per site.

## `discovery` (type: `string`):

"Sitemap" reads the site's sitemap (falls back to following links if there isn't one). "Follow links" crawls internal links from the start URLs. "Only the URLs I give" audits just your list. API values: "sitemap", "links", "pages".

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

Test the links on audited pages and report the broken ones (404s, dead domains).

## `checkExternalLinks` (type: `boolean`):

Also check outgoing links. Sites that block automated checks (e.g. LinkedIn) are skipped, not reported as broken.

## `maxLinkChecksPerSite` (type: `integer`):

Upper limit on how many unique links are tested per site. 0 = don't check links. Example: 300.

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

Skip pages the site's robots.txt asks crawlers not to visit.

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

How many pages to fetch at the same time per site.

## Actor input object example

```json
{
  "startUrls": [
    "https://books.toscrape.com"
  ],
  "maxPagesPerSite": 5,
  "discovery": "sitemap",
  "checkBrokenLinks": true,
  "checkExternalLinks": true,
  "maxLinkChecksPerSite": 300,
  "respectRobotsTxt": true,
  "maxConcurrency": 4
}
```

# Actor output Schema

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

No description

## `siteSummaries` (type: `string`):

No description

## `runSummary` (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 = {
    "startUrls": [
        "https://books.toscrape.com"
    ],
    "maxPagesPerSite": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("signalloom/seo-site-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://books.toscrape.com"],
    "maxPagesPerSite": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("signalloom/seo-site-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://books.toscrape.com"
  ],
  "maxPagesPerSite": 5
}' |
apify call signalloom/seo-site-audit --silent --output-dataset

```

## MCP server setup

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