On-Page SEO Audit Tool: SEO Checker & Crawler avatar

On-Page SEO Audit Tool: SEO Checker & Crawler

Pricing

from $7.00 / 1,000 pages

Go to Apify Store
On-Page SEO Audit Tool: SEO Checker & Crawler

On-Page SEO Audit Tool: SEO Checker & Crawler

SEO audit tool: crawls a website, or checks a list of pages, and audits the on-page SEO of each page: title, meta description, H1 and headings, canonical, noindex, image alt text, structured data, status codes and redirects. A 0-100 SEO score per page and a site report of duplicate titles.

Pricing

from $7.00 / 1,000 pages

Rating

0.0

(0)

Developer

Sanira Botheju

Sanira Botheju

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

What does On-Page SEO Audit do?

On-Page SEO Audit checks the SEO basics of every page of a website and gives each page a score from 0 to 100. You get one result per page in a table you can download as JSON, CSV or Excel or read through the API.

Enter a website. The tool starts at its address, follows the links to the other pages of the same site, and for each page reports the title, meta description, headings, canonical address, noindex, images without alt text, structured data, links and more. Every problem it finds is listed on the page with a code and a sentence that says what is wrong.

  • Crawls the site for you: follows links on the same site, up to the number of pages you set. Or turn crawling off and give it a list of pages.
  • One result per page: about 50 facts, a list of issues and a score. Sort by score to see the worst pages first.
  • A report for the whole site: duplicate titles, duplicate descriptions, pages with noindex, pages that returned errors, redirects, and pages the site's robots.txt does not allow.
  • Follows the rules of the site: reads robots.txt and does not fetch what it forbids, waits for a Crawl-delay, and sends no more than three requests at a time to one host.
  • Reads the HTML the server sends. It does not run JavaScript, so a page that builds its content in the browser shows little text here. See the FAQ.

What data do you get?

FieldExampleMeaning
url, finalUrlhttps://crawlee.dev/jsThe address checked, and where it ended up after redirects
httpStatus200HTTP status of the final address
redirectCount, redirectChain1How many redirects were followed, and the addresses that redirected
responseTimeMs, sizeBytes51, 62516Time to download the page (from the Apify server) and the size of its HTML
title, titleLengthCrawlee for JavaScriptThe page title and its length in characters
metaDescription, metaDescriptionLengthCrawlee helps you...The meta description and its length
h1Count, h1Texts, h2Count to h6Count1Headings that have text
canonicalUrl, canonicalStatusselfmissing, self, elsewhere or invalid
metaRobots, xRobotsTag, noindex, nofollowfalseWhat the robots meta tag and the X-Robots-Tag header say
indexabletrueLoaded, no noindex, canonical not pointing to another page
lang, hreflangCount, hasViewport, charseten, 2, true, utf-8Language and device settings
hasOgTitle, hasOgDescription, hasOgImage, hasTwitterCardtrueSocial sharing tags
structuredDataTypes["Organization"]The @type values of the JSON-LD on the page
wordCount554Words of visible text in the main content
imageCount, imagesMissingAlt30, 0Images, and images with no alt attribute
internalLinkCount, externalLinkCount, nofollowLinkCount28, 11, 0Links by kind
mixedContentCount0Files loaded over http on an https page
score, errorCount, warningCount, noticeCount100, 0, 0, 0The score and the number of issues of each severity
issues[{ "code": "TITLE_TOO_LONG", ... }]Each issue: code, severity (error, warning or notice) and message
depth, foundOn1, https://crawlee.dev/How many clicks from your start address, and the page that linked here
errornullEmpty when the page was fetched, otherwise a code and a message

How to audit a website

  1. Open the tool and enter the website under Websites or pages, for example https://crawlee.dev.
  2. Set Maximum pages per site. The default is 100. The run stops there, so this is also the most you can be charged for that site.
  3. Press Start.
  4. Open the Output tab. The Pages view shows the score and the main facts of each page, the Issues view shows what was found. The site report is in the key-value store of the run, under SITE_ISSUES.

To check only certain pages, turn off Crawl the site and list the pages. To run an audit every week, use the Schedule option in Apify Console.

How much does it cost to audit a website?

You pay for results, not for time: $10 per 1,000 pages checked ($0.01 a page). Apify subscribers on the Silver plan pay $8.50 and on the Gold plan $7.00 per 1,000 pages. Each run also has a start fee of $0.00005.

Pages checkedCost
10$0.10
100$1.00
1,000$10.00
10,000$100.00

Apify's free plan includes $5 of credit each month, which covers about 500 pages.

Every result in the table is charged, also a page that answered 404 or could not be fetched, because finding those is part of the audit. So is the result for an entry that is not a web address, and for an address you entered that robots.txt forbids. A page that is reached under two addresses (a redirect and its target) is one result. Links to files that are not web pages, and links the site's robots.txt forbids, are not saved and cost nothing. Set Maximum pages per site, or a maximum cost for the run in Apify Console, and the tool stops there and keeps what it has.

How the score works

Each page starts at 100 points. For every issue found, points come off: 20 for an error, 8 for a warning, 3 for a notice. The score does not go below 0. A page that could not be loaded (a fetch failure, or a final HTTP status that is not 2xx) scores 0. No score (null) is given where no page was read: an entry that is not a web address, a file that is not HTML, or an address robots.txt forbids.

IssueSeverityWhen
HTTP_ERRORerrorThe final HTTP status is not 2xx
FETCH_FAILEDerrorNo answer: DNS error, refused connection, timeout, certificate error, more than 10 redirects
TITLE_MISSINGerrorNo title
TITLE_TOO_LONG / TITLE_TOO_SHORTwarning / noticeMore than 60 / fewer than 30 characters
DESCRIPTION_MISSINGwarningNo meta description
DESCRIPTION_TOO_LONG / DESCRIPTION_TOO_SHORTwarning / noticeMore than 160 / fewer than 70 characters
H1_MISSING / H1_MULTIPLEwarningNo H1 with text / more than one
NOINDEXwarningMeta robots or X-Robots-Tag says noindex
NOFOLLOWnoticeMeta robots or X-Robots-Tag says nofollow
CANONICAL_MISSINGnoticeNo canonical address
CANONICAL_ELSEWHERE / CANONICAL_INVALIDwarningThe canonical names another page / cannot be used as an address
LANG_MISSINGnoticeThe html tag has no lang
NO_VIEWPORTwarningNo viewport meta tag
IMAGES_MISSING_ALTwarningAn img has no alt attribute (an empty alt is fine)
THIN_CONTENTwarningFewer than 200 words in the main content
MIXED_CONTENTwarningAn https page loads images, scripts, styles, media or frames over http
JSONLD_INVALIDwarningA JSON-LD block is not valid JSON
OG_MISSING / OG_INCOMPLETEnoticeNo Open Graph tags at all / some of title, description and image missing
REDIRECTEDnoticeThe address redirects
REDIRECT_CHAINwarningTwo or more redirects in a row
REDIRECTED_OFFSITEwarningThe address redirects to a different site (only that page is checked)
SLOW_RESPONSEnoticeThe download took more than 3,000 ms
PAGE_TRUNCATEDnoticeThe page is over 3 MB; only the start was checked
NOT_HTMLwarningAn address you entered returns something that is not an HTML page
ROBOTS_BLOCKED / ROBOTS_UNREACHABLEwarningrobots.txt forbids the page / could not be read, so the page was not fetched

The limits (60, 160, 200 words and so on) are common rules of thumb, not rules of any search engine. Use the score to sort pages, not as a verdict.

Input

The only required field is Websites or pages.

{
"startUrls": [{ "url": "https://crawlee.dev" }],
"crawlSite": true,
"maxPagesPerSite": 100,
"includePatterns": ["/docs/"],
"excludePatterns": ["*/api/*"],
"requestTimeoutSecs": 30
}
FieldWhat it does
startUrlsThe websites to crawl, or the pages to check when crawlSite is off. Several sites in one run are fine.
crawlSiteOn (default): follow links to other pages of the same site. Off: check only the addresses you listed.
maxPagesPerSiteThe most pages checked on each site (default 100, up to 100,000). Your start addresses count.
includePatternsCheck a page found by the crawl only if its address matches one of these.
excludePatternsSkip a page if its address matches one of these.
requestTimeoutSecsHow long to wait for one page (default 30).
userAgentThe name sent with each request. Leave empty to use the tool's own name.

Patterns are plain text that may appear anywhere in the address, with * for any characters. For a regular expression, wrap it in slashes, for example /\/blog\/\d{4}\//. Patterns filter the pages the crawl finds. The addresses you enter yourself are always checked.

What counts as the same site: the same host, with or without a leading www., over http or https. Links to other hosts, such as a blog. subdomain, are counted as external links and not followed. The crawl does not follow links marked rel="nofollow", or the links on a page whose robots meta tag or header says nofollow, and it skips addresses that end in a file type such as .pdf, .jpg or .zip.

Output example

One page of crawlee.dev, checked with Crawl the site off:

{
"url": "https://crawlee.dev/blog",
"finalUrl": "https://crawlee.dev/blog",
"site": "https://crawlee.dev",
"depth": 0,
"foundOn": null,
"httpStatus": 200,
"redirectCount": 0,
"redirectChain": [],
"responseTimeMs": 957,
"sizeBytes": 66715,
"contentType": "text/html",
"title": "Crawlee Blog - learn how to build better scrapers | Crawlee for JavaScript · Build reliable crawlers. Fast.",
"titleLength": 107,
"metaDescription": "Guides and tutorials on using Crawlee, the most reliable open-source web scraping and browser automation library for JavaScript and Node.js developers.",
"metaDescriptionLength": 151,
"h1Count": 0,
"h1Texts": [],
"h2Count": 12,
"h3Count": 3,
"h4Count": 0,
"h5Count": 0,
"h6Count": 0,
"canonicalUrl": "https://crawlee.dev/blog",
"canonicalStatus": "self",
"metaRobots": null,
"xRobotsTag": null,
"noindex": false,
"nofollow": false,
"indexable": true,
"lang": "en",
"hreflangCount": 2,
"hasViewport": true,
"charset": "utf-8",
"hasOgTitle": true,
"hasOgDescription": true,
"hasOgImage": true,
"hasTwitterCard": true,
"structuredDataTypes": [
"Blog"
],
"structuredDataErrors": 0,
"wordCount": 1340,
"imageCount": 28,
"imagesMissingAlt": 0,
"internalLinkCount": 88,
"externalLinkCount": 49,
"nofollowLinkCount": 0,
"mixedContentCount": 0,
"score": 84,
"errorCount": 0,
"warningCount": 2,
"noticeCount": 0,
"issues": [
{
"code": "TITLE_TOO_LONG",
"severity": "warning",
"message": "The title is 107 characters long. Search results usually cut titles after about 60."
},
{
"code": "H1_MISSING",
"severity": "warning",
"message": "The page has no H1 heading."
}
],
"error": null
}

The site report

Findings that need all pages are saved in the key-value store of the run under SITE_ISSUES, as JSON. For each site it holds:

  • duplicateTitles and duplicateDescriptions: groups of pages with the same text (ignoring case), with the count and up to 25 addresses
  • noindexPages: the pages that say noindex, and whether the meta tag or the header says it
  • errorPages: pages that answered with an error status or could not be fetched, and the page that linked to them
  • redirects: addresses that redirect, with the address they lead to
  • blockedByRobots: addresses the site's robots.txt does not allow, which the tool did not fetch
  • lowestScoringPages, issueCounts, averageScore and counts with the true totals

Each list holds at most 1,000 entries. The SUMMARY record of the run has the average score, the number of pages and how often each issue was found.

What can you use it for?

  • SEO audits for clients or your own site: a first pass over every page in minutes, sorted by score.
  • Before and after a redesign or migration: run it on the old and the new site and compare titles, canonicals, noindex and redirects.
  • Finding the pages that need work: missing titles, duplicate descriptions, thin pages, images without alt text.
  • Regular checks: put the tool on a schedule and watch for a noindex that slipped into production or a page that started to return errors.
  • Feeding a report or an AI pipeline: the results are flat JSON with stable field names.

Use it from the API

curl -X POST "https://api.apify.com/v2/acts/cyber1nj3ct0r~on-page-seo-audit/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "startUrls": [{ "url": "https://crawlee.dev" }], "maxPagesPerSite": 50 }'

To read the site report, start the run with the normal run endpoint, then fetch https://api.apify.com/v2/key-value-stores/<defaultKeyValueStoreId>/records/SITE_ISSUES with the store id from the run. The tool also works as a tool for AI agents through the Apify MCP server.

FAQ

Does it run JavaScript?

No. It reads the HTML the server sends, as a search engine's first fetch does. A page that builds its title, headings or text in the browser with JavaScript shows little or nothing here, and a site made only of such pages will give you a thin result. Links that appear only after JavaScript runs are not found either, so use the list mode for those pages.

How fast is it, and how many pages can it check?

About two pages a second on one site, because the tool spaces out its requests (three at a time at most, 300 ms between starts). A site of 1,000 pages takes five to ten minutes, more if the site answers slowly. Several sites in one run are checked at the same time. If the site's robots.txt asks for a Crawl-delay, the tool waits for it, up to 30 seconds between requests. The run has a time limit of one hour by default; when it is reached, the tool stops and keeps what it has.

Why do I not see duplicate titles in the page results?

Duplicates can only be found once all pages are known, so they are in the site report (SITE_ISSUES), not in the single results.

A page appears once although I entered two addresses for it

A page that is reached under two addresses, for example /old that redirects to /new and /new itself, is checked and charged once. The redirect is listed in the redirects of the site report.

A site blocks the tool. What can I do?

The tool identifies itself honestly in its User-Agent and does not try to get round blocks, so it will not pass a firewall, a captcha or a login. If it is your own site, allow the User-Agent in your firewall, or set your own under More options. If the site's robots.txt forbids the tool, those pages are not fetched; they are listed under blockedByRobots. When ten pages in a row fail or are refused (HTTP 403, 429, a server error, or no answer), the tool gives that site up, keeps the results so far and says why under stopped in the summary and the site report. You are charged only for the results that were saved.

Is it allowed?

The tool fetches public pages the way a search engine's crawler does, obeys robots.txt, limits its speed and never logs in. You are responsible for how you use the results, and for having the right to audit a site at the speed you choose. Use it on your own sites and on sites you have permission to test.

Something does not work

Open an issue on the Issues tab with the website you tried and what you expected. Every report is read and answered.