How it will work: 3 steps
- Follow us on ApifyThe tool is built and waits in the queue for the Apify Store. Apify is the cloud platform where our tools run.
- Paste your input and press StartNo code needed: you fill in a form (the input). It already has a working example. For example:
https://apify.comin Website URL. Each start is one run. - Download the resultsWhen the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.
This tool is an Apify Actor: a small program that runs on Apify. You can also run it on a schedule, for example every Monday. New to it? Read how it works, step by step and the 8 words you need first.
What it does
SEO Site Audit crawls one website from a start URL and checks every page it finds: HTTP status, redirect chain, broken links, title, meta description, canonical, hreflang, headings, noindex and page size. You get one row per page with a list of issues sorted by priority, plus one readable report for the whole site.
- Status and redirects: the HTTP status code, every redirect hop (
redirectChain) and the final URL. - Links: broken internal links (4xx, 5xx or no answer) and broken external links (4xx, 5xx or a domain that does not exist), with the page where each one was found.
- Meta tags: title and its length, meta description and its length, canonical, meta robots and
X-Robots-Tag, noindex, nofollow,lang, hreflang. - Content: the first H1, H1 and H2 counts, word count, images without an
altattribute. - Speed signals: response time, time to first byte and HTML size. Optional Google PageSpeed (Lighthouse) score and Core Web Vitals with your own free Google API key.
- Issues: a list of found problems (
issues[]) with a code, severity (critical,high,medium,low) and a short message, plus a page score from 0 to 100.
Good for
- Find broken links and the pages that contain them before users or search engines do.
- Check titles, meta descriptions, canonical tags and noindex on every page after a redesign or migration.
- Find redirect chains and internal links that point to redirects.
- Get a quick technical SEO health check of a client or competitor site.
Not a good fit
- Sites that build their content with JavaScript only. The Actor reads the server HTML, so text and links added later by scripts are not seen.
- Pages behind a login, a paywall or bot protection that blocks normal crawlers.
- Keyword research, rankings, backlinks or traffic data. This Actor checks your pages, not search results.
- Many websites in one run. Use one run per website.
Who uses it
SEO specialists
Check titles, canonicals and noindex tags after a redesign.
Web developers
Find broken links and redirect chains before users do.
Marketing agencies
Run a quick health check on a competitor site or many brands.
Price
Prices will be shown after release.
Questions
Do I need an account or an API key?
No. It checks public pages without login. A Google key is needed only for PageSpeed tests.
Does it run JavaScript like a browser?
No. It reads the HTML that the server returns. Text added by scripts is not seen.
Can I audit several websites in one run?
No. Use one start URL per run. Start one run for each site.
Will it find pages with no links to them?
No. It finds pages that links from the start URL can reach.
Am I charged for 404 pages and redirects?
Yes, when they are on your site: a page that answers 404 or 301 is a checked page and an important finding. Pages that give no answer at all are free. When the start URL itself fails, only the start fee is charged.
Is the result complete?
It is complete for the pages the crawler can reach by links from the start URL, within your limits and robots.txt. Pages that no link points to (orphan pages) are not found.
Details
Step by step on Apify
- Open the Input tab.
- Add your website to Website URL (
startUrl), for examplehttps://example.com. - Keep Max pages (
maxPages) at the suggested 20 for a first test. - Click Start.
- Open the Output tab. The Pages by priority view shows the pages with the lowest score first (rows are saved in that order). Open the Audit report (HTML) for a readable summary.
Use cases
| Task | Input | Key fields |
|---|---|---|
| Fix broken links | startUrl, checkExternalLinks | brokenLinks, brokenLinksCount, url |
| Check meta tags after a redesign | startUrl, maxPages | title, titleLength, metaDescription, canonical, noindex |
| Clean up redirects after a migration | startUrl (old domain or new) | redirectChain, finalUrl, statusCode |
| Check hreflang on a multi-language site | startUrl, includeSubdomains | hreflang, lang, issues |
| Weekly site health check | startUrl on a schedule | RUN_SUMMARY.siteHealthScore, issuesBySeverity |
| Speed check of key templates | pagespeedApiKey, pagespeedMaxPages | pagespeed.performanceScore, pagespeed.largestContentfulPaintMs |
Tips for better results
- Run it after each site move to catch broken links early.
- Add your free Google API key if you want PageSpeed scores.
- Start one run for each site, because one run takes one start URL.
Limits and good to know
- HTML only, no JavaScript. Titles, headings, links and text are read from the HTML the server sends. On sites that render content in the browser, H1, word count and links can be missing
- One site per run, up to 2000 pages. Subdomains only with
includeSubdomains - robots.txt is always respected. If
robots.txtanswers with a server error, the Actor checks only the start URL and reportsrobots_txt_unavailable - Internal links are checked when the linked page is crawled in the same run. Links to files (PDF, images and similar) are checked separately, up to 500 per run. Pages beyond
maxPagesare not checked - External links: up to
maxExternalLinksand up to 20 per checked page. Answers 401, 403, 429 and 999, timeouts and loops are reported asrestricted_external_links(could not verify), not as broken, because many sites block automated checks. Link checks stop after 10 timeouts in a row and take at most about 60 s plus 1 s per checked page; links left unchecked are counted inRUN_SUMMARY.externalLinksSkipped - A redirect to another website (for example to a login service) is a normal row with status 301 or 302 and is charged as one page
- HTML larger than 5 MB is checked by its first 5 MB
- PageSpeed depends on your Google key and quota. A failed test is saved as
pagespeed.status = "error"with a reason such asinvalid_api_keyorquota_exceeded, and is not charged. Tests stop after 2 failures in a row, after a wrong key or quota error, or after a failed test that took over 30 s (a test is stopped at 60 s). PageSpeed is skipped when the site stopped answering (SOURCE_ERROR)
For developers
Sample result
One result from a real test run, in JSON. Real values change from run to run. In Excel or CSV each field is a column.
{
"url": "https://apify.com/integrations",
"finalUrl": "https://apify.com/integrations",
"status": "ok",
"statusCode": 200,
"redirectChain": [],
"depth": 1,
"title": "Connect Apify with your apps · Apify",
"titleLength": 36,
"metaDescription": "Integrate the Apify platform and Actors with your favorite tools, APIs, and cloud services. Trigger workflows, send data in real time, and power your AI and apps with live web automation.",
"metaDescriptionLength": 187,
"h1Count": 1,
"canonical": "https://apify.com/integrations",
"isCanonicalSelf": true,
"noindex": false,
"hreflang": [],
"wordCount": 1674,
"responseTimeMs": 162,
"pageSizeBytes": 949320,
"brokenLinks": [
{ "url": "https://www.relay.app/apps/apify/integrations", "type": "external", "statusCode": 404, "error": null },
{ "url": "https://block.github.io/goose/docs/mcp/apify-mcp/", "type": "external", "statusCode": 404, "error": null }
],
"brokenLinksCount": 2,
"pagespeed": null,
"issues": [
{ "code": "broken_external_links", "severity": "medium", "message": "2 broken external links" },
{ "code": "meta_description_too_long", "severity": "low", "message": "Meta description has 187 characters" },
{ "code": "restricted_external_links", "severity": "low", "message": "6 external links could not be verified (401/403/429, timeout or redirect loop)" }
],
"issuesCount": 3,
"topSeverity": "medium",
"score": 88,
"error": null,
"fetchedAt": "2026-10-17T08:21:08.535Z"
}Data fields (40)
| Field | Type |
|---|---|
url | string |
finalUrl | string |
status | string |
statusCode | integer |
redirectChain | array |
depth | integer |
linkedFrom | string |
contentType | string |
isHtml | boolean |
responseTimeMs | integer |
ttfbMs | integer |
pageSizeBytes | integer |
title | string |
titleLength | integer |
metaDescription | string |
metaDescriptionLength | integer |
h1 | string |
h1Count | integer |
h2Count | integer |
canonical | string |
isCanonicalSelf | boolean |
noindex | boolean |
nofollow | boolean |
robotsMeta | string |
xRobotsTag | string |
lang | string |
hreflang | array |
wordCount | integer |
imagesMissingAlt | integer |
internalLinksCount | integer |
externalLinksCount | integer |
inlinksCount | integer |
brokenLinks | array |
brokenLinksCount | integer |
pagespeed | object |
issues | array |
issuesCount | integer |
topSeverity | string |
score | integer |
error | string |
Input settings (12)
The main fields of the input form. With the API you send them as JSON.
| Setting | Name in the API | Type | Example value |
|---|---|---|---|
| Website URL required | startUrl | string | "https://apify.com" |
| Max pages | maxPages | integer | 20 |
| Max link depth | maxDepth | integer | |
| Check external links | checkExternalLinks | boolean | true |
| Max external links to check | maxExternalLinks | integer | 300 |
| Include subdomains | includeSubdomains | boolean | false |
| Exclude URLs | excludeUrlPatterns | array | |
| Concurrent requests | maxConcurrency | integer | 5 |
| User-Agent | userAgent | string | |
| Google PageSpeed API key (optional) | pagespeedApiKey | string | |
| PageSpeed pages | pagespeedMaxPages | integer | 1 |
| PageSpeed device | pagespeedStrategy | string | "mobile" |