DEV Community

Batulzii Ulziikhuu
Batulzii Ulziikhuu

Posted on

Free SEO Audit Crawler API: Automate Technical SEO Checks with JavaScript or Python

Desktop crawlers like Screaming Frog are excellent, but they're manual: open the app, crawl, export, repeat. If you manage several sites, run an agency, or want SEO checks in CI after every deploy, you want an SEO audit crawler you can call as an API and get JSON back.

This guide shows how to do that with the SEO Audit Toolkit on Apify, from JavaScript, Python and curl, and how to turn the results into automated alerts.

What the audit checks

For every crawled page:

  • Title and meta description: missing, too short/long, duplicates across the site
  • H1: missing or multiple
  • Canonical, noindex / robots meta (including none), hreflang
  • Structured data (JSON-LD/schema.org) and Open Graph tags
  • Image alt text, word count / thin content
  • Broken internal and external links (HTTP status checks)
  • HTTP errors and redirect problems

Site-wide:

  • robots.txt parsing (including "blocks all crawlers" detection)
  • sitemap.xml validation (index sitemaps, URL counts, invalid XML)
  • Tech stack detection
  • Optional Google PageSpeed / Lighthouse scores with your own API key

You get a 0–100 site score plus a prioritized issue list with example URLs, so you know what to fix first.

Is it free?

Honestly: almost. You pay per page audited ($0.004 per page on Apify's Free plan, down to $0.0015 on paid plans) plus a tiny start fee. A 50-page audit is about $0.20. Apify's free plan includes monthly credits, so small sites and testing effectively cost nothing out of pocket. The summary record and unreachable-URL errors are free, and you can cap spend per run.

Step 1: API token

Create an account at apify.com, copy your token from Settings → API & Integrations:

export APIFY_TOKEN=your_token
Enter fullscreen mode Exit fullscreen mode

Step 2: Run an audit with JavaScript

npm install apify-client
Enter fullscreen mode Exit fullscreen mode
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const run = await client.actor('batuweb/seo-audit-toolkit').call({
  startUrls: ['https://example.com'],
  crawlMode: 'sitemap',   // or crawl links from the start URL
  maxPages: 50,
  checkBrokenLinks: true,
  maxLinkChecks: 200,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
const summary = items.find((i) => i.type === 'summary'); // summary is the last record
console.log('Score:', summary.score);
for (const issue of summary.prioritizedIssues.slice(0, 10)) {
  console.log(`${issue.severity.padEnd(8)} ${issue.code} (${issue.pages} pages) e.g. ${issue.exampleUrls[0]}`);
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Python

pip install apify-client
Enter fullscreen mode Exit fullscreen mode
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("batuweb/seo-audit-toolkit").call(run_input={
    "startUrls": ["https://example.com"],
    "maxPages": 100,
})

items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
summary = next(i for i in items if i.get("type") == "summary")
pages = [i for i in items if i.get("type") == "page"]

print("Site score:", summary["score"], "| pages:", summary["pagesAudited"])
print(summary["issuesBySeverity"])
Enter fullscreen mode Exit fullscreen mode

Step 4: curl / no-code

curl -X POST \
  "https://api.apify.com/v2/acts/batuweb~seo-audit-toolkit/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls":["https://example.com"],"maxPages":20}'
Enter fullscreen mode Exit fullscreen mode

The same endpoint works from n8n, Make, Zapier or Google Sheets (Apps Script UrlFetchApp).

Output example (summary record)

{
  "type": "summary",
  "score": 97,
  "pagesAudited": 10,
  "pagesFailed": 0,
  "issuesBySeverity": { "critical": 0, "high": 1, "medium": 2, "low": 11 },
  "prioritizedIssues": [
    { "code": "BROKEN_INTERNAL_LINKS", "severity": "high", "pages": 1, "exampleUrls": ["https://example.com/about/"] },
    { "code": "TITLE_TOO_SHORT", "severity": "medium", "pages": 2, "exampleUrls": ["https://example.com/contact/"] }
  ],
  "robotsTxt": { "https://example.com": { "status": 200, "blocksAllCrawlers": false } },
  "sitemaps": [{ "url": "https://example.com/sitemap-0.xml", "status": 200, "valid": true, "urlCount": 51 }]
}
Enter fullscreen mode Exit fullscreen mode

Each page also gets its own record with all checks and issues, which is handy for spreadsheets.

Automation ideas

  1. SEO regression check in CI: run after deploy and fail the pipeline if the score drops or a critical issue appears:
if (summary.issuesBySeverity.critical > 0 || summary.score < 85) process.exit(1);
Enter fullscreen mode Exit fullscreen mode
  1. Weekly client reports: an Apify schedule per client site, with a webhook to Slack or email.
  2. Broken-link monitoring across a portfolio of sites.
  3. Pre-migration baselines: audit before and after a redesign and diff the page records.
  4. AI agents: call it via the Apify MCP server so an assistant can audit a URL on request.

Honest limitations

  • It is an HTML crawler, not a headless browser. Content rendered only by client-side JavaScript may be missed.
  • PageSpeed/Lighthouse metrics need your own free Google API key and cost extra per page.
  • The score is a heuristic for prioritization, not a Google ranking factor.
  • Only audit sites you own or have permission to audit. Private/internal network addresses are blocked by design.

FAQ

How is this different from Screaming Frog? Screaming Frog is a powerful desktop app. This is a lightweight cloud API for automation, scheduling and integrations. Many people use both.

How many pages can I audit? Set maxPages. Cost scales linearly, and you can set a maximum cost per run.

Can I export CSV? Yes, any Apify dataset downloads as CSV, Excel or JSON.

Related tools

Disclosure: I built the SEO Audit Toolkit Actor.

Top comments (0)