SEO Audit
Pricing
from $4.25 / 1,000 page auditeds
SEO Audit
Audit many web pages at once and get one row per page with a 0-100 score, titles, headings, links, indexability, structured data and a list of fixes ranked by importance. Plain HTTP only, $5 per 1,000 pages.
Pricing
from $4.25 / 1,000 page auditeds
Rating
0.0
(0)
Developer
Ishaan Pare
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Audit many web pages in one run and get a ranked list of what to fix on each, at $5 per 1,000 pages. Give it a list of addresses, or let it follow internal links from them. Each page comes back as one row with a 0 to 100 score, the page's SEO details, and its issues in fix-first order.
You don't need a login, a browser, proxies or an API key. The Actor reads pages over plain HTTP and respects each site's robots.txt.
What you get
- One row per page, with the same fields every time
- A score from 0 to 100 and a
topFixfield, the single most useful thing to do first - Issues sorted most important first, each with a severity, a code, a message and a fix
- Title, meta description, canonical, robots rules, headings, word count, images and alt text
- Internal and external link counts, plus broken links when you turn that on
- Viewport, language, hreflang, structured data types, Open Graph and Twitter card
- Page size, response time, HTTPS, robots.txt result, sitemap listing and the full redirect chain
Sample output
{"recordType": "audit","url": "http://shop.example/desks","finalUrl": "https://shop.example/desks","httpStatus": 200,"redirectChain": [{ "url": "http://shop.example/desks", "httpStatus": 301 }],"score": 76,"title": "Oak desks","titleLength": 9,"metaDescription": null,"metaDescriptionLength": 0,"canonical": "https://shop.example/desks","robotsMeta": null,"xRobotsTag": null,"isIndexable": true,"h1Count": 1,"firstH1": "Handmade oak desks","headingOutline": { "h1": 1, "h2": 4, "h3": 2, "h4": 0, "h5": 0, "h6": 0 },"wordCount": 812,"imageCount": 14,"imagesMissingAlt": 2,"internalLinks": 38,"externalLinks": 3,"brokenLinks": null,"linksChecked": null,"linksNotChecked": null,"hasViewport": true,"lang": "en","hreflangCount": 0,"structuredDataTypes": ["Organization", "Product"],"openGraph": true,"twitterCard": true,"pageSizeBytes": 84211,"responseTimeMs": 412,"usesHttps": true,"robotsTxtAllowed": true,"inSitemap": true,"issues": [{"severity": "high","code": "missing_meta_description","message": "The page has no meta description.","fix": "Add a meta description of 70 to 160 characters that sums up the page and gives a reason to click."},{"severity": "medium","code": "title_too_short","message": "The title has 9 characters, under the suggested 30.","fix": "Expand the title to 30 to 60 characters with the page's main topic."},{"severity": "medium","code": "images_missing_alt","message": "2 of 14 images have no alt attribute.","fix": "Add alt text that describes each image, or alt=\"\" for images that are only decoration."},{"severity": "low","code": "single_redirect","message": "The address redirects once before the page loads.","fix": "Link directly to the final address where you can."}],"topFix": "Add a meta description of 70 to 160 characters that sums up the page and gives a reason to click.","status": null,"reason": null,"fetchedAt": "2026-11-02T10:00:00.000Z"}
This example shows the format, and the page is made up.
How to use it
- Add your page addresses, one per line. A bare domain such as example.com is read as https://example.com.
- Set Maximum pages, which also caps the cost. Turn on Follow internal links or Check links if you want them.
- Press Start, then sort the results by
scoreor filter onrecordTypeequal toaudit.
The example input audits two pages. A run with no input at all uses those same two pages, so it costs about $0.01. An explicitly empty address list audits nothing, costs nothing and returns a status row.
Input options
| Option | Default | What it does |
|---|---|---|
| urls | Two example pages | The pages to audit |
| maxPages | 100 | Stops after requesting this many pages, up to 10,000. Failed pages count, and pages robots.txt blocks don't |
| followInternalLinks | Off | Also audits pages linked from each audited page on the same site. Skips links marked nofollow, pages with a nofollow robots tag, and links to files such as PDFs and images |
| maxPagesPerSite | 50 | When following links, stops adding pages for a site at this many |
| checkLinks | Off | Requests the links on each page and lists the broken ones |
| maxLinksPerPage | 25 | When checking links, how many different links to check per page, up to 100 |
A link is listed as broken only when it answers a clear error such as 404 or 410, or when its host doesn't exist or refuses connections. Answers such as 403, 429 or a server error often mean a site is turning bots away, so those links are counted in linksNotChecked and aren't called broken. Link checking costs nothing extra, but it makes runs slower.
What it checks
| Severity | Issue codes |
|---|---|
| Critical | noindex_meta, noindex_header, blocked_for_googlebot, missing_title |
| High | broken_links, not_https, missing_h1, missing_meta_description, missing_viewport |
| Medium | canonical_points_elsewhere, multiple_canonicals, missing_canonical, redirect_chain, thin_content, multiple_h1, title_too_short, title_too_long, images_missing_alt, missing_lang, invalid_structured_data, not_in_sitemap, slow_response |
| Low | description_too_short, description_too_long, single_redirect, large_page, skipped_heading_level, no_internal_links, missing_structured_data, missing_open_graph, missing_twitter_card |
The score starts at 100 and drops by 25 for each critical issue, 12 for each high, 5 for each medium and 2 for each low, and it stops at 0. It's our own measure for ranking your pages against each other, not a score from Google or any other search engine. Length limits such as 30 to 60 characters for titles are common rules of thumb, not search engine rules.
Pricing
You pay only for pages that are audited, and Apify platform usage is included.
| Event | Price |
|---|---|
| Each page audited | $0.005 ($5 per 1,000) |
| Each run started | $0.00005 |
Status rows are free, so you aren't charged for pages that are blocked, missing, not HTML or unreachable. Checking links and following links add no separate charge, though each extra page you follow is billed as one audit.
A run stops at the maximum cost you set, and a status row tells you when that happens. On the free Apify plan, each run covers up to 100 pages, and a status row tells you when you reach that limit. Any paid Apify plan removes it.
Status rows
When a page can't be audited, you get a free row with recordType set to status. It has the same fields as an audit row, with status and reason filled in.
| Status | Meaning |
|---|---|
| no_urls | No addresses were given |
| invalid_url | The text isn't a valid web address |
| blocked_url | The address isn't allowed: private, internal or loopback, not http or https, or it contains a password |
| robots_blocked | The site's robots.txt doesn't allow this Actor to read the page, so it wasn't fetched |
| robots_unavailable | The site's robots.txt answered with a server error, so the page wasn't fetched |
| not_html | The address returned something other than an HTML page |
| too_large | The page is over 5 MB |
| http_error | The site answered with an error such as 404 or 403, shown in httpStatus |
| redirect_error | Too many redirects, a redirect loop, or a redirect to an invalid address |
| fetch_failed | The site couldn't be reached, and reason says why |
| audit_failed | The page was read, but something went wrong while auditing it |
| site_limit | Maximum pages per site was reached for a site |
| max_pages | Maximum pages was reached |
| free_limit | The run reached the free plan limit |
| spending_limit | The run reached your maximum cost |
A run in which every page gets a status row still finishes as succeeded, so check the status rows when you see no audits.
What it can't do
- JavaScript isn't run. The Actor reads the HTML the server sends. Text, links and tags that JavaScript adds later aren't seen, so a JavaScript-rendered page can show false issues such as a missing H1 or thin content. The thin_content message says when a page looks like this.
- It doesn't measure Core Web Vitals, rendering speed or mobile layout.
responseTimeMsis the time to download the HTML from our server, so it won't match what your visitors see. - It doesn't use proxies, solve CAPTCHAs or log in. Sites that turn away automated requests return a free
http_errorrow. - It doesn't track rankings, keywords or backlinks.
- It treats www and non-www as one site. Other subdomains count as separate sites and external links.
- Text fields past 1,000 characters are cut. The length fields still give the full length.
inSitemapreads up to 10 sitemap files and 10 MB per site. If it can't read them all and the page isn't in those it read, the field is null rather than false.
How it treats sites
The Actor identifies itself as seo-audit-actor and checks robots.txt before every page, redirect, sitemap and link check. It makes at most 2 requests at once per host, waits 500 ms between request starts, and honours Crawl-delay up to 10 seconds. It refuses private and internal addresses, including when a public page redirects to one. It stops reading any response at 5 MB.
Using it with AI agents
The main input is a list, every field is optional, and no credentials are needed. An agent can audit many pages in one call, act on topFix, and read status rows to see what went wrong.
Data and use
This Actor reads only public pages and stores only the fields shown above. You are responsible for auditing pages in line with the sites' terms. This Actor is not affiliated with or endorsed by Google, any other search engine, or any site you audit.
Support
Open an issue on the Issues tab with your input and what you expected.