SEO Site Audit Scraper
Pricing
from $1.70 / 1,000 page audits
SEO Site Audit Scraper
Audit any website for SEO: crawl pages, check titles, meta tags, headings, canonicals, noindex, status codes, redirect chains and broken links, read robots.txt and sitemaps. One row per page with issue codes.
Pricing
from $1.70 / 1,000 page audits
Rating
0.0
(0)
Developer
DataWatcher
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Security
Limited permissionsShare
SEO Site Audit Scraper: technical SEO audit, broken links and redirect checker
Scrape website data for a full technical SEO audit: every page checked for on-page SEO issues, broken links, redirect chains, the internal link graph with anchor text, and your sitemap and robots.txt validated. Get one clean JSON row per finding, with a plain-language fix for each issue. Run it from the Console or the API, schedule it and monitor your site over time. It is a pay-per-event site audit alternative to desktop crawlers and monthly SEO suites: you pay only for the rows you get.
⭐ Why this one
- One schema across SEO actors. Page audits, links, redirects, sitemap URLs and robots.txt come as typed rows (
recordType) with the same envelope, so one parser reads every row. - Every issue comes with a fix. Each finding has a stable
code, aseverity, a plainmessage, theevidencefound on the page and afixyou can hand to a developer. - Pay per event, no subscription. Audit one site on demand or on a schedule; there is no seat or monthly licence.
- API and JSON first. Feed dashboards, spreadsheets, Slack alerts or a CI check through the Apify API and integrations.
- Polite by design. It respects robots.txt, waits between requests and audits public sites only.
🔍 What you get
| You want to find | Row type | What it holds |
|---|---|---|
| On-page SEO problems | pageAudit | Title, meta description, h1, canonical, indexability, hreflang, Open Graph, security headers, content hash, health score and an issues list with fixes |
| Broken links checker results | brokenLink | Source page, target URL, HTTP status, anchor text, internal or external |
| Redirect chains and loops | redirectChain | Start URL, final URL, every hop with status and location |
| Internal links and anchor text | internalLink | Source, target, anchor text, rel, followed or not, source depth |
| Sitemap validator | sitemapUrl | Each URL listed in the sitemap and the sitemap that lists it |
| robots.txt validator | robotsReport | Status, rules found and the sitemaps it declares |
| Site-wide health | auditSummary | Pages crawled, status groups, issue counts by code and severity, health score |
Checks include missing, short, long and duplicate titles and meta descriptions, missing or multiple h1, missing or wrong canonical, noindex and canonical conflicts, orphan pages, duplicate content, thin content, missing image alt text, mixed content, non-https pages, redirect loops and long chains, links to 4xx and 5xx pages, deep pages, hreflang errors, missing viewport and lang, and missing security headers.
What this actor is not. It audits the site you give it: its pages, its internal link graph and (if you switch it on) its outbound links. It does not hold a backlink index and returns no data about who links to you from other sites. Page-speed scores such as LCP are not measured here either.
Fields that are not measured. The actor makes no image requests, so largeImageCount is always null and the IMAGE_TOO_LARGE code is never raised. Missing data is null, never a guess.
🚀 How to scrape a site for SEO data
- Open the actor and enter the website address in Start URLs.
- Choose a Mode: crawl a site, check a URL list, or read a sitemap.
- Set Max pages and Max depth, then click Start.
- Download the data as JSON, CSV or Excel, or read it through the API.
🕷️ 1. Crawl a site
{"mode": "crawl","startUrls": ["https://example.com/"],"maxPages": 200,"maxDepth": 3,"emitLinkRows": true}
Follows internal links, audits every page, reads robots.txt and the sitemap, and writes broken links, redirect chains and a summary. Turn on emitLinkRows for the full internal link graph.
📋 2. Check a URL list
{"mode": "urlList","startUrls": ["https://example.com/old-page", "https://example.com/pricing"]}
Checks exactly the URLs you give: status, redirects, final URL and the page checks. No links are followed. Good for migration checks.
🗺️ 3. Read a sitemap
{"mode": "sitemap","startUrls": ["https://example.com/"]}
Reads the sitemap (index files too) and checks the status of each listed URL.
Useful options
includeUrlPatternsandexcludeUrlPatterns: glob patterns such ashttps://example.com/blog/**or**/tag/**.includeSubdomains: also crawlblog.example.comforexample.com.checkExternalLinks: request outbound links to find broken external links.respectRobotsTxt: on by default; skipped pages still show as a finding.- Free plan: up to 1,000 rows per run (see Pricing).
📦 Output: SEO audit data
Every row has the same envelope (schemaVersion, recordType, url, dates, target, status, coverage, warnings, errors) and a data object with the fields of its type. Real rows from a crawl, shortened:
pageAudit
{"recordType": "pageAudit","url": "https://crawler-test.com/content/mult_h1","status": "success","data": {"finalUrl": "https://crawler-test.com/content/mult_h1","httpStatus": 200,"title": "Mult H1s","titleLength": 8,"h1": ["header number 1", "header number 2"],"h1Count": 2,"indexable": true,"score": 67,"wordCount": 14,"internalLinkCount": 1,"issues": [{"code": "MULTIPLE_H1","severity": "low","message": "The page has more than one h1 heading.","fix": "Keep one h1 and make the others h2.","evidence": "2 h1: header number 1; header number 2"}]}}
brokenLink
{"recordType": "brokenLink","url": "https://crawler-test.com/links/broken_links_internal","data": {"sourceUrl": "https://crawler-test.com/links/broken_links_internal","targetUrl": "https://crawler-test.com/links/not_found/foo1","httpStatus": 404,"linkScope": "internal","anchorText": "Broken Internal Link 1"}}
redirectChain
{"recordType": "redirectChain","url": "https://httpbin.org/redirect/3","data": {"startUrl": "https://httpbin.org/redirect/3","finalUrl": "https://httpbin.org/get","hopCount": 3,"loop": false,"hops": [{"url": "https://httpbin.org/redirect/3", "httpStatus": 302, "location": "/relative-redirect/2"},{"url": "https://httpbin.org/relative-redirect/2", "httpStatus": 302, "location": "/relative-redirect/1"},{"url": "https://httpbin.org/relative-redirect/1", "httpStatus": 302, "location": "/get"}]}}
internalLink
{"recordType": "internalLink","url": "https://crawler-test.com/links/broken_links_internal","data": {"sourceUrl": "https://crawler-test.com/links/broken_links_internal","targetUrl": "https://crawler-test.com/","anchorText": "Crawler Test two point oh!","followed": true,"sourceDepth": 0}}
sitemapUrl
{"recordType": "sitemapUrl","url": "https://crawler-test.com/urls/page_with_hreflang_header_not_ok","data": {"loc": "https://crawler-test.com/urls/page_with_hreflang_header_not_ok","sitemapUrl": "https://crawler-test.com/test_sitemap.xml"}}
robotsReport
{"recordType": "robotsReport","url": "https://crawler-test.com/robots.txt","data": {"robotsUrl": "https://crawler-test.com/robots.txt","httpStatus": 200,"sitemaps": ["https://crawler-test.com/test_sitemap.xml", "https://crawler-test.com/sitemap.xml.gz"]}}
auditSummary
{"recordType": "auditSummary","url": "https://crawler-test.com/links/broken_links_internal","data": {"pagesCrawled": 3,"pagesByStatus": {"2xx": 2, "4xx": 1},"healthScore": 52,"issueCounts": [{"code": "INTERNAL_LINK_TO_4XX", "severity": "high", "count": 1},{"code": "VIEWPORT_MISSING", "severity": "medium", "count": 2}]}}
🔌 Run it your way
- Schedule it in the Console (daily or weekly) and watch the
auditSummaryhealth score and issue counts over time. - Start it from the API with the same input as in the Console and read the dataset of the run.
- Send the data on to Google Sheets, Slack, a webhook, Make, Zapier or your own tool through Apify integrations.
- Use it from an AI agent through the Apify MCP server:
Audit https://example.com with the seo-site-audit-scraper actor, crawl up to 200 pages and list the high severity issues with their fixes.
Pricing
Pay per event. There is no start fee. Free plan: each run returns up to 1,000 rows; upgrade your Apify plan for more.
| Event | Price | When it is charged |
|---|---|---|
seo-page-audited | $0.0020 ($2.00 per 1,000) | One page audited with all its checks and issue codes. |
seo-audit-summarized | $0.0010 ($1.00 per 1,000) | One summary row per audited site. |
seo-link-checked | $0.0005 ($0.50 per 1,000) | One broken link, redirect chain or internal link row. |
seo-sitemap-url-read | $0.0002 ($0.20 per 1,000) | One URL read from a sitemap. |
seo-robots-read | $0.0010 ($1.00 per 1,000) | One parsed robots.txt file. |
Data
This actor returns only what the site shows publicly at run time. We don't store or keep that data and are not its controller — you decide how you use it. It audits public sites, respects robots.txt by default and keeps a polite pause between requests. This actor is not affiliated with or endorsed by any site you audit, or by any SEO tool vendor.
🩺 If a run fails
The run health (the RUN_HEALTH record, RUN_SUMMARY and the last line of the log) names the cause, for example site down: list request answered 500 x3. Find that start of the message in the table.
| Error in the log / run health | What it means | What you do |
|---|---|---|
site down: <request> answered 500, 502-504, 520-526 | The site is offline or has a fault. The actor waits longer between tries, then stops the run. | Try again later. |
blocked: <request> answered 401, 403, 1020 or a captcha page | The site refused the request or showed a captcha page. The actor does not use a proxy. | Try again later, or ask the site owner to allow the actor's User-Agent. |
rate limited: <request> answered 429 | The site asks for fewer requests. The actor waits and slows down by itself. | Try again later. |
gone: <request> answered 404, 410 | The page was removed. The actor records it as a finding (a row with the status) and goes on. | Nothing; this is normal. |
network error: <request> failed with timeout (or connection error, DNS error) | A timeout or a broken connection. The actor retries with a pause. | Try again later. |
wrong answer: <request> returned HTML instead of JSON (or an empty body) | The site answered with a page that is not data (HTML instead of JSON, an empty body). The site has probably changed. | Report it in the Issues tab; we fix it. |
❓ FAQ
How do I run a technical SEO audit of my website?
Enter your site in Start URLs, keep the mode on crawl and start the run. Read the pageAudit rows for on-page issues, brokenLink and redirectChain rows for link problems and the auditSummary row for the overall health score.
How do I find broken links and redirect chains?
Run a crawl. Every internal link that answers 4xx or 5xx becomes a brokenLink row with its source page and anchor text; every redirect with two or more hops becomes a redirectChain row. Switch on checkExternalLinks for outbound links too.
Does it show backlinks?
No. It audits one site: its pages, internal links and anchor text, and the outbound links you ask it to check. It has no backlink index.
How do I export the SEO audit data to Excel or CSV?
Open the Output tab of the run and download the data in the format you need.
How do I scrape a website with the API?
Start the actor from the Apify API with the same input as in the Console and read the dataset of the run.
💬 Feedback and custom work
Need another check, a field or a custom feed? Open the Issues tab and tell us.