SEO Site Audit — Website Crawler & Lighthouse avatar

SEO Site Audit — Website Crawler & Lighthouse

Pricing

Pay per event + usage

Go to Apify Store
SEO Site Audit — Website Crawler & Lighthouse

SEO Site Audit — Website Crawler & Lighthouse

SEO site audit crawler: status codes, titles, meta, H1, canonicals, indexability, broken links, duplicates, speed, onpage score & Lighthouse.

Pricing

Pay per event + usage

Rating

0.0

(0)

Developer

CheapAPI

CheapAPI

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

21 hours ago

Last modified

Share

Crawl any website and get a full technical SEO audit for every page — status codes, titles, meta descriptions, H1s, canonicals, indexability, broken links, duplicate content, page speed, an onpage score and a plain-English list of issues — plus a site summary and optional Lighthouse scores.

Who this is for: SEO agencies auditing client sites, site owners and marketers checking their own website, and developers who need crawl data in a pipeline or CI check.

Why this Actor

  • From $3.40 per 1,000 audited pages (Gold plan; $6.90 on Free), no monthly fee; Apify platform usage is billed separately — versus $30 (Gold) / $40 (Free) for the most-used SEO audit crawler in the Store and $5 (Gold) / $10 (Free) for a 28-field budget crawler. One per-page auditor is $0.40 cheaper on Gold ($3 vs $3.40) but finds no broken links, site-wide duplicates or Lighthouse scores (see the comparison below).
  • 99 fields per page plus 60+ SEO checks (full field reference): onpage score 0–100, a priority (high / medium / low) and a fix hint for every issue, word count, readability, links, page size, timings, broken link targets, Core Web Vitals (optional) — and site-wide checks (sitemap, robots.txt, SSL, HTTPS/www redirects, 404 page, duplicates across the site).
  • Lighthouse on demand: performance, accessibility, best practices and SEO scores with LCP, TBT, CLS and failed audits — from $0.007 per URL.
  • Crawl exactly what you need: include-only and exclude URL patterns (/blog/, *?sort=, *.pdf$), crawl speed from gentle (5 s between requests) to fastest (0.1 s), depth and time limits.
  • Free change monitoring: each page is marked new, changed or unchanged versus the previous run, with the changed fields — schedule it weekly and review only what moved. No browser, proxies or API keys to set up.

Compared with alternatives

A typical run: 1,000 pages of one website. Prices are the per-page charge × 1,000 on the Free and Gold plans (event fees only). For this Actor, Apify platform usage is billed separately by Apify (at the default 256 MB a small run typically uses about $0.001–$0.005), on top of the price shown.

1,000 pages (Free / Gold)Crawls the whole siteFields per page (as listed)Broken link targetsSite-wide duplicatesLighthouseJavaScript renderingChange tracking
Most-used SEO audit crawler (~670 users)$40 / $30✓~40 (as listed)✓titles, headingslab speed metrics✗✗
Most-used SEO data extractor (~480 users)$300 / $10✗ (your URLs only)11 (as listed)✗✗✗✓✗
Budget SEO audit crawler (~110 users)$10 / $5✓28 (as listed)✗✗✗✗✗
Low-cost per-page auditor (~190 users)$5 / $3optionalnot stated (structured-data focus)✗✗✗✗✗
This Actor$6.90 / $3.40 plus platform usage✓99 + 60+ checks✓ (URL, status, anchor)titles, descriptions, content✓ ($0.007–$0.07 per URL)✓ (+$0.002 per page)✓ free

The low-cost per-page auditor costs $1.90 (Free) / $0.40 (Gold) less per 1,000 pages. It checks structured data, social tags and headings of the URLs you give it; this Actor adds broken link targets, duplicate titles/descriptions/content across the site, indexability reasons, Lighthouse, JavaScript rendering, a site summary (sitemap, robots.txt, SSL, redirects) and free change tracking between runs. Our total includes the $0.002 website summary fee. Rival field counts are as listed on their Store pages, not independently verified.

Cheaper still: a very new crawler with about 4 users charges $0.50 per 1,000 pages (plus a small start fee and platform usage) for a basic audit — status, title/description, canonical, headings, word count, links, image alt gaps, indexability and structured data. If that is all you need, it costs less; it does not list broken link targets, site-wide duplicates, Lighthouse, JavaScript rendering or change tracking.

Lighthouse only? If you just need Lighthouse / PageSpeed scores for URLs you already know, a PageSpeed-API Actor (~90 users) is cheaper at about $0.002 per URL versus our $0.007 (Gold) – $0.07 (Free), and a free Lighthouse Actor (~200 users) charges only platform usage. Use this Actor when you also need the crawl, issues, broken links and duplicates.

Prices, user counts and feature lists from public Apify Store listings, checked September 2026.

Not included

  • Keyword rankings and search volumes — this Actor audits pages, not Google positions. Use Domain SEO Analyzer for the keywords a domain ranks for, or Keyword Research Tool for volumes and ideas.
  • Backlinks (who links to the site) — only links on the crawled pages are analysed. Use Backlink Checker.
  • Real-user (field) Core Web Vitals — Lighthouse and full browser rendering measure lab values from one test run, not visitor data.
  • Pages behind a login — only publicly reachable pages are crawled.
  • Automatic fixes — you get issues and data, not changes to your website.

What data you get

One row per crawled page (HTML pages, broken URLs and redirects) in the dataset:

FieldTypeExample
idstring3f9c1a0b7d2e4c61 (stable across runs: hash of website + URL)
urlstringhttps://example-shop.com/
statusCodenumber200
pageTypestringhtml / broken / redirect
redirectUrlstringhttps://example-shop.com/ (for redirects)
onpageScorenumber (0–100)97.07
issuesCount, issues, issueCodesnumber, array4, ["Images without alt text", …], ["noImageAlt", …]
issueDetailsarray[{"code": "noImageAlt", "priority": "medium", "fixHint": "Add descriptive alt text…"}] — one entry per issue code, same order
title, titleLength, titleMissing, titleTooShort, titleTooLong, duplicateTitlestring, number, boolean"Example Shop – Running Shoes…", 55, false
metaDescription, metaDescriptionLength, metaDescriptionMissing, duplicateMetaDescriptionstring, number, boolean"Shop running shoes…", 123
h1, h1Count, h1Missing, h1List, h2Count, h3Countstring, number, boolean, array"Running shoes for every runner", 1
wordCount, textToHtmlRatio, readabilityScorenumber1165, 0.047, 31.26
canonicalUrl, canonicalIsSelfstring, booleanhttps://example-shop.com/, true
indexable, nonIndexableReasonboolean, stringfalse, robots_txt / meta_tag / redirect / canonicalized_to_other_url
duplicateContentbooleanfalse
hasBrokenLinks, brokenLinksCount, brokenLinksboolean, number, arraytrue, 2, [{"url": "…/missing", "statusCode": 404, "anchorText": "Old offer"}]
hasBrokenResourcesbooleanbroken images, scripts or CSS
clickDepth, internalLinksCount, externalLinksCount, inboundLinksCountnumber0, 130, 33, 11
imagesCount, imagesWithoutAlt, scriptsCount, renderBlockingScriptsnumber, boolean58, true, 48, 12
pageSizeBytes, totalTransferSizeBytes, domSizenumber148362, 2184530, 162918
loadTimeMs, timeToFirstByteMs, timeToInteractiveMs, largestContentfulPaintMs, cumulativeLayoutShiftnumber (Core Web Vitals: null without Full browser rendering)486, 112, 512
isHttps, hasStructuredData, socialTags, misspelledWords, deprecatedTagsmixedtrue, {"og:type": "website"}
lighthousePerformanceScore, lighthouseAccessibilityScore, lighthouseBestPracticesScore, lighthouseSeoScore, lighthousenumber, object45, 75, 54, 85 (when Lighthouse is on)
checksobjectall 60+ true/false checks
changedSinceLastRun, changeTypeboolean, stringtrue, new / changed / unchanged / baseline (first run)
changedFields, previousOnpageScore, previousStatusCodearray, number, number["title", "onpageScore"], 92.5, 200
website, fetchedAt, scrapedAtstringcontext

Issue priorities and fix hints: issueDetails gives every issue code a priority — high (hurts indexing, rankings or visitors directly, e.g. broken pages, notIndexable, duplicate content), medium (worth fixing soon, e.g. missing meta description, slow server) or low (minor, e.g. missing image title attributes) — and a one-sentence fixHint. They come from a fixed table per issue code, so they are free and consistent between runs; sort by priority to build a to-do list.

That is 99 fields per page, all declared in the dataset schema (expand the reference above). Plus a site summary per website in the key-value store record SITE_SUMMARY: overall onpage score, pages crawled, top issues with page counts, broken links/resources, duplicate titles/descriptions/content, non-indexable pages, redirect loops, CMS, server, SSL validity/expiry, sitemap/robots.txt/HTTPS/www-redirect/404 checks, and — with change monitoring — new/changed/unchanged page counts and the previous run's onpage score.

How to use

  1. Open the Actor and add one or more websites to Websites (e.g. https://example.com). For many sites, use Bulk edit to paste a list, or link a text file with one URL per line (up to 100 websites per run).
  2. Set Max pages per website (prefilled with 20 for a quick first run; 100 if you leave it empty).
  3. Optional: turn on Run Lighthouse audit or JavaScript rendering (for React/Vue/Angular sites).
  4. Optional: under Advanced: crawl scope, limit the crawl with Only URLs matching / Exclude URLs matching and pick a Crawl speed.
  5. Click Start. Pages appear in the Output tab; the site summary is in the key-value store (SITE_SUMMARY).
  6. Export as JSON, CSV, Excel, XML or HTML, or read it through the API. Run it again later (or on a schedule) and use the Changes since last run view.
{
"startUrls": ["https://example.com", "https://shop.example.org/blog/"],
"maxPagesPerSite": 500,
"runLighthouse": true,
"lighthousePagesPerSite": 3,
"enableJavaScript": false,
"includeUrlPatterns": ["/blog/", "/products/"],
"excludeUrlPatterns": ["/cart/", "*?sort="],
"crawlSpeed": "normal",
"monitorChanges": true,
"onlyPagesWithIssues": false
}

API — curl

curl -X POST "https://api.apify.com/v2/acts/cheapapi~seo-site-audit/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"startUrls": ["https://example.com"], "maxPagesPerSite": 100}'

JavaScript (apify-client)

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_TOKEN>' });
const run = await client.actor('cheapapi/seo-site-audit').call({
startUrls: ['https://example.com'],
maxPagesPerSite: 100,
runLighthouse: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const siteSummary = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord('SITE_SUMMARY');
console.log(items.length, siteSummary.value);

Python (apify-client)

from apify_client import ApifyClient
client = ApifyClient("<YOUR_TOKEN>")
run = client.actor("cheapapi/seo-site-audit").call(run_input={
"startUrls": ["https://example.com"],
"maxPagesPerSite": 100,
})
pages = client.dataset(run["defaultDatasetId"]).list_items().items
summary = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("SITE_SUMMARY")
print(len(pages), summary["value"])

Use cases

  • Technical SEO audits for clients or your own sites — export the issue list straight into a spreadsheet.
  • Pre- and post-migration checks: find broken links, redirect chains, lost canonicals and non-indexable pages.
  • Content quality reviews: thin content, missing or duplicate titles, descriptions and H1s, low readability.
  • Scheduled monitoring: run weekly; changeType and changedFields show which pages are new or changed (title, meta description, H1, canonical, status, indexability, issues, score) since the last run.
  • Section audits: audit only /blog/ or /products/ with include patterns, and skip faceted or cart URLs with exclude patterns.
  • Performance tracking with Lighthouse and Core Web Vitals for your key landing pages.
  • Lead generation for agencies: audit prospects' websites and send them the top issues.

Advanced options

All options are optional. The first four fields (Websites, Max pages per website, Run Lighthouse audit, JavaScript rendering) are all most users need.

InputNameDefaultWhat it does
includeUrlPatternsOnly URLs matching—Crawl and deliver only URLs whose path matches one of these patterns (e.g. /blog/, /products/*.html$, or a full URL). * = anything, trailing $ = end of URL. The start page is visited to discover links but only delivered if it matches. Max 50.
excludeUrlPatternsExclude URLs matching—Never crawl or deliver matching URLs (e.g. /cart/, *?sort=, *.pdf$). Exclusions always win. Max 50.
crawlSpeedCrawl speednormalgentle = 5 s, normal = 2 s, fast = 0.5 s, fastest = 0.1 s between requests to the website.
maxCrawlDepthMax crawl depth—How many clicks away from the start page to crawl (0 = start page only). Empty = no limit.
crawlDelayMsExact delay between requests (ms)—Exact pause in milliseconds (0–60,000). Overrides Crawl speed.
maxCrawlMinutesMax crawl time (minutes)60If the crawl is not finished after this time, it is stopped and the pages crawled so far are delivered.
priorityUrlsPriority URLs—Up to 20 URLs that are crawled first (must belong to one of the websites).
respectSitemapFollow sitemap orderoffCrawl pages in the order of the website's XML sitemap.
customSitemapUrlCustom sitemap URL—Use this sitemap instead of the one listed in robots.txt (e.g. https://example.com/sitemap_pages.xml).
crawlSitemapOnlyCrawl sitemap pages onlyoffOnly audit URLs listed in the sitemap; links on pages are not followed.
includeSubdomainsInclude subdomainsoffAlso crawl subdomains (blog.example.com, shop.example.com…).
allowedSubdomainsOnly these subdomains—Crawl only these subdomains (e.g. blog.example.com). Leave empty for all.
excludedSubdomainsExcluded subdomains—Subdomains to skip. Needs "Include subdomains".
respectRobotsTxtRespect robots.txtonObey the website's robots.txt rules. Turn off to audit pages blocked for crawlers (only on sites you own or may audit).
customRobotsTxtCustom robots.txt rules—Extra robots.txt rules for the crawl, e.g. "User-agent: *\nDisallow: /cart/".
robotsTxtModeCustom robots.txt mode—Merge your rules with the website's robots.txt or replace it.
loadResourcesLoad images, scripts & CSSonLoad page resources to find broken images/scripts/CSS, measure image sizes and render-blocking resources. Included in the page price.
enableBrowserRenderingFull browser rendering (Core Web Vitals)offRender pages in a real browser to measure Core Web Vitals (LCP, CLS, FID) per page. Includes JavaScript rendering. Extra fee per page.
enableXhrAllow XHR requestsoffLet pages load data with XHR/fetch during rendering. Needs JavaScript rendering.
disableCookiePopupHide cookie bannersoffTry to close cookie consent pop-ups during rendering.
supportCookiesAccept cookiesoffKeep cookies between requests (for sites that need a session cookie).
customJavaScriptCustom JavaScript—Snippet executed on every page (max 2,000 characters, 700 ms). Its result is returned in "customJsResult". Example: meta = {}; meta.url = document.URL; meta;
userAgentCustom user agent—User-Agent header for the crawler and Lighthouse (max 254 characters). Empty = standard crawler user agent.
acceptLanguageAccept-Language header—Language sent to the website, e.g. "en-US" or "de-DE,de;q=0.9".
deviceDevice—Screen preset used for rendering. Works with "Full browser rendering".
screenWidthScreen width (px)—Custom screen width in pixels (240–9999) for Lighthouse, and for the crawl with "Full browser rendering".
screenHeightScreen height (px)—Custom screen height in pixels (240–9999) for Lighthouse, and for the crawl with "Full browser rendering".
screenScaleFactorScreen scale factor—Device pixel ratio, 0.5–3, for Lighthouse, and for the crawl with "Full browser rendering".
useExtraCrawlerNetworkUse extra crawler networkoffCrawl through an additional pool of IP addresses — helps with sites that block or rate-limit crawlers.
returnSlowPagesKeep very slow pagesoffDeliver pages that take longer than 120 seconds to load (with the data collected so far) instead of marking them as failed.
titleMinLengthTitle too short below (characters)30A page title shorter than this number of characters is reported as "Title too short".
titleMaxLengthTitle too long above (characters)65A page title longer than this number of characters is reported as "Title too long", because search results usually cut it off.
minPageSizeBytesSmall page below (bytes)1024An HTML page smaller than this many bytes is reported as "Very small page", which often means an empty or error page.
maxPageSizeBytesLarge page above (bytes)1048576An HTML page larger than this many bytes is reported as "Large page size".
minCharacterCountThin content below (characters)1024A page with fewer visible text characters than this is reported as "Thin content".
maxCharacterCountVery long content above (characters)256000A page with more visible text characters than this is reported as "Very long content".
minTextToHtmlRatioLow text-to-HTML ratio below0.1A page whose visible text is a smaller share of its HTML than this ratio (0–1) is reported as "Low text-to-HTML ratio".
maxTextToHtmlRatioHigh text-to-HTML ratio above0.9A page whose visible text is a larger share of its HTML than this ratio (0–1) is reported as "High text-to-HTML ratio".
maxLoadTimeMsSlow page above (ms)3000A page that takes longer than this many milliseconds to load is reported as "Slow page load".
maxWaitingTimeMsSlow server response above (ms)1500A page whose server takes longer than this many milliseconds to send the first byte (TTFB) is reported as "Slow server response".
minReadabilityScoreLow readability below15A page whose Flesch-Kincaid readability score is below this value is reported as "Low readability" (higher scores mean easier text).
minTitleRelevanceTitle not relevant below0.3A title whose relevance to the page content (0–1) is below this value is reported as "Title not relevant to page content".
minDescriptionRelevanceDescription not relevant below0.2A meta description whose relevance to the page content (0–1) is below this value is reported as "Meta description not relevant to page content".
minKeywordsRelevanceMeta keywords not relevant below0.6A meta keywords tag whose relevance to the page content (0–1) is below this value is reported as "Meta keywords not relevant to page content".
disabledPageChecksSkip these page checks—Checks that are not run and do not affect the onpage score.
disabledSiteChecksSkip these site-wide checks—Site-wide tests to skip.
forceSiteWideChecksRun site-wide checks for 1-page auditsoffAlso run site-wide checks (sitemap, robots.txt, redirects, 404 page) when only one page is audited.
checkWwwRedirectCheck www redirectoffTest whether www and non-www versions redirect to one another.
validateStructuredDataValidate structured dataoffCheck schema.org / microdata markup for errors.
checkSpellingCheck spellingoffFind misspelled words on each page (see "misspelledWords").
spellingLanguageSpelling language—Language for the spelling check. Empty = detected automatically.
spellingExceptionsSpelling exceptions—Words that are never reported as misspelled (brand names…), max 1,000.
includeBrokenLinkDetailsList broken links per pageonAdd the list of broken link targets (URL, status code, anchor text) to each page.
onlyPagesWithIssuesOnly pages with issuesoffDeliver (and charge) only pages that have at least one issue.
includeAllChecksInclude all check resultsonAdd the full "checks" object (60+ true/false checks) to each page.
lighthousePagesPerSiteLighthouse pages per website1How many pages per website get a Lighthouse audit (1 = the start page).
lighthouseDeviceLighthouse devicemobileMobile (default, like Google's mobile-first index) or desktop.
lighthouseCategoriesLighthouse categories—Categories to test. Empty = all four.
lighthouseAuditsOnly these Lighthouse audits—Run only specific audits, e.g. "metrics/largest-contentful-paint". Empty = all.
lighthouseLanguageLighthouse report languageenLanguage code for audit titles, e.g. "en", "de", "es". Default "en".
lighthouseVersionLighthouse version—Specific Lighthouse version (e.g. "12.6.0"). Empty = latest.
lighthouseThrottlingNetwork throttling—Simulated network speed. Empty = Lighthouse default.
lighthouseThrottlingMethodThrottling method—How throttling is applied.
lighthouseCpuSlowdownCPU slowdown multiplier—1–4, used with the DevTools throttling method.
monitorChangesTrack changes since the last runonKeep a compact fingerprint of every crawled page in a named key-value store and mark each page as new / changed / unchanged next time. Free.
monitorStoreNameMonitoring store nameseo-site-audit-monitorNamed key-value store for the fingerprints (one record per website). Use different names for separate histories.

Output example

Example output — one page row (shortened; values illustrative but consistent with each other and with the site summary below):

{
"website": "https://example-shop.com",
"url": "https://example-shop.com/",
"pageType": "html",
"statusCode": 200,
"redirectUrl": null,
"onpageScore": 97.07,
"issuesCount": 4,
"issues": [
"Links from HTTPS to HTTP pages",
"Meta keywords not relevant to page content",
"Low text-to-HTML ratio",
"Images without alt text"
],
"issueCodes": [
"httpsToHttpLinks",
"irrelevantMetaKeywords",
"lowContentRate",
"noImageAlt"
],
"issueDetails": [
{ "code": "httpsToHttpLinks", "priority": "medium", "fixHint": "Change links on this HTTPS page that point to http:// URLs to their https:// versions." },
{ "code": "irrelevantMetaKeywords", "priority": "low", "fixHint": "Remove the meta keywords tag (search engines ignore it) or make it match the content." },
{ "code": "lowContentRate", "priority": "low", "fixHint": "Little visible text compared with HTML code. Add content or reduce inline code, scripts and markup." },
{ "code": "noImageAlt", "priority": "medium", "fixHint": "Add descriptive alt text to images that carry meaning; use alt=\"\" for purely decorative images." }
],
"title": "Example Shop – Running Shoes, Trail Shoes & Sports Gear",
"titleLength": 55,
"titleMissing": false,
"titleTooShort": false,
"titleTooLong": false,
"duplicateTitle": false,
"metaDescription": "Shop running shoes, trail shoes and sports gear with free delivery and 30-day returns. Over 2,000 products from top brands.",
"metaDescriptionLength": 123,
"metaDescriptionMissing": false,
"duplicateMetaDescription": false,
"h1": "Running shoes for every runner",
"h1Count": 1,
"h1Missing": false,
"h2Count": 3,
"wordCount": 1165,
"textToHtmlRatio": 0.047,
"readabilityScore": 31.26,
"canonicalUrl": "https://example-shop.com/",
"canonicalIsSelf": true,
"indexable": true,
"nonIndexableReason": null,
"duplicateContent": false,
"hasBrokenLinks": false,
"brokenLinksCount": 0,
"brokenLinks": [],
"hasBrokenResources": false,
"clickDepth": 0,
"internalLinksCount": 130,
"imagesCount": 58,
"imagesWithoutAlt": true,
"renderBlockingScripts": 12,
"pageSizeBytes": 148362,
"totalTransferSizeBytes": 2184530,
"domSize": 162918,
"loadTimeMs": 486,
"timeToFirstByteMs": 112,
"timeToInteractiveMs": 512,
"largestContentfulPaintMs": null,
"cumulativeLayoutShift": null,
"isHttps": true,
"lighthousePerformanceScore": 45,
"lighthouseAccessibilityScore": 75,
"lighthouseBestPracticesScore": 54,
"lighthouseSeoScore": 85,
"lighthouse": {
"device": "mobile",
"performanceScore": 45,
"accessibilityScore": 75,
"bestPracticesScore": 54,
"seoScore": 85,
"firstContentfulPaintMs": 1266,
"largestContentfulPaintMs": 2363,
"totalBlockingTimeMs": 8342,
"cumulativeLayoutShift": 0.002,
"speedIndexMs": 5328,
"timeToInteractiveMs": 13840,
"serverResponseTimeMs": 95,
"failedAudits": [
{
"id": "max-potential-fid",
"title": "Max Potential First Input Delay",
"score": 0,
"value": "7,630 ms"
}
],
"lighthouseVersion": "13.4.0"
},
"changedSinceLastRun": true,
"changeType": "changed",
"changedFields": ["title", "onpageScore"],
"previousOnpageScore": 95.2,
"previousStatusCode": 200,
"javascriptRendered": false,
"browserRendered": false,
"fetchedAt": "2026-09-27T01:52:24.000Z",
"scrapedAt": "2026-09-28T16:04:14.261Z"
}

Example output — the site summary (SITE_SUMMARY, one entry per website) for the same 10-page crawl:

{
"website": "https://example-shop.com",
"domain": "example-shop.com",
"crawlFinished": true,
"crawlStopReason": "page_limit_reached",
"siteStatus": "no_errors",
"pagesCrawled": 10,
"pagesInQueue": 0,
"pagesDelivered": 10,
"onpageScore": 95.87,
"averagePageScore": 95.86,
"pagesWithIssues": 10,
"brokenLinks": 0,
"brokenResources": 0,
"duplicateTitles": 0,
"duplicateDescriptions": 0,
"duplicateContent": 0,
"nonIndexablePages": 1,
"redirectLoops": 0,
"internalLinks": 1248,
"externalLinks": 188,
"topIssues": [
{ "issue": "Images without title attribute", "pages": 10 },
{ "issue": "Low text-to-HTML ratio", "pages": 9 },
{ "issue": "Images without alt text", "pages": 7 },
{ "issue": "Links from HTTPS to HTTP pages", "pages": 3 },
{ "issue": "Not indexable", "pages": 1 }
],
"cms": "WordPress 6.6",
"server": "cloudflare",
"ip": "203.0.113.10",
"sslValid": true,
"sslIssuer": "CN=WE1, O=Google Trust Services, C=US",
"sslExpires": "2026-12-17T10:33:03.000Z",
"notFoundStatusCode": 404,
"wwwRedirectStatusCode": null,
"crawlStartedAt": "2026-09-27T08:02:15.000Z",
"crawlEndedAt": "2026-09-27T08:02:37.000Z",
"lighthousePagesTested": 1,
"scrapedAt": "2026-09-28T16:04:14.261Z",
"changeMonitoring": {
"previousRunAt": "2026-09-21T16:02:51.118Z",
"previousOnpageScore": 95.4,
"pagesNew": 1,
"pagesChanged": 2,
"pagesUnchanged": 7,
"pagesNotCrawledAgain": 0
}
}

The dataset has five table views: Overview, Titles, meta & headings, Indexability & links, Page speed & Lighthouse and Changes since last run. RUN_SUMMARY in the key-value store lists skipped websites and errors in plain words.

Pricing

Apify Free plan: Apify does not pay developers for usage on its Free plan, so on the Free plan this Actor can be used for up to $0.25 of results per calendar month — enough to try it on a small input. When the allowance is used up, the run ends with a clear message (not an error). Any paid Apify plan removes the limit; prices are the same.

Pay per event — no monthly fee. Prices drop automatically on higher Apify plans (Platinum and Diamond get the Gold price):

EventFreeBronzeSilverGold+When it is charged
Audited page$0.0069$0.0055$0.0045$0.0034Per page delivered to the dataset (loading of images/scripts/CSS included)
Website summary$0.002$0.002$0.002$0.002Once per website that delivered at least one page
JavaScript rendering (add-on)$0.002$0.002$0.002$0.002Per crawled page (delivered or not), only when JavaScript rendering is on
Full browser rendering (add-on)$0.0065$0.0065$0.0065$0.0065Per crawled page (delivered or not), only when full browser rendering is on (JavaScript rendering is charged too)
Lighthouse audit$0.07$0.021$0.014$0.007Per URL with a successful Lighthouse result
Crawled page not delivered$0.0009$0.0009$0.0009$0.0009Per page that was crawled but not delivered: left out by Only pages with issues or your URL patterns (including the start page visited for link discovery), or when the crawl results could not be read or the crawl start got no answer (the crawl may still have run; its page limit is charged). Never charged when every crawled page is delivered
Website crawled without delivered pages$0.0003$0.0003$0.0003$0.0003Once per website whose crawl started but delivered no page (unreachable site, everything filtered out). Replaces the website summary fee
Lighthouse test without result$0.0065$0.0065$0.0065$0.0065Per Lighthouse test that ran (or may have run, when no answer arrived) but returned no usable report, e.g. the page did not load

Worked examples:

  • 1,000 pages of one website (Gold): 1,000 × $0.0034 + $0.002 = $3.40. On the Free plan: $6.90.
  • 100 pages + Lighthouse on the 3 main pages (Bronze): 100 × $0.0055 + $0.002 + 3 × $0.021 = $0.615.
  • 200 pages of a React site with JavaScript rendering (Silver): 200 × ($0.0045 + $0.002) + $0.002 = $1.302.
  • Only pages with issues, 500 crawled, 120 with issues (Gold): 120 × $0.0034 + 380 × $0.0009 + $0.002 = $0.752 (instead of $1.702 for all 500 pages).
  • A website that cannot be reached (any plan): $0.0003 + 1 × $0.0009 = $0.0012.

Set Maximum cost per run in the run options: the Actor limits the number of crawled pages up front so the run never goes over your budget (it reserves the full price of every page a crawl may crawl). Change monitoring, crawls that were rejected (e.g. invalid input) and Lighthouse tests the service could not start are free. The small "not delivered" fees exist because every crawled page and every Lighthouse test is paid for when it runs, even if nothing is delivered; with default settings on a reachable website they are rarely charged.

Apify platform usage is billed separately by Apify (at the default 256 MB a small run typically uses about $0.001–$0.005); the prices and examples on this page are event fees only.

Integrations

  • Schedules: run the audit weekly or monthly from Apify Schedules — with change monitoring on, each run tells you what changed since the previous one.
  • Webhooks: get notified when a run finishes and fetch the dataset automatically.
  • Make, Zapier, n8n: use the Apify app/node to start audits and push issues to Slack, email or your CRM.
  • Google Sheets: export the dataset with the Google Sheets integration, or download CSV/Excel.
  • API & MCP: every run, dataset and the SITE_SUMMARY record are available over the Apify API, and AI agents can start audits through the Apify MCP server.

FAQ

Is there a limit on the Apify Free plan? Yes: up to $0.25 of this Actor's results per calendar month, enough to try it. Apify pays developers nothing for Free-plan usage while our data costs are real, so this keeps the Actor sustainable. Runs that reach the allowance stop cleanly and keep everything collected so far; the allowance resets on the 1st of the month. Any paid Apify plan has no limit.

Is it legal? Crawling publicly available pages for SEO analysis is generally fine, but only audit websites you own or have permission to audit, respect the website's terms, and keep a gentle crawl speed for sites you don't control. Turning off Respect robots.txt should be limited to your own sites.

How fresh is the data? Every run crawls the website live, so results reflect the site at the time of the run (fetchedAt per page).

Why did I get fewer pages than "Max pages per website"? The website may have fewer reachable pages, robots.txt or your URL patterns may exclude parts of it, the crawl may have hit Max crawl time or Max crawl depth, or your Maximum cost per run capped it. Images, scripts and CSS files are checked but not returned as rows. See RUN_SUMMARY (including pagesFilteredOutByUrlPatterns) and crawlStopReason in SITE_SUMMARY.

How do I audit only part of a website? Put a section URL into Websites (e.g. https://example.com/blog/) and add /blog/ to Only URLs matching. Use Exclude URLs matching for carts, filters, tag pages or PDFs.

How does change monitoring work? After each run, a compact fingerprint of every page (status, onpage score, title, meta description, H1, canonical, indexability, word count, issues) is saved in the named key-value store seo-site-audit-monitor in your account. The next run of the same website compares against it and fills changedSinceLastRun, changeType and changedFields. The first run is the baseline. It is free; switch it off with Track changes since the last run.

How do I control the budget? Set Maximum cost per run in the run options: the page limit is reduced up front so the run never goes over it. Rendering add-ons and Lighthouse are only charged when you switch them on.

Why was I charged for "Crawled page not delivered" or "Website crawled without delivered pages"? The crawler visited those pages, which costs the same whether or not you keep them. With Only pages with issues or URL patterns, pages that do not qualify cost $0.0009 each instead of the full page price. A website that could not be reached still costs $0.0003 + one checked page. If the crawl results could not be read, or the crawl start got no answer (the crawl may still have run), the pages up to the crawl's page limit are charged as checked pages; RUN_SUMMARY lists pagesChecked, websitesChecked and the error. With JavaScript or browser rendering on, the rendering add-on applies to checked pages too, because they were rendered.

Why was I charged $0.0065 for a Lighthouse test without result? The test ran (or may have run, when no answer arrived) but returned no usable report, for example because the page did not load in the test browser. Tests that could not be started are free. RUN_SUMMARY.lighthouseChecked counts them.

Is Apify platform usage included? No. Apify platform usage (compute) is billed separately by Apify, on top of the event fees. At the default 256 MB memory a small run typically uses about $0.001–$0.005; long crawls wait longer and use more. Each run's usage is shown in Apify Console.

Can I schedule it? Yes — create an Apify Schedule (e.g. every Monday) and a webhook or Make/Zapier scenario that sends you the rows where changeType is new or changed.

Which export formats are available? JSON, CSV, Excel, XML, HTML and RSS from the Output tab or the API, plus Google Sheets through the integration.

How long does an audit take? Roughly 1–3 minutes for 20 pages and 5–10 minutes for a few hundred pages at the normal crawl speed. Choose Fast only for sites that can handle it.

Something doesn't work — where do I get help? Open an issue on the Actor's Issues tab with the run link and your input (without private data) and we will look into it.

Limitations

  • Lighthouse runs only on crawled HTML pages with status 2xx (the start page first); URLs outside the crawl are not tested.
  • The crawler identifies itself with its own user agent; sites with aggressive bot protection may block it (try Use extra crawler network or a Custom user agent).
  • Core Web Vitals per page (largestContentfulPaintMs, cumulativeLayoutShift, firstInputDelayMs) are measured only with Full browser rendering; otherwise they are null. Lighthouse always measures them.
  • Broken link details are listed for up to 5,000 broken links per website (100 per page).
  • If the crawl reaches Max crawl time, it is stopped and the pages crawled so far are delivered (site-wide duplicate checks may then be incomplete).
  • When several websites share a small budget, pages are allocated in input order, so the last websites may be skipped.
  • URL patterns match the URL path and query from its start (robots.txt-style * and $), not full regular expressions. Pages behind excluded URLs can still be reached if other links point to them through included sections.
  • Change monitoring compares with the last run of the same website in the same monitoring store; changing thresholds or skipped checks changes onpage scores and shows up as changes. pagesNotCrawledAgain can include pages that were simply outside this run's page limit. Up to 40,000 URLs per website are remembered.

Privacy and personal data

The Actor audits the technical SEO of web pages; it does not look for, extract or build profiles of people. Page text is analysed for word counts and checks but not stored in the output (only titles, meta descriptions, headings and URLs). If a page you audit shows personal data (for example a name in a title), it can appear in those fields — you are responsible for processing it lawfully (e.g. under GDPR/CCPA). The change-monitoring store keeps only hashed fingerprints, scores and status codes per URL in your own Apify account; delete the store at any time to remove them.