SEO Audit Tool - SEO Checker, Site Audit & Core Web Vitals avatar

SEO Audit Tool - SEO Checker, Site Audit & Core Web Vitals

Pricing

Pay per event

Go to Apify Store
SEO Audit Tool - SEO Checker, Site Audit & Core Web Vitals

SEO Audit Tool - SEO Checker, Site Audit & Core Web Vitals

SEO crawler for technical SEO audits, JS sites too: 0-100 SEO score and fix hints per page, site report (duplicate titles, broken pages, missing H1, meta, alt), optional Core Web Vitals. $5/1k pages.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Yukai Lin

Yukai Lin

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 hours ago

Last modified

Share

What does SEO Audit Tool do?

SEO audit tool for $5 per 1,000 pages: it crawls your site, scores audited pages from 0 to 100 and lists on-page and technical SEO issues with fix hints, plus a site report (sitemap, canonicals, duplicates, broken pages). Broken, blocked and failed pages are free. Cloudflare email-protection helper links found within pages are skipped.

Why this one

  • $5 per 1,000 pages, compute included, no start fee. The most used SEO audit Actor on the Store, smart-digital/complete-seo-audit-tool, charges $40 per 1,000 pages (comparison, checked 2 October 2026). scrapesignal_labs is cheaper per page ($0.50) but bills platform usage on top and has no browser fallback (all prices).
  • Works on JavaScript sites and sites that block bots: a second network, then a real browser. The two most used SEO audit Actors read static HTML only.
  • A fix hint for every issue, category scores, and site checks: sitemap cross-check, canonical and redirect targets, duplicate titles and content, hreflang return links, broken internal pages with the page that links to them.
  • Broken, blocked, failed and timed-out pages are free. Every row says charged: true/false.
  • Core Web Vitals without an API key (optional, $5 per 1,000 pages measured) and run-to-run comparison for weekly monitoring.

Input (copy and paste)

{
"urls": ["https://www.python.org/"],
"maxPages": 20
}

Output (real result, shortened)

One page of a real 20-page python.org run. The whole run costs $0.10 on the Free plan (20 × $0.005), and its site report gave an average score of 94.4:

{
"url": "https://www.python.org/",
"success": true,
"score": 93,
"issueCount": 2,
"issues": [
{ "id": "h1-multiple", "severity": "warning", "message": "Page has 5 H1 headings.", "category": "headings",
"fixHint": "Keep a single main H1 and turn the others into H2 headings.", "impact": "medium" },
{ "id": "canonical-missing", "severity": "notice", "message": "Canonical link is missing.", "category": "indexing",
"fixHint": "Add <link rel=\"canonical\"> pointing to the preferred URL of this page (usually itself).", "impact": "low" }
],
"categoryScores": { "technical": 100, "indexing": 94, "meta": 100, "headings": 85, "images": 100, "social": 100, "...": 100 },
"title": "Welcome to Python.org",
"wordCount": 1182
}

All fields: Output: one item per page. The site report: Output: site report.

For mixed-content and no-https-redirect, an issue may include machine-readable evidence to check the finding. Other issues do not necessarily have this field.

How much does it cost?

EventPrice
Audited page$5.00 / 1,000 pages
PageSpeed measurement (optional)$5.00 / 1,000 pages measured

Example: auditing a 1,000-page site costs 1,000 × $0.005 = $5.00 on the Free plan; PageSpeed on 50 of those pages adds 50 × $0.005 = $0.25.

No start fee. Broken pages, failed pages and the site checks (sitemap, canonical targets, image checks, structured data, run-to-run comparison) are free. PageSpeed measurements are only charged when a score comes back. Your maximum charge limit is always respected.

Features

SEO audit tool that crawls your website and checks discovered content pages for on-page and technical SEO problems, including sites built with JavaScript or protected against bots: when a site blocks plain requests, the page is fetched from a second network or audited in a real browser automatically, and a page that loads almost empty until JavaScript runs (a client-rendered app shell) is rendered in a real browser too. Each audited page gets a score from 0 to 100, category scores and a list of issues with a fix hint for every issue. The whole site gets a report: score distribution, most common problems, crawl coverage (indexable / noindex / canonicalized / 4xx / 5xx), sitemap checks, canonical and redirect problems, duplicate titles, H1s and content, and broken internal pages.

25+ checks per page, including:

  • 🏷️ Title: missing, too short, too long (search results cut titles at about 60 characters)
  • 📝 Meta description: missing, too short, too long
  • 🔠 Headings: missing, empty or multiple H1s, skipped heading levels (H2 → H4), full heading outline
  • 🔗 Canonical & indexing: missing or conflicting canonical, noindex or none in meta robots or the X-Robots-Tag header, pages that robots.txt blocks for Googlebot
  • 🖼️ Images: images without an alt attribute (alt="" on decorative images is correctly accepted); optional check for broken and oversized images
  • 🌍 hreflang: invalid codes (en-UK, jp), missing x-default, missing self-reference, duplicate codes, broken or redirecting targets, missing return links
  • 📱 Mobile & language: viewport tag, lang attribute
  • 🌐 Social & structured data: Open Graph title/image, Twitter card, and JSON-LD and Microdata validated against Google's rich result rules (errors, eligible rich results; RDFa types listed)
  • ⚙️ Technical: HTTP status, HTTPS, an HTTP start URL that does not redirect to HTTPS, mixed content (HTTP images, scripts or stylesheets on an HTTPS page), redirect chains, slow server response, very large HTML, thin content (word count; Chinese and Japanese text, written without spaces, is estimated from its length)
  • 💔 Broken pages: internal links that return 404/410/5xx, with the page that links to them. A page-discovered link whose path is exactly /cdn-cgi/l/email-protection is skipped, with or without a fragment, because it is Cloudflare's email helper rather than a content page. Other broken URLs and an explicitly entered helper start URL are handled normally.

Site-level checks (in the report):

  • 🗺️ Sitemap: no sitemap found, sitemap URLs that return errors, redirect or are noindex, crawled indexable pages missing from the sitemap
  • ↪️ Canonical tags that point to an error page, a redirect or a noindex page
  • 🔁 Internal links that point to a redirect instead of the final URL
  • 👯 Duplicates: titles, meta descriptions, H1s and identical page text (duplicate content)
  • 📊 Crawl coverage: indexable, noindex, canonicalized, redirected, 4xx, 5xx, blocked by robots.txt, deepest page

Optional:

  • ⚡ Core Web Vitals with Google PageSpeed Insights, no API key needed: performance score, LCP, CLS, TBT, FCP and real-user INP for the pages you choose ($5 per 1,000 pages measured)
  • 📈 Monitoring: compare with the previous run and see issues added or resolved per page and the score change

Why use it?

  • Works on JavaScript sites and sites that block bots. Many SEO crawlers analyze static HTML only; this one falls back to a real browser automatically when a site blocks plain requests or a page has almost no text until JavaScript runs.
  • A fix hint for every issue, plus category scores (technical, indexing, meta, headings, content, links, images, social, schema, performance, mobile, international).
  • $5 per 1,000 pages, no extra compute charges. See the price comparison below.
  • Pay only for audited pages: broken pages are reported for free; blocked pages, pages skipped by robots.txt and downloads are not charged.
  • Built for recurring checks: schedule it weekly with Compare with the previous run to get issues added and resolved per page, score changes and new broken pages, or feed the JSON into your dashboard.

Cost control and price comparison

Control your cost

  • Charged: one Audited page event per HTML page audited (charged: true on the row); PageSpeed only when a score comes back.
  • Free (charged: false, the error ends with "(not charged)"): invalid input lines (errorType: "invalid_input"), broken internal pages (a finding), blocked, failed and timed-out pages, downloads (PDF, images) and pages skipped by robots.txt. A start URL that is skipped or is not an HTML page still gets a row (errorType: "robots_txt" or "unsupported"); downloads found while crawling are skipped without a row.
  • Before it starts, the run logs its plan: Max pages × price (plus PageSpeed pages if on) is the most it can cost, compared with your maximum charge per run (run options). Small sites have fewer pages and cost less. The plan is saved as costPlan in SUMMARY.
  • When the maximum is reached, the run stops: the status message says so, SUMMARY.status is LIMIT_REACHED and SUMMARY.notProcessed has the number of pages found but not audited and the first 100 of them.
  • If Apify restarts the run (server migration or Resurrect), pages audited before it are read again for the report but not charged again and not written to the dataset twice (SUMMARY.resumed).

Price comparison (checked October 2026)

ActorTotal price for 1,000 pages (Free plan)Crawls the siteReal-browser fallback
SEO Audit Tool (this Actor)$5.00, nothing else: no start fee, compute includedYesYes
smart-digital/complete-seo-audit-tool$40.00YesNo (static HTML)
logiover/website-seo-audit-crawler$10.00 + $0.00005 start feeYesNo (plain HTTP only)
autofacts/metadata-scraper$5.00; the max charge per run must be set to at least $0.10Only with followLinks (off by default)No (no JavaScript)
scrapesignal_labs/website-seo-audit$0.50 + $0.00005 start fee + platform usageYesNo

A 1,000-page audit with this Actor costs $5, which the Apify Free plan's $5 monthly credit covers.

We are not the cheapest: scrapesignal_labs costs less per page, but you also pay the Apify compute it uses, and it has no browser fallback. At $5 this Actor is the one with a real-browser fallback, a fix hint per issue and site-level checks (sitemap, canonical targets, duplicates, hreflang return links). For PageSpeed, lizaraco/site-audit charges $10 per 1,000 measurements; this Actor charges $5.

Switching from another SEO audit Actor

Already running an SEO audit Actor? You can keep most of your input: this Actor also accepts the field names other SEO audit Actors use and maps them to its own. The run log lists every mapping ("Input: ...").

Their fieldRead here as
startUrls as [{ "url": ... }], or url / startUrl (one URL)Start URLs
maxRequestsPerCrawl, maxPagesToCrawl, maxCrawlPages, maxPagesPerCrawlmaxPages
crawlScope: "same-domain" / "same-hostname"domain / host
followLinks: false or crawlPages: falseOnly the start URLs
includeSubdomains: true / falseWhole website / Only this host
maxPages together with crawlPages or includeSubdomains (a per-site limit there)maxPagesPerSite, so several sites get the same pages each as before
excludeUrlPatterns: ["/tag/"] (a URL fragment)the glob **/tag/**
proxyproxyConfiguration
auditSchema: falsestructured data validation off
Per-check switches (auditImages, extractMetaTags, ...) and useProxyignored: every check always runs, at the same price

maxDepth, maxConcurrency, respectRobotsTxt and excludeUrlPatterns have the same names here. One difference: if your startUrls is a list of plain strings (["https://example.com"]), rename it to urls, because Apify only accepts { "url": ... } objects in startUrls.

Compared with the two most-used SEO audit Actors (Apify Store, checked 2 October 2026)

SEO Audit Tool (this Actor)smart-digital/complete-seo-audit-toolautofacts/metadata-scraper
Price per 1,000 pages (Free plan)$5.00$40.00$5.00
With a paid Apify plan$4.50 (Silver), $4.00 (Gold and up)$35.00 (Silver), $30.00 (Gold and up)$3.50 (Silver), $3.00 (Gold and up)
Start fee / platform usageNone / includedNone / includedNone / included; max charge per run at least $0.10
Failed pages charged?No: broken, blocked, failed and timed-out pages are freeNot stated in its READMENo: failed URLs are not charged
Crawls the whole site by defaultYesYes (5 pages per start URL by default)No: only with followLinks (off by default)
JavaScript sites / sites that block botsYes: second network, then a real browserNo: static HTML; anti-bot sites out of scopeNo: no JavaScript
Fix hint per issueYesYesIssues with severity and the recommended value
Site checksSitemap cross-check, canonical and redirect targets, duplicates, hreflang return links, broken pagesSitemap discovery, robots.txt, duplicate titles and descriptions, redirects, broken linkshreflang, local-business data
Core Web VitalsOptional, Google PageSpeed Insights (lab data, plus real-user data when Google has it), $5 per 1,000 pagesLab timings measured during the crawl, includedNo
Compare with the previous runYes (issues added and resolved, score change)Not mentioned in its READMENot mentioned in its README
Not in this ActorReadability, keyword density, title width in pixels, basic accessibility checksFull schema.org extraction (RDFa, hCard)

Prices are the Store's pay-per-event prices on the date above; check each Actor's Pricing tab for the current rate.

Paste your existing input. A typical input from another SEO audit Actor runs here unchanged, except that a list of plain strings in startUrls goes in urls:

{
"urls": ["https://example.com", "https://example.org"],
"crawlPages": true,
"maxPages": 20,
"includeSubdomains": false,
"respectRobotsTxt": true,
"excludeUrlPatterns": ["/tag/", "/author/"]
}

This audits up to 20 pages of each site on its own host, skips URLs containing /tag/ or /author/ and respects robots.txt: at most 40 pages, $0.20 on the Free plan. An input with startUrls: [{ "url": ... }], followLinks, maxDepth and maxRequestsPerCrawl, or with crawlScope: "same-domain" and maxPagesToCrawl, also runs as it is.

How to use it

  1. Enter your website URL in URLs or domains, e.g. https://www.example.com/ or just example.com (one per line for several sites). A bad line never stops the run: it becomes a row with errorType: "invalid_input" (not charged).
  2. Set Max pages (100 is a good start).
  3. Optional: turn on Also audit pages from the sitemap, Respect robots.txt, Check images, Measure Core Web Vitals or Compare with the previous run, or limit the crawl with include/exclude URL patterns.
  4. Click Start. Open Site report in the Output tab for the summary, or the Pages, Issues and fixes and Category scores tables for details.

The prefilled input audits two sites in one run (python.org and books.toscrape.com, 20 pages shared between them): $0.10, usually done in about a minute, and the REPORT has a per-site table comparing them. Replace them with your own sites.

Input example

{
"urls": ["https://www.python.org/"],
"crawlScope": "domain",
"maxPages": 100,
"useSitemap": true,
"excludeUrlPatterns": ["**/blog/tag/**"]
}

Crawl scope: Whole website includes subdomains (blog.example.com, shop.example.com); Only this host stays on the start URL's host (www. and the bare domain count as one); Same folder and Only the start URLs narrow it further. With Same folder, a start page that links to nothing inside its own folder (sites that give every page its own folder, such as /en/getting-started/) is audited with the folder one level up (/en/, never the whole site), listed in SUMMARY scopeWidened.

Use urls (a plain list of strings) in API calls. The older startUrls field ([{ "url": "https://…" }]) still works and can hold uploaded or linked URL list files, but Apify rejects the whole request with HTTP 400 if one of its entries is a bare domain or a blank line.

Several sites in one run (agencies). Put one site per line in URLs or domains. Max pages is shared fairly: each site gets its share (Max pages ÷ number of sites) while the others are still being crawled, and a small site leaves its unused share to the others. Set Max pages per site for a fixed cap. Every row has site (host without www.) and startUrl, the sitemap of every site is read (up to 20 sites), SUMMARY.sites has one entry per site (pagesAudited, averageScore, brokenPages, pagesFailed, sitemapFound, sitemapUrls) and the REPORT has a Per site table. Real run (September 2026, maxPages: 12): python.org, books.toscrape.com and webscraper.io got 4 pages each.

{
"urls": ["https://www.python.org/", "books.toscrape.com", "https://webscraper.io/"],
"maxPages": 12
}

Output: one item per page

For an HTTPS page with HTTP images, scripts or stylesheets, issues[] includes one mixed-content issue with evidence.pageUrl, up to three evidence.resourceUrls, and evidence.totalResources (the full detected count). For an HTTP start URL that remains HTTP, no-https-redirect includes evidence.startUrl and evidence.finalUrl. Evidence URLs omit query strings, fragments and URL credentials. For example, http://example.com/a.js?token=abc appears as http://example.com/a.js in resourceUrls. These fields use URLs already collected during the audit; they do not add requests. Other issues may have no evidence field. Scores and billing are unchanged.

Real output for https://www.python.org/ (shortened):

{
"url": "https://www.python.org/",
"site": "python.org",
"startUrl": "https://www.python.org/",
"input": "https://www.python.org/",
"success": true,
"mode": "fast",
"via": "direct",
"score": 93,
"issueCount": 2,
"issueCodes": "h1-multiple, canonical-missing",
"issues": [
{ "id": "h1-multiple", "severity": "warning", "message": "Page has 5 H1 headings.", "category": "headings",
"fixHint": "Keep a single main H1 and turn the others into H2 headings.", "impact": "medium" },
{ "id": "canonical-missing", "severity": "notice", "message": "Canonical link is missing.", "category": "indexing",
"fixHint": "Add <link rel=\"canonical\"> pointing to the preferred URL of this page (usually itself).", "impact": "low" }
],
"categoryScores": { "technical": 100, "indexing": 94, "meta": 100, "headings": 85, "images": 100, "social": 100, "...": 100 },
"httpStatus": 200,
"title": "Welcome to Python.org",
"titleLength": 21,
"metaDescriptionLength": 52,
"h1": ["Intuitive Interpretation", "Compound Data Types", "..."],
"headings": [{ "level": 1, "text": "Intuitive Interpretation" }, "..."],
"canonical": null,
"xRobotsTag": null,
"blockedByRobotsTxt": false,
"viewport": true,
"wordCount": 1182,
"contentHash": "9f824c550ac6dbe88bd0688e",
"bytes": 53229,
"imagesMissingAlt": 0,
"nofollowLinks": 0,
"hreflangLinks": [],
"twitterCard": null,
"structuredDataTypes": ["WebSite"]
}

via tells you where the page was read from: backend (our servers), direct (Apify's network, used when a site blocks our servers), vm (our second server, Oracle, different IP) or browser. Failed pages carry an errorType (blocked, not_found, timeout, network, unsupported, robots_txt…). input (on start pages) is your original line; issueCodes is the issue IDs as one text column for spreadsheets; charged says whether the row was charged.

Output: site report

The key-value store contains REPORT (Markdown, easy to read or share) and SUMMARY (JSON). From the same python.org run (20 pages):

{
"status": "SUCCESS",
"pagesAudited": 20,
"averageScore": 94.4,
"scoreDistribution": { "80-100": 20, "60-79": 0, "40-59": 0, "0-39": 0 },
"categoryAverages": { "technical": 100, "indexing": 94, "meta": 99.7, "headings": 89.5, "...": 100 },
"site": {
"coverage": { "crawled": 20, "indexable": 20, "noindex": 0, "canonicalized": 0, "redirected": 3, "clientErrors4xx": 0, "serverErrors5xx": 0, "blockedByRobotsTxt": 0, "maxDepth": 1 },
"sitemap": { "found": false, "urls": 0 },
"internalLinksToRedirects": [
{ "url": "https://www.python.org/psf/", "finalUrl": "https://www.python.org/psf-landing/", "linkedFrom": "https://www.python.org/" },
{ "url": "https://www.python.org/doc/av", "finalUrl": "https://www.python.org/doc/av/", "linkedFrom": "https://www.python.org/" }
],
"canonicalProblems": [],
"duplicateH1": [],
"duplicateContent": [],
"hreflangProblems": []
}
}

status is SUCCESS, PARTIAL_RESULTS (some pages failed), FAILED, NO_RESULTS or LIMIT_REACHED (stopped at your spending limit). The summary also lists the most common issues (with fix hints), the lowest-scoring pages, duplicate titles and descriptions, and broken internal pages with the page that links to them. It also has sites (one entry per site), invalidInputs, costPlan and, when the run stopped at your limit, notProcessed.

Optional: PageSpeed Insights (Core Web Vitals)

Turn on Measure Core Web Vitals (PageSpeed Insights) to run Google's PageSpeed Insights on the start URL(s) and the next pages audited, up to Max pages to measure (default 5). No setup is needed: without your own key, our servers run Google PageSpeed Insights with our key, and when Google's quota is busy they measure with our own Lighthouse server instead. With your own key, the Actor calls Google directly.

Where to measure from (pagespeedSource): lab results depend on where Lighthouse runs, so you can pick the location. auto (default) uses Google, then our Lighthouse servers; google uses Google only; lighthouse uses our servers only (Taiwan first, then Phoenix, US); lighthouse-tw and lighthouse-us measure from that one location and are never swapped for another (if it is unavailable, the page is reported as not measured and is not charged). Choose Taiwan when your visitors are in Asia. Our servers give lab data only; real-user field data comes from Google. The price is the same for every option.

Each page gets a pagespeed object:

FieldMeaning
performanceScoreLighthouse performance score, 0-100
lcpMs, cls, tbtMs, fcpMs, speedIndexMsLab measurements: Largest Contentful Paint, Cumulative Layout Shift, Total Blocking Time, First Contentful Paint, Speed Index
inpMsInteraction to Next Paint from real-user data (lab tests cannot measure INP), when Google has enough traffic for the page or its site
fieldReal-user (Chrome UX Report) 75th percentiles: lcpMs, inpMs, cls, fcpMs, ttfbMs, category, and source (url or origin)
sourceWho measured: google (Google with our key), vm-lighthouse (our Lighthouse servers: lab data only, no field/inpMs) or google (your key)
node, nodeLocationWith vm-lighthouse: which of our servers measured, tw (Taiwan) or us (Phoenix, US)
ttiMs, opportunitiesTime to interactive and the top savings suggestions (id, title, estimated ms/bytes saved); measured through our servers
error, errorKindWhy a page was not measured (quota, key, page, api, skipped); such pages are not charged

Price: $5 per 1,000 pages measured (pagespeed-audit event), charged only when a score comes back.

Real result (September 2026, mobile, 3 of 5 audited python.org pages measured with pagespeedMaxPages: 3; charged 5 × page audit + 3 × PageSpeed):

{
"url": "https://www.python.org/",
"score": 93,
"pagespeed": {
"strategy": "mobile",
"performanceScore": 78,
"lcpMs": 4802,
"cls": 0.003,
"tbtMs": 0,
"fcpMs": 2718,
"speedIndexMs": 2718,
"inpMs": 88,
"field": { "source": "url", "category": "FAST", "lcpMs": 1225, "inpMs": 88, "cls": 0, "fcpMs": 1158, "ttfbMs": 526 },
"lighthouseVersion": "13.5.0",
"measuredUrl": "https://www.python.org/"
}
}

The lab LCP (4.8 s) is much slower than what real visitors see (field.lcpMs 1.2 s): Lighthouse simulates a slow phone on a throttled mobile network. Use the lab numbers to compare pages and track changes, and the field numbers for what your visitors actually experience. Lab scores also vary a few points between runs.

Optional: use your own Google API key (about 5 minutes)

You do not need a key. Add one only if you want the calls to count against your own Google quota (for example very large runs): put it in Your own Google API key. If our daily capacity is ever used up, the remaining pages are marked errorKind: "quota" and not charged, and adding your key lets you measure them.

  1. Open Google Cloud Console and create a project (no billing account needed).
  2. Enable the PageSpeed Insights API.
  3. Go to APIs & Services → Credentials → Create credentials → API key.
  4. Recommended: edit the key, keep Application restrictions: None (Apify servers have changing IPs) and set API restrictions to PageSpeed Insights API only.
  5. Paste the key into the Actor input. It is stored encrypted.

The API is free; your daily quota is shown in Google Cloud Console under the PageSpeed Insights API's Quotas page.

After a quota or key error the Actor stops measuring for the rest of the run (those pages are not charged). SUMMARY.pagespeed has the average performance score and the pages sorted from slowest, and the REPORT gets a PageSpeed table.

Structured data (JSON-LD and Microdata)

Every page gets a structuredData object checked with the same rules as Schema Markup Validator (by TidyTools): status, formats (json-ld, microdata), types, eligible richResults, errorCount, warningCount, the first errors with code and path, and rdfaTypes (RDFa is detected, not validated). It does not change the page score. Real result from webscraper.io (September 2026), a page marked up with Microdata only:

"structuredData": {
"status": "errors",
"formats": ["microdata"],
"types": ["OfferCatalog", "VideoObject"],
"richResults": [],
"errorCount": 2,
"warningCount": 2,
"errors": [
{ "code": "REQUIRED_MISSING", "type": "VideoObject", "property": "thumbnailUrl", "path": "microdata[1]", "format": "microdata" },
{ "code": "REQUIRED_MISSING", "type": "VideoObject", "property": "uploadDate", "path": "microdata[1]", "format": "microdata" }
],
"rdfaTypes": []
}

Turn off Validate structured data to skip it.

Monitoring: compare with the previous run

Turn on Compare with the previous run and schedule the Actor (for example weekly). Each page gets change (new, changed, unchanged), previousScore, scoreDelta, issuesAdded and issuesResolved. SUMMARY.changes and a Since the last run section in the REPORT show the average score change, issues added and resolved (by issue ID), the biggest score drops and gains, new broken pages, fixed broken pages and pages no longer found. Runs with the same Monitor name are compared (default: start URL + crawl scope). The first run is the baseline. If a run stops before the whole site is crawled (Max pages or spending limit), pages it did not reach are kept and not reported as removed.

Real second run on webscraper.io (September 2026; for the test, the previous snapshot of two pages was edited):

[
{ "url": "https://webscraper.io/", "score": 96, "change": "changed", "previousScore": 90, "scoreDelta": 6,
"issuesAdded": ["structured-data-missing"], "issuesResolved": ["title-missing"] },
{ "url": "https://webscraper.io/pricing", "score": 94, "change": "changed", "previousScore": 100, "scoreDelta": -6,
"issuesAdded": ["canonical-other", "heading-skip", "structured-data-missing"], "issuesResolved": [] }
]

REPORT excerpt from the same run:

## Since the last run
- Average score: **97.3** (+2.3 from 95)
- Issues added: **4**, resolved: **1** on 6 page(s) seen in both runs
- New pages: **0**, pages no longer found: **0**, new broken pages: **0**, broken pages fixed: **1**

Pages are audited and charged the same way with or without monitoring.

Use with AI agents (MCP)

Connect Apify's MCP server (https://mcp.apify.com?tools=tidytools/seo-audit-crawler) to Claude, Cursor or any MCP client, then ask e.g. "Audit the first 50 pages of example.com and list the three fixes that would raise the score most."

{ "urls": ["https://example.com/"], "maxPages": 50 }

Failed pages are not charged and carry an errorType, so the agent can tell a blocked site from a broken page.

Use it from code and integrations

Run it from your own code with the Apify API. This call waits for the run and returns the results as JSON (replace YOUR_TOKEN with your Apify API token):

curl -X POST "https://api.apify.com/v2/acts/tidytools~seo-audit-crawler/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"urls":["https://www.python.org/"],"maxPages":20}'

The synchronous endpoint waits up to 5 minutes. For bigger runs, start the run with POST https://api.apify.com/v2/acts/tidytools~seo-audit-crawler/runs and read the dataset when it finishes, or use the apify-client package for JavaScript or Python.

Schedules and integrations: run it daily or weekly with Apify Schedules, get a webhook when a run finishes, or send the results to Zapier, Make, n8n, Google Sheets, Slack and other apps with Apify integrations. Results can be exported as JSON, CSV, Excel or XML.

Scoring

Each page starts at 100. Critical issues (e.g. missing title, missing H1, noindex, HTTP errors, no HTTPS) cost 15 points, warnings (e.g. missing meta description, images without alt text, invalid hreflang) cost 5, and notices (e.g. missing canonical, Open Graph or structured data) cost 2. Each category score starts at 100 and loses three times those points for issues in that category.

Redirects that only add a language or country folder (/pricing → /en-sg/pricing) depend on where the request comes from, so they are counted separately and not reported as problems.

Advanced settings

  • Plain HTTP requests from: Auto (recommended) reads pages from our servers and retries from Apify's network when a site blocks data-center requests, then from our second server (Oracle, different IP), before falling back to a browser. A Cloudflare 520-530 error answered to our servers (common for sites that sit behind Cloudflare) counts as a refusal and is retried the same way. You can force any one of them.
  • Time limit per page: default 120 seconds for reading a page, all retries and the browser fallback included. A slower page gets errorType: "timeout" and is not charged. 0 = no limit.
  • Image checks (Check images) count toward the same page time limit. When it runs out, the page is still audited, and imageCheck has incomplete: true and the number of images not checked.
  • Proxy: optional Apify Proxy for requests sent from Apify's network (billed to your Apify account).

Limitations

  • On-page checks: no backlinks or keyword rankings. Core Web Vitals only with the optional PageSpeed Insights measurement (no key needed).
  • JSON-LD and Microdata are validated; RDFa types are only listed.
  • Only public http/https pages; no logins.
  • Download files (PDF, ZIP, installers) found while crawling are skipped; a start URL that is a download gets a free row with errorType: "unsupported".
  • Sitemap URLs outside the crawl are checked as a sample (up to 100 per run).

FAQ

Does the Actor collect usage data? The Actor sends one anonymous usage counter per run (input type, item count range, outcome) to improve the tool; no URLs, content or account data.

Does it measure Core Web Vitals? Yes, optionally. Turn on PageSpeed Insights for the pages you choose to get the performance score, LCP, CLS, TBT, FCP and real-user INP. No API key is needed; it costs $5 per 1,000 pages measured.

Can it audit JavaScript websites? Yes. In Auto mode a page that comes back almost empty (under about 200 characters of visible text, typical for client-rendered React or Vue apps) is audited again in a real browser, and a site that blocks plain requests is fetched from a second network or a browser (mode: "browser" on the row). Text or tags that JavaScript adds to a page that already has content are only seen with Page fetching (HTTP or browser) set to Browser.

Does it check backlinks or keyword rankings? No. It is a technical and on-page SEO checker: titles, meta, headings, canonical, hreflang, structured data, broken pages, sitemap and duplicates.

Can I track SEO issues over time? Yes. With Compare with the previous run on, each run is compared with the previous one and shows the issues added or resolved per page and the score change.

What are the limits? Up to 10,000 pages per run (Max pages), 120 seconds per page by default (Time limit per page), PageSpeed on up to 500 pages per run, and sitemap URLs outside the crawl are checked as a sample of up to 100. Before it starts, the run logs the most it can cost (Max pages × price); it never charges more than your maximum charge per run and stops there, keeping the pages audited so far.

How fast is it? The prefilled input (2 sites, 20 pages) is usually done in about a minute. Pages are audited in parallel (Parallel pages: 10 by default, up to 30); pages that need the browser fallback and PageSpeed measurements take longer.

Can I audit any website? Does it respect robots.txt? It reads only public pages (no logins) and reports for every page whether robots.txt blocks Googlebot. Respect robots.txt is off by default because the Actor is meant for sites you own or are allowed to audit: an audit has to see pages that robots.txt may hide from crawlers. Use it only on sites you own or may audit; turn Respect robots.txt on to follow robots.txt and skip the pages it disallows for crawlers (skipped pages are not charged; a skipped start URL gets a row with errorType: "robots_txt"). Auditing public pages is generally allowed, but follow each site's terms of service; this is not legal advice.

Does it work with the API, schedules, webhooks, Make, n8n or Zapier? Yes. Start runs from the Apify API (examples), an Apify schedule or a webhook, use the Apify apps for Make, n8n and Zapier, or call it from AI agents through MCP.

Support

Open an issue in the Issues tab with your start URL and input. Issues are checked regularly.

Found this useful? A short review on the Store helps other users find it.