Site Audit: Full-Site SEO Audit with Fixes
Pricing
from $3.50 / 1,000 pages
Site Audit: Full-Site SEO Audit with Fixes
Audit every page of a website for SEO problems in one run. Each page gets a score from 0 to 100, its issues and a one-line fix for each. Run it again and each page is marked new, changed or unchanged, with pages that are gone. $0.005 per page, no browser, no monthly fee.
Pricing
from $3.50 / 1,000 pages
Rating
0.0
(0)
Developer
Brian Gomes
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 hours ago
Last modified
Categories
Share
Audit every page of a website for technical SEO problems in one run. Each page gets an SEO score from 0 to 100, a list of its issues and a plain-English fix for each one. Run it again next week and it shows you what changed.
- Full-site SEO crawler. It reads the sitemap and the pages your menus link to that the sitemap leaves out. With no sitemap, it crawls the site's links. Up to 50,000 pages a run.
- One page in seconds. Set How to find pages to This page only to audit a single URL, for the price of one page.
- Ready for code and AI agents. Every output field is typed, and agents can run it through Apify's MCP server.
- 34 checks on every page. Titles, meta descriptions, H1s, canonicals, noindex, broken internal links, redirects, mixed content, alt text, slow pages and more.
- Structured data and AI readiness. Product data for Google's merchant listings, breadcrumbs and share images on every page. For the whole site: whether robots.txt lets AI crawlers in, and whether there's an /llms.txt.
- A fix for every issue. Hand the list to whoever runs the site. The summary row ranks the 10 fixes that matter most.
- Week-over-week changes. Every page is marked new, changed, unchanged or removed, with the issues that appeared and the ones you fixed.
- A summary you can read in a minute. Every run ends with one in plain English: the score, what's new, what you fixed and what's still open.
- $5 per 1,000 pages. Other SEO audit Actors in the Store charge $10 to $40 for the same 1,000 pages. No browser, no subscription.
Quick start
- Put your homepage in Start URL.
- Click Start. The form is set to 10 pages, so your first audit costs $0.05.
- Read the run summary first. Then open the results, sort by
scoreand work from the top fixes.
Read this first: the run summary
Every run ends with a short summary in plain English. Here is one from a week with changes (example data):
Score 95 (up 1 from 94). 1 new problem, 1 fixed.## New problems (1)- **No meta description** on https://example.com/products/aria. Fix: Add a meta description, 70 to 160 characters, that sums up the page.## Fixed since last run (1)- **Broken internal links** on https://example.com/policies/privacy-policy.## Still open (56)- **Product photos with empty alt text** on 21 pages.- **No share image** on 35 pages.## AI readinessrobots.txt lets all 4 AI crawlers in (GPTBot, ClaudeBot, PerplexityBot and Google-Extended). /llms.txt found.## Run- Site: https://example.com/- Pages audited: 86. Not audited: 1. Error rows: 0.- Audited 2026-11-02 13:00 UTC by Site Audit 0.3.
The number after a heading counts problems: one issue on one page is one problem. Long lists stop at 25 items, then say how many more are in the dataset.
A quiet week is one line: All clear. Score 94, nothing changed.
- What counts as a change: issues only. A page whose text alone changed, like a stock count or a date, isn't news.
- First run: there's nothing to compare yet, so it lists the top 5 fixes instead. So does a run with Compare with the previous run off.
- New checks: after an update adds a check, its findings are listed as new checks, not new problems.
- Where it is: the run's status message starts with the first line, then the run's counts. The full text is
SUMMARY.mdin the run's key-value store, andsummaryTexton the summary row. In the Console, it's the first link on the run's Output tab. By API:https://api.apify.com/v2/actor-runs/<runId>/key-value-store/records/SUMMARY.md. - Cost: none. It's built from fixed templates, with no AI.
What does this SEO audit check?
| Check | Issue id | Severity |
|---|---|---|
| The page answers with an error (4xx or 5xx) | http-error | error (the page scores 0) |
| The page redirects before it answers. The full chain is listed | redirect | warning |
| Slow response, over 3,000 ms by default | slow-response | warning |
| Title missing or empty | title-missing | error |
| Title over 60 or under 10 characters | title-too-long, title-too-short | notice |
| Same title as another page. Every page that shares it is flagged. Language or region versions of one page, linked by hreflang, don't count | title-duplicate | warning |
| More than one title element | title-multiple | notice |
| Meta description missing | meta-description-missing | warning |
| Meta description over 160 or under 50 characters | meta-description-too-long, meta-description-too-short | notice |
Same meta description as another page, flagged on each. hreflang versions don't count. Nor do pages 2 and on of a series (?page=2, rel="prev") | meta-description-duplicate | warning |
A meta description that's a URL handle (like red-lace-bodysuit-plus-size), not a sentence | meta-description-is-url | warning |
A title or meta description escaped twice, so search results show & or ' as text | double-escaped-text | warning |
| No H1 | h1-missing | warning |
| More than one H1 | h1-multiple | notice |
| An H1 with no text, like a logo image alone | h1-no-text | notice |
| No canonical link | canonical-missing | notice |
| A canonical that points to another URL | canonical-elsewhere | notice |
| noindex in meta robots or the X-Robots-Tag header | noindex | warning |
noindex on a page the sitemap lists. On Shopify, the fix names the seo.hidden metafield | noindex-in-sitemap | warning |
No lang attribute on <html> | lang-missing | notice |
| Images with no alt attribute | images-missing-alt | warning |
Product photos and other content images with empty alt text (alt=""). That means images in a product gallery, or 200 px and up outside the header, footer and menus. Small and decorative images (role="presentation") can keep alt="" | images-empty-alt | notice |
| Internal links that are broken, each listed with its status or error | broken-internal-links | error |
| Images, scripts, stylesheets or frames loaded over http on an https page | mixed-content | warning |
| HTML over 2 MB | page-too-large | warning |
| The page was cut off (over 5 MB, it stopped arriving, or its HTML couldn't be parsed past a point) | page-incomplete | warning |
| A JSON-LD block that doesn't parse as JSON | structured-data-invalid | warning |
| Product JSON-LD with an offer missing its price, priceCurrency or availability, or with no offers and no reviews | product-offer-incomplete | warning |
Product JSON-LD with no shippingDetails (gift cards and a store-wide hasShippingService don't count) | product-shipping-missing | notice |
Product JSON-LD with no hasMerchantReturnPolicy, on the offers or the Organization | product-returns-missing | notice |
Product JSON-LD with no aggregateRating or review | product-reviews-missing | notice |
A product, collection or article page with no BreadcrumbList (JSON-LD or microdata) | breadcrumbs-missing | notice |
No og:image, so a shared link shows no picture | og-image-missing | notice |
No og:title | og-title-missing | notice |
Product, collection and article pages are told apart by their JSON-LD and og:type. Each page row lists its JSON-LD types in structuredDataTypes.
Site-wide checks: AI readiness
Two checks look at the whole site, once per run. Their issues go on the summary row, not on every page.
| Check | Issue id | Severity |
|---|---|---|
| robots.txt stops GPTBot, ClaudeBot, PerplexityBot or Google-Extended from reading the home page | ai-crawlers-blocked | warning |
No /llms.txt, or an HTML page in its place | llms-txt-missing | notice |
The summary row's aiReadiness says which AI crawlers are allowed or blocked, and whether /llms.txt was found. A This page only audit skips these checks.
How is the SEO score calculated?
Every page starts at 100. It loses 30 for each error, 10 for each warning and 3 for each notice, and stops at 0. A page that answers with an error status scores 0.
Files that aren't HTML, like a PDF or the /agents.md file Shopify lists in its sitemaps, get their status, redirects and X-Robots-Tag checked, but no score: a score would only say they have no title. They're free, and the row's note says so.
Every issue comes with a fix you can hand to whoever runs the site. Two examples, word for word from the output:
title-too-long: "Shorten thenoindex-in-sitemap: "Either remove noindex or remove the page from the sitemap: the two contradict each other."
On a Shopify store, some fixes name the setting to change. For noindex-in-sitemap, that's the page's seo.hidden metafield.
The summary row at the end gives the site score and the issue counts by type. It also ranks the ten fixes that matter most across the site, by severity times pages. The site score is the average page score, less 10 per site-wide warning and 3 per site-wide notice. The plain average is in pageScoreAverage.
Track SEO changes week over week
This is the part you'll use every week.
The first run audits the site. Every run after that on the same start URL compares against the last one and marks each page:
- new: it wasn't there last time
- changed: its score, its issues, its status code or its visible text changed
- unchanged: nothing changed
- removed: it was there last time and isn't now
Each changed page says what moved in changeReasons: status, issues, score or content (the visible text). Each page row also carries previousScore, newIssues (issues that appeared) and fixedIssues (issues that went away). The summary row counts all of it, plus the pages that answered fine last time and now redirect or fail.
So you don't read a 500-row audit every week. You read what moved.
On shops and news sites, many pages change only in their text from one run to the next: a rotating "you may also like" row, a date, a stock count. Those show changeReasons: ["content"], and the run's status line counts them apart. To see only SEO changes, filter on issues or score.
How it works: the Actor keeps a small record of each page's score, issues, status code and a fingerprint of its text, in your own account's key-value store named site-audit-history. A This page only audit keeps its own record, apart from full-site audits of the same URL. Delete that store in Storage to start fresh. Turn off Compare with the previous run to skip it.
A run that stops early (at your page limit or your maximum charge), or that couldn't read a sitemap in full (it timed out, or answered 429 or a server error), never calls a page removed. It keeps the pages it didn't reach in the record for next time.
To be told when something breaks, schedule the Actor with Apify Schedules and connect a webhook or an integration like Slack, email or Google Sheets.
How it finds pages: sitemap, crawl or one page
- Auto (the default): it reads the sitemap first. It looks for Sitemap lines in robots.txt, then /sitemap.xml and /sitemap_index.xml, follows sitemap indexes and reads gzipped sitemaps. Then it audits pages the start page's header, footer and menus link to, if the sitemap leaves them out. On Shopify, that's the policy pages and /collections/all. Those rows say
foundIn: link. Carts, account and search pages, links with a query string and pages robots.txt disallows are skipped. If the site has no sitemap, it follows links from the start page instead. - Sitemap only: audits the pages the sitemap lists, including ones no menu links to anymore. Only pages found in a sitemap get the
noindex-in-sitemapcheck. - Crawl only: follows links from the start page, on the same site only (with or without www.), up to the depth you set. Links to files like images, PDFs, CSS and JS aren't followed as pages.
- This page only: audits the start URL and nothing else. No sitemap is read and no links are followed as pages, though its internal links are still checked. It's the quickest run, usually a few seconds, and costs one page.
You can also give it a sitemap URL as the start URL, and it reads that sitemap directly.
Page content as Markdown (optional)
Turn on Include page content as Markdown and each row gets the page's main content as Markdown: headings, paragraphs, lists and code blocks. It takes <main> or <article> when the page has one. Otherwise it takes the body and leaves out navigation, header, footer, sidebars and forms. Up to 50,000 characters per page. Link targets aren't kept. It costs nothing extra.
Input
| Field | What it does | Default |
|---|---|---|
startUrl | The website, like https://example.com, or a sitemap URL. | required |
maxPages | Stop after auditing this many pages. Only pages that answer are counted and charged; files that aren't HTML and pages the site rate-limits aren't. 1 to 50,000. | 100 |
discovery | auto, page (this URL only), sitemap or crawl. | auto |
maxDepth | When crawling, how many clicks from the start page to follow. 0 audits the start page only. | 5 |
checkInternalLinks | Check each link to the same site once and list the broken ones on every page that has them. | true |
compareWithPreviousRun | Mark each page new, changed, unchanged or removed since the last run. | true |
includeMarkdown | Add the page's main content as Markdown. | false |
slowThresholdMs | A page slower than this gets a slow-response issue. | 3000 |
maxConcurrency | Requests in flight at once, 1 to 20. Never more than 4 to one host. | 5 |
requestTimeoutSecs | How long to wait for any one request. | 20 |
The form starts at 10 pages, so your first audit costs $0.05.
Example input:
{"startUrl": "https://example.com","maxPages": 500,"discovery": "auto","checkInternalLinks": true,"compareWithPreviousRun": true}
Output: what you get for each page
Export the dataset as CSV, JSON, Excel, XML or HTML, or read it through the Apify API. It has four kinds of rows:
- one row per page audited (
type: page) - one row per page that disappeared since the last run (
type: page,change: removed) - an error row when something couldn't be read, like a missing sitemap (
type: error) - one summary row at the end (
type: summary)
The summary row holds the site score, the top fixes and counts in summary. It also has the run summary as Markdown, in summaryText. The same text is saved as SUMMARY.md in the run's default key-value store. The run's status message starts with its first line. See "Read this first" above.
A page row holds: url, audited, score, issueCount, issues (each with id, severity, message and fix), change, changeReasons, previousScore, newIssues, fixedIssues, statusCode, finalUrl, redirectCount, redirectChain, responseTimeMs, contentType, htmlBytes, title, titleLength, metaDescription, metaDescriptionLength, h1Count, canonicalUrl, noindex, lang, imagesMissingAlt, imagesEmptyAlt, internalLinks, brokenInternalLinks (up to 20 listed, all counted), mixedContent (up to 20 listed), structuredDataTypes, wordCount, contentHash, foundIn (sitemap, link, crawl or page), depth, markdown, markdownTruncated, note (something worth knowing that isn't an error, like a file that isn't HTML; on the summary row, why the run stopped early), error, startUrl.
Example page row (example data, real field names):
{"type": "page","url": "https://example.com/pricing","audited": true,"score": 57,"issueCount": 3,"issues": [{"id": "title-too-long","severity": "notice","message": "The title is 74 characters.","fix": "Shorten the <title> to 60 characters or fewer so search results don't cut it off."},{"id": "meta-description-missing","severity": "warning","message": "The page has no meta description.","fix": "Add a meta description, 70 to 160 characters, that sums up the page."},{"id": "broken-internal-links","severity": "error","message": "1 internal link(s) are broken.","fix": "Fix or remove the links listed in brokenInternalLinks."}],"change": "changed","changeReasons": ["issues", "score"],"previousScore": 97,"newIssues": ["broken-internal-links", "meta-description-missing"],"fixedIssues": [],"statusCode": 200,"finalUrl": "https://example.com/pricing","redirectCount": 0,"responseTimeMs": 412,"title": "Pricing plans for teams of every size, billed monthly or yearly | Example","titleLength": 74,"metaDescription": null,"h1Count": 1,"canonicalUrl": "https://example.com/pricing","noindex": false,"lang": "en","imagesMissingAlt": 0,"imagesEmptyAlt": 0,"internalLinks": 38,"structuredDataTypes": ["Organization", "WebPage"],"wordCount": 912,"foundIn": "sitemap","depth": 0,"note": null,"error": null}
Any text in the output that starts with =, +, - or @ (a title, a meta description, Markdown, a header value, a URL) gets a leading ', so it can't run as a formula when you open the dataset in a spreadsheet.
How much does an SEO audit cost?
You pay per page audited. There's no monthly fee.
- Each page audited: $0.005. A page counts when it answers with a status code, errors and redirects included.
- Free: pages skipped for robots.txt, pages that never answer, pages a site still rate-limits (HTTP 429) after retries, files that aren't HTML (PDFs, Markdown), menu links that redirect to a page already audited, internal link checks, the robots.txt and /llms.txt checks, the run summary, Markdown, removed-page rows, error rows and the summary row.
- Discounts: on Apify's discount tiers the price drops to $0.0045 (Bronze), $0.004 (Silver) and $0.0035 (Gold and above).
- Apify's standard start fee applies to each run.
Worked examples, at the base price:
- A 100-page site: $0.50 per audit.
- A 500-page site: $2.50 per audit. Every week, about $10 a month.
- A 5,000-page site: $25 per audit.
For a hard ceiling, set maxPages or a maximum charge per run. The run stops cleanly when it reaches your maximum charge.
Limits
- No JavaScript rendering. A page built in the browser by a client-side framework is audited on the HTML the server sends, which may be thin.
- Some pages are fetched twice when crawling. Each internal link is checked once per run, up to 100 new links per page, and the link check doesn't read the page body. When crawling, a page that was link-checked is requested again when its turn comes to be audited. You're charged once.
- Rows arrive in batches. Page rows wait until 1,000 more pages are audited, or the run ends. That way a duplicate title or description is flagged on both pages. On runs over 1,000 pages, a page stored before its duplicate turned up isn't flagged. The later page is, and names it. Pages are charged as their rows are stored.
- It stops on its own when a site stops answering: 20 requests in a row with no answer, or 10 minutes spent waiting. It also stops when 5 pages in a row are still rate-limited (HTTP 429) after their retries, and says so.
- No proxies, no logins, no forms submitted.
robots.txt and good manners
- It respects robots.txt (RFC 9309). If robots.txt can't be reached, nothing on that site is fetched, and a row says why.
- It honours Crawl-delay up to 10 seconds, and sends at most 4 requests at a time to one host.
- When a site answers 429 Too Many Requests (Shopify does, to a crawler that asks too fast), it slows down on that site: one request start a second, doubling with each further burst of 429s up to 10 seconds. It tries the page or link again up to 3 times, waiting as long as Retry-After asks, up to 30 seconds. A page still rate-limited is reported as not audited, isn't charged and doesn't pull down the site score. A link to it isn't called broken.
- It identifies itself honestly as
SiteAuditHTTP/0.3.
Public websites only
Addresses on private networks, loopback and cloud metadata ranges are refused, including when a public page redirects to one.
FAQ
Is this a Screaming Frog alternative? For a cloud audit you can schedule, with no page cap and no software to install, yes. The difference: it doesn't render JavaScript, and a desktop crawler can. See Limits.
Does it check AI readiness (AEO or GEO)?
Yes, the parts you can see over HTTP. Every page gets checked for JSON-LD that parses, Product data Google's merchant listings use, breadcrumbs and share tags. For the whole site, it checks whether robots.txt lets GPTBot, ClaudeBot, PerplexityBot and Google-Extended in, and whether there's an /llms.txt. Look at the summary row's aiReadiness.
Does it work on JavaScript-heavy sites? It audits the HTML the server sends. A site that builds its pages in the browser (some React, Vue or Angular apps) may look thin, with titles or content missing.
Is it safe to run on my own site? Yes. It respects robots.txt and Crawl-delay, and sends at most 4 requests at a time to one host.
How do I run an SEO audit on my whole website?
Put your homepage in startUrl and run it. Sort the page rows by score, lowest first, and work from the summary row's top ten fixes.
How do I see only what changed since last week?
Filter the page rows on change. Anything changed, new or removed moved since the last run. changeReasons says what moved (a status, issues, the score, or only the text), and newIssues and fixedIssues say exactly which issues.
Why does a page have a lower score than last time?
Look at newIssues on that row. Each one has a message and a fix.
How do I audit a single page?
Put the page in startUrl and set How to find pages (discovery) to This page only (page). It audits just that URL, checks its internal links, and usually finishes in a few seconds. You pay for one page.
Do I need an API key or a login? No. It audits public pages over HTTP, so the only required input is the website.
Can an AI agent run it?
Yes. Claude, ChatGPT and other MCP clients can find and run it through the Apify MCP server. The only required input is startUrl, every output field is typed and described in the dataset schema, and it's approved for Apify's agentic payments, so an agent can pay for its own runs. For a question about one page, discovery: "page" answers in seconds.
Can I call it from my own code? Yes. Start it and read the results through the Apify API or the Python and JavaScript clients.
Integrations
This Actor runs on Apify, so everything the platform does works with it.
- API. Start a run and read the results from your own code, in any language. Apify API
- Schedules. Run it weekly and each run tells you what changed since the last one. Schedules
- Tasks. Save your input once as a task and run it again with one click, or on a schedule. Tasks
- Webhooks. Get a call to your own URL when a run succeeds or fails. Webhooks
- Google Sheets and Drive. Download the results as CSV or Excel and open them in Sheets. Or add a Google Sheets step after this Actor in Make or Zapier. Or send the files to a Google Drive folder. Datasets and exports, Google Drive
- Zapier, Make and n8n. Start a run from another app and send the results on to the next step. Zapier, Make, n8n
- AI agents (MCP). Claude, ChatGPT and other MCP clients can find and run this Actor through the Apify MCP server. Apify MCP server
- Other Actors. Pass this Actor's results to another Actor when a run finishes. Actor-to-Actor
The SEO toolkit
Five Actors that work together. All are priced per result, with no monthly fee.
| Actor | What you get | Price |
|---|---|---|
| Website SEO Audit & Crawler (this one) | A 0–100 SEO score and a fix list for every page, with week-over-week changes | $5 / 1,000 pages |
| Broken Link Checker | Every 404, server error and redirect chain, with the page it's on | $1 / 1,000 links |
| Bulk PageSpeed Insights | Lighthouse score and Core Web Vitals for every URL, mobile and desktop | $2.50 / 1,000 tests |
| Sitemap URL Extractor | Every URL in a site's sitemaps, with lastmod and status codes | $0.50 / 1,000 URLs |
| Website Screenshot API | A clean full-page screenshot of every URL, with cookie banners and pop-ups hidden | $8 / 1,000 screenshots |
Support
Found a bug or need a feature? Open an issue on this Actor's Issues tab. Include the run ID and the URL you gave it.
If it saved you time, a quick review on the Reviews tab helps other people find it.