CrawlCheck

Round 2 · tested 2–3 November 2026

Sixty-three faults, ten free tools, one answer key.

In one sentence

Round 2 of CrawlCheck's test of free AI audit tools: a 41-page fake business site with 63 planted faults across robots.txt, server answers per crawler, indexing, structured data, links, on-page basics, JavaScript, sitemaps, machine files and security headers, plus an identical twin with none, and ten free tools graded fault by fault against what the server sends.

Round 1 planted ten faults on one page and counted. Round 2 is the version we would want to read: a 41-page fake business site with 63 planted faults across ten categories, an identical twin with none of them, and every free AI-audit and crawler checker we could run without an account, graded fault by fault against what the server actually sends to each visitor.

This is the second round. Round 1 used ten faults on one page; it now carries a dated correction that this round produced.

Read this first. CrawlCheck publishes this page and built both test sites, so the test is not neutral by construction: it rewards fetching pages as several crawlers, which is how CrawlCheck works. Three things keep it checkable. The sites stay up at lab2.crawlcheck.io and lab2-clean.crawlcheck.io and the answer key is published with this page. Every tool's raw output, the grading rules and each verdict with its quote are published too. CrawlCheck was graded on its first run, by a grader told to give it no benefit of the doubt, and every grade sheet then went through a second, independent verification pass that changed eight verdicts. We fixed two CrawlCheck defects this round exposed; the fixes are described below and do not change its score.

Result

Faults caught, out of 63

A full catch counts 1 and a partial catch 0.5. “Wrong” is a tool telling the user the opposite of the truth about a planted fault; it is worse than silence, so it sits next to the score instead of hidden inside it. “False alarms” are untrue claims on the clean twin, which has none of the 63 faults.

CrawlCheckfirst run, before any fix331 wrong
2 false alarms
aicrawlercheck.comthree free endpoints, graded as one9.5
GEO ToolboxAgent Readiness Scanner + llms.txt Checker7
Hostinger AI Visibility Checkerfree check3.52 wrong
Knowatoa AI Search Consolefree check2.51 wrong
isitagentready.comagent-readiness checker2
Swetrix AI Crawlability Checkerfree check1.5
Google Rich Results Testsingle-purpose1
Schema.org Validatorsingle-purpose1
Writesonic AI Crawl Checkerfree check0.57 wrong

Reach differs: a single-page checker never looked at the 41 subpages. The per-tool sections give each tool's score on the faults it actually looked at, and the table below splits the score by category.

By category

Where each tool looks, and what it finds there

Points caught out of the faults planted in each category. A dash means the tool never fetched anything that holds a fault of that category.

Tool robots.txt7 Server answers per crawler7 Indexing directives7 Structured data7 Links and redirects7 On-page basics7 JavaScript and rendering6 Sitemaps6 Machine files5 Security headers4 Total63
CrawlCheck 4.5 5 5 1 3.5 4 2.5 4 1.5 2 33
aicrawlercheck.com 4 2.5 1 1 0 1 0 0 0 0 9.5
GEO Toolbox 1 2.5 1 0.5 0 0 0 0 2 0 7
Hostinger AI Visibility Checker 1.5 0 0 1 0 0 0 – 1 0 3.5
Knowatoa AI Search Console – 2.5 0 0 0 0 0 – – 0 2.5
isitagentready.com 2 0 0 0 0 0 0 0 – 0 2
Swetrix AI Crawlability Checker 1.5 0 0 0 0 0 0 – 0 0 1.5
Google Rich Results Test 0 0 0 1 0 0 0 – – 0 1
Schema.org Validator – 0 0 1 0 0 0 – – 0 1
Writesonic AI Crawl Checker 0 0 0 0.5 0 0 0 0 0 0 0.5

Fault by fault

All 63, every tool

Caught Partly Missed✕ Said the opposite· Never looked there
FaultCrawl­Checkaicrawler­checkGEO ToolboxHostingerKnowatoaisitagent­readySwetrixGoogle RRTSchema.orgWritesonic
robots.txt
R1 ClaudeBot's robots group holds only a Crawl-delay, so its access depends on the parser: Google's reference parser merges it into the next group and blocks it site-wide (line 11); others read an empty group and allow everything RFC 9309 s2.2.1; google/robotstxt Caught Caught Caught Caught Never looked there Caught Caught Missed Never looked there Missed
R2 /assets/ (the stylesheet and the script every page needs) is disallowed for all crawlers Google: do not block resources needed to render Caught Partly Missed Missed Never looked there Partly Missed Missed Never looked there Missed
R3 Googlebot-Image is disallowed from the whole site Google image crawler docs Caught Caught Missed Missed Never looked there Missed Missed Missed Never looked there Missed
R4 Storebot-Google is disallowed from the whole site Google shopping crawler docs Caught Caught Missed Missed Never looked there Missed Missed Missed Never looked there Missed
R5 A group for "Perplexity-Bot" (not PerplexityBot) never applies to Perplexity's crawler Perplexity crawler docs Missed Missed Missed Missed Never looked there Missed Missed Missed Never looked there Missed
R6 The Sitemap line is a relative path; it must be an absolute URL sitemaps.org / RFC 9309 Partly Partly Missed Partly Never looked there Partly Partly Missed Never looked there Missed
R7 A Noindex: line in robots.txt, which Google has ignored since 2019 Google Search Central Missed Missed Missed Missed Never looked there Missed Missed Missed Never looked there Missed
Server answers per crawler
S1 PerplexityBot is answered with HTTP 403 on every page Perplexity crawler docs Caught Caught Caught Missed Caught Missed Missed Missed Missed Said the opposite
S2 Applebot gets HTTP 200 with a 'Just a moment...' challenge page instead of content Apple crawler docs Caught Missed Missed Missed Said the opposite Missed Missed Missed Missed Said the opposite
S3 OAI-SearchBot gets pages with the services, areas and prices sections removed OpenAI crawler docs Partly Missed Missed Missed Missed Missed Missed Missed Missed Missed
S4 ClaudeBot is redirected (302) from every page to /unavailable Anthropic crawler docs Caught Partly Partly Said the opposite Partly Missed Missed Missed Missed Said the opposite
S5 GPTBot gets HTTP 429 on every request OpenAI crawler docs Caught Caught Caught Missed Caught Missed Missed Missed Missed Said the opposite
S6 Googlebot user agents get an extra keyword block no other visitor sees (cloaking) Google spam policies Partly Missed Missed Missed Missed Missed Missed Missed Missed Said the opposite
S7 Bingbot gets HTTP 503 on /pricing Bing Webmaster Guidelines Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Missed
Indexing directives
I1 /services/gutter-guards carries meta robots noindex Google robots meta docs Caught Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
I2 /pricing is sent with an X-Robots-Tag: noindex header Google robots meta docs Caught Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Missed
I3 /areas/riverbend has a canonical pointing to a URL that returns 404 Google canonical docs Partly Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
I4 /services/downspout-repair has a canonical pointing to a different service page Google canonical docs Caught Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
I5 The homepage carries meta robots nosnippet Google robots meta docs Caught Caught Caught Missed Missed Missed Missed Missed Missed Missed
I6 /faq has two conflicting robots meta tags (index,follow and noindex) Google robots meta docs Partly Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
I7 /about has a canonical to the http:// version of itself Google canonical docs Said the opposite Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
Structured data
D1 The homepage JSON-LD does not parse (trailing comma) JSON / schema.org Caught Caught Partly Caught Missed Missed Missed Caught Caught Partly
D2 /contact LocalBusiness has no address Google LocalBusiness structured data Missed Never looked there Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
D3 /contact schema telephone differs from the phone number printed on the page Google structured data guidelines Missed Never looked there Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
D4 /reviews marks up self-serving AggregateRating on the business itself Google review snippet guidelines Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Missed
D5 /about has two Organization nodes with different names schema.org / Google Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
D6 sameAs on /about points to a profile URL that returns 404 schema.org sameAs Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
D7 Blog posts mark up Article without datePublished or author Google Article structured data Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
Links and redirects
L1 The homepage links to /services/roof-repair, which returns 404 Google link best practices Partly Missed Missed Missed Missed Missed Missed Missed Missed Missed
L2 /old-gutter-page redirects three times before reaching a page Google redirect docs Partly Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
L3 /promo-a and /promo-b redirect to each other (loop), linked from a blog post Google redirect docs Caught Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
L4 /specials returns 200 with 'Page not found' text (soft 404), linked from the footer Google soft 404 docs Partly Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
L5 /areas/lakeside is in the sitemap but linked from no page (orphan) Google link best practices Caught Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
L6 /faq and /faq/ both return 200 with no redirect between them Google duplicate URL docs Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
L7 The about page links internally to an http:// URL Google HTTPS docs Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
On-page basics
P1 /careers has no <title> Google title link docs Caught Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
P2 /areas/millbrook and /areas/cedar-park have the same title Google title link docs Caught Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
P3 /services/fascia-repair has no meta description Google snippet docs Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
P4 /services/ice-dam-prevention has two <h1> elements Accessibility / heading structure Caught Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
P5 The three homepage images have no alt text WCAG 1.1.1 / Google image SEO Caught Caught Missed Missed Missed Missed Missed Missed Missed Missed
P6 /privacy has no lang attribute WCAG 3.1.1 Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
P7 /terms has no viewport meta tag Google mobile-friendly docs Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
JavaScript and rendering
J1 /pricing prices exist only after JavaScript runs (the HTML says 'Loading prices...') Google JavaScript SEO basics Partly Never looked there Never looked there Said the opposite Never looked there Never looked there Never looked there Never looked there Never looked there Said the opposite
J2 The homepage links to the area pages only through JavaScript click handlers, not <a href> Google link best practices Partly Missed Missed Missed Missed Missed Missed Missed Missed Missed
J3 /reviews content is rendered entirely by JavaScript into an empty container Google JavaScript SEO basics Caught Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Said the opposite
J4 /faq answers are fetched from /api/faq.json after load and are not in the HTML Google JavaScript SEO basics Partly Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
J5 /gallery photos are CSS background images with no <img>, so they cannot be indexed Google image SEO docs Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
J6 /careers content is inside an iframe from /embed/careers Google iframe guidance Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
Sitemaps
X1 The sitemap index lists /sitemap-blog.xml, which returns 404 sitemaps.org Missed Missed Missed Never looked there Never looked there Missed Never looked there Never looked there Never looked there Missed
X2 The sitemap lists a noindex URL (/services/gutter-guards) Google sitemap docs Caught Never looked there Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
X3 The sitemap lists a redirecting URL (/old-gutter-page) Google sitemap docs Caught Never looked there Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
X4 The sitemap lists a URL that returns 404 (/services/roof-repair) Google sitemap docs Caught Never looked there Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
X5 Two lastmod values are not valid W3C dates sitemaps.org Partly Never looked there Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
X6 The sitemap lists a URL on another host sitemaps.org Partly Never looked there Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
Machine files
M1 llms.txt does not start with an H1 title llmstxt.org Caught Missed Caught Caught Never looked there Never looked there Missed Never looked there Never looked there Missed
M2 llms.txt links to two pages that return 404 llmstxt.org Missed Missed Caught Missed Never looked there Never looked there Missed Never looked there Never looked there Missed
M3 security.txt Expires is in the past (2025-01-01) RFC 9116 Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
M4 security.txt has no Contact field RFC 9116 Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
M5 security.txt is served as text/html RFC 9116 Partly Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
Security headers
T1 No Strict-Transport-Security header on any page RFC 6797 Caught Missed Missed Missed Missed Missed Missed Missed Missed Missed
T2 /about loads an image over http:// (mixed content) MDN mixed content Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
T3 A blog post links to a staging host (staging.lab2.crawlcheck.io) OWASP information exposure Missed Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there Never looked there
T4 The homepage sets a session cookie without Secure or HttpOnly OWASP session management Caught Missed Missed Missed Missed Missed Missed Missed Missed Missed

Hover or focus a cell for the tool's own words. The full quote and its location in the raw output are in each tool's grade sheet.

Tool by tool

How each one checks, what it caught, and where it slipped

CrawlCheck 33 of 63 · 33 of the 63 it looked at

How it checks. Fetches the homepage as 13 named crawlers plus browser and mobile controls and compares what each one is served; applies robots.txt per crawler; reads robots.txt, the sitemap tree, llms.txt and security.txt; a separate free 41-page crawl reads every page's title, directives, canonical, links and redirects.

What it fetched from the lab (from the lab's request log): 541 requests, 103 distinct paths, sent as 53 user agents.

Caught (26). R1 ClaudeBot's robots group holds only a Crawl-delay, so its access depends on the parser: Google's reference parser merges it into the next group and blocks it site-wide (line 11); others read an empty group and allow everything; R2 /assets/ (the stylesheet and the script every page needs) is disallowed for all crawlers; R3 Googlebot-Image is disallowed from the whole site; R4 Storebot-Google is disallowed from the whole site; S1 PerplexityBot is answered with HTTP 403 on every page; S2 Applebot gets HTTP 200 with a 'Just a moment...' challenge page instead of content; S4 ClaudeBot is redirected (302) from every page to /unavailable; S5 GPTBot gets HTTP 429 on every request; I1 /services/gutter-guards carries meta robots noindex; I2 /pricing is sent with an X-Robots-Tag: noindex header; I4 /services/downspout-repair has a canonical pointing to a different service page; I5 The homepage carries meta robots nosnippet; J3 /reviews content is rendered entirely by JavaScript into an empty container; D1 The homepage JSON-LD does not parse (trailing comma); M1 llms.txt does not start with an H1 title; X2 The sitemap lists a noindex URL (/services/gutter-guards); X3 The sitemap lists a redirecting URL (/old-gutter-page); X4 The sitemap lists a URL that returns 404 (/services/roof-repair); L3 /promo-a and /promo-b redirect to each other (loop), linked from a blog post; L5 /areas/lakeside is in the sitemap but linked from no page (orphan); P1 /careers has no <title>; P2 /areas/millbrook and /areas/cedar-park have the same title; P4 /services/ice-dam-prevention has two <h1> elements; P5 The three homepage images have no alt text; T1 No Strict-Transport-Security header on any page; T4 The homepage sets a session cookie without Secure or HttpOnly

Partly (14). R6 The Sitemap line is a relative path; it must be an absolute URL (robots.txt names a sitemap | 1 Sitemap: line(s) | at least one | ✓ Passed); S3 OAI-SearchBot gets pages with the services, areas and prices sections removed (OAI-SearchBot | different | words (198 → 164) | a template or a cache variant, not a different page); S6 Googlebot user agents get an extra keyword block no other visitor sees (cloaking) (Googlebot | 200 | 220 | 0.91 | different body text); I3 /areas/riverbend has a canonical pointing to a URL that returns 404 (/areas/riverbend canonical elsewhere · listed in the sitemap); I6 /faq has two conflicting robots meta tags (index,follow and noindex) (Gutter FAQ | Northfield Gutter Co. | 200 | 1 | 65 | ... | self | noindex); J1 /pricing prices exist only after JavaScript runs (the HTML says 'Loading prices...') (/pricing | 106 → 132 | 20% | 14 → 14 | 0 → 0 | —); J2 The homepage links to the area pages only through JavaScript click handlers, not <a href> (7 elements with onclick and no tabindex or role (span.lnk, span.lnk, span.lnk)); J4 /faq answers are fetched from /api/faq.json after load and are not in the HTML (/faq | 65 → 94 | 31% | 14 → 14 | 0 → 0 | —); M5 security.txt is served as text/html (security.txt | ... | absent (200)); X5 Two lastmod values are not valid W3C dates (Sitemap URLs with a change date | ... | 36 of 38); X6 The sitemap lists a URL on another host (/services status 530 · listed in the sitemap); L1 The homepage links to /services/roof-repair, which returns 404 (/services/roof-repair Not found | 404 | 1 | 4 | ... | 1 | 0); L2 /old-gutter-page redirects three times before reaching a page (/old-gutter-page 2 hops: 301 permanent → 301 permanent → https://lab2.crawlcheck.io/services/ (200)); L4 /specials returns 200 with 'Page not found' text (soft 404), linked from the footer (/specials Page not found | 200 | 1 link-found | 13)

Where it said the opposite of the truth:

  • I7 /about has a canonical to the http:// version of itself: “About Northfield Gutter Co. | 200 | 1 | 171 | 36.3% | 2 | none | 1 | self”

Missed (22) on pages or files it did read; never looked where the other 0 live.

On the clean twin it said something untrue:

  • Business phone on the page: none found (one defect, three statements: "none found ✗ Failed", "structured data only, not shown to readers", "Phone numbers written on the page | 0") — The number is printed in the page body and footer. Cause: the page-side phone check read only tel: links. Fixed after grading (2026-11-04); the first run is what is graded.
  • The sitemap lists URLs but carries no lastmod dates / Add <lastmod> dates — Every entry has a lastmod. The detail line is true (all 35 share one build-stamp date) but the explanation and fix shown were the no-lastmod text. Fixed after grading (2026-11-04).

Evidence quality 2 of 3. Free output names agents, URLs and observed values: per-identity status, words, bytes and sha256; machine-file transcript with status, content-type and bytes; redirect hops; JS raw-vs-rendered counts; top finding with rule link and fetch manifest. Not 3: most finding evidence is locked, robots verdicts carry no line numbers, and several rows contradict the report's own tables (ClaudeBot redirect, Googlebot split, internal links resolve, sitemap named). One redirect status (/services/ 200) was never observed.

aicrawlercheck.com 9.5 of 63 · 9.5 of the 23 it looked at

How it checks. Evaluates robots.txt for 265 bot tokens, then fetches the homepage as 20 crawler user agents through six gates (robots, directives, status, redirects, interstitial, text without JavaScript); a GEO endpoint reads the page and llms.txt.

What it fetched from the lab (from the lab's request log): 42 requests, 10 distinct paths, sent as 22 user agents.

Caught (8). R1 ClaudeBot's robots group holds only a Crawl-delay, so its access depends on the parser: Google's reference parser merges it into the next group and blocks it site-wide (line 11); others read an empty group and allow everything; R3 Googlebot-Image is disallowed from the whole site; R4 Storebot-Google is disallowed from the whole site; S1 PerplexityBot is answered with HTTP 403 on every page; S5 GPTBot gets HTTP 429 on every request; I5 The homepage carries meta robots nosnippet; D1 The homepage JSON-LD does not parse (trailing comma); P5 The three homepage images have no alt text

Partly (3). R2 /assets/ (the stylesheet and the script every page needs) is disallowed for all crawlers (Full content access; 2 path rules (/assets/, /quote)); R6 The Sitemap line is a relative path; it must be an absolute URL (Sitemap index with 2 child sitemaps at https://lab2.crawlcheck.io/sitemap.xml. Not declared in robots.txt.); S4 ClaudeBot is redirected (302) from every page to /unavailable (1 redirect, ending at https://lab2.crawlcheck.io/unavailable)

Missed (12) on pages or files it did read; never looked where the other 40 live.

On the clean twin: no untrue claims. Advisories only: llms-full.txt missing; no named training-bot groups; thin content; no question headings.

Evidence quality 3 of 3. Names the agent, the observed status (403/429), the robots line number and group, character counts per agent, and states its own method ("Tested with the crawler user agent from our server, not the crawler IP range").

Good at things the key does not reward. Robots verdicts for 265 user-agent tokens across 8 categories (acc_main_lab2.json totalBots 265). Live fetch of the homepage as 20 crawler user agents with six gates each (robots, directive, status, redirects, interstitial, JS) (acc_diag_lab2.json results). Honest caveat on fake-bot protection: "Our request does not come from Perplexity AI's network, so we cannot tell which." (diag results[PerplexityBot].evidence).

GEO Toolbox 7 of 63 · 7 of the 30 it looked at

How it checks. Fetches the homepage as six AI crawlers and in a browser, reads robots.txt for 34 bots and the sitemap as Googlebot; the llms.txt checker parses the file and follows every link in it.

What it fetched from the lab (from the lab's request log): 34 requests, 21 distinct paths, sent as 10 user agents.

Caught (6). R1 ClaudeBot's robots group holds only a Crawl-delay, so its access depends on the parser: Google's reference parser merges it into the next group and blocks it site-wide (line 11); others read an empty group and allow everything; S1 PerplexityBot is answered with HTTP 403 on every page; S5 GPTBot gets HTTP 429 on every request; I5 The homepage carries meta robots nosnippet; M1 llms.txt does not start with an H1 title; M2 llms.txt links to two pages that return 404

Partly (2). S4 ClaudeBot is redirected (302) from every page to /unavailable (ClaudeBot (200 but only 4 words)); D1 The homepage JSON-LD does not parse (trailing comma) (FIX Schema.org structured data 8 pts — No JSON-LD schema.org markup found.)

Missed (22) on pages or files it did read; never looked where the other 33 live.

On the clean twin: no untrue claims. Advisories only: No Last-Modified on llms.txt; llms.txt links to HTML not .md; no llms-full.txt; few answer-friendly structures.

Evidence quality 3 of 3. Cites robots line numbers (line 11, llms line 1), observed status codes per bot UA (429, 403) and word counts from live probes it actually made under each UA, and counts resolving llms.txt links (2/4, 11/11, both correct per the log).

Good at things the key does not reward. Separates robots permission from server behaviour: "robots does not disallow it (possible UA filtering)" — the right diagnosis for UA-based blocking. Link-checks every llms.txt link: "2/4 links resolve, 2 dead" on lab2 and "11/11 links resolve" on clean, both exact per the log. Accurately labels optional items as optional: "WARNING No summary blockquote — Optional per spec." (true on lab2, not a key fault).

Hostinger AI Visibility Checker 3.5 of 63 · 3.5 of the 23 it looked at

How it checks. About 26 weighted checks in seven groups: crawl permission, findability, readability without JavaScript, structured data, contact and price legibility, llms.txt, agent protocols. Fetches the homepage with its own agent, a headless browser and once as ClaudeBot.

What it fetched from the lab (from the lab's request log): 19 requests, 14 distinct paths, sent as 4 user agents.

Caught (3). R1 ClaudeBot's robots group holds only a Crawl-delay, so its access depends on the parser: Google's reference parser merges it into the next group and blocks it site-wide (line 11); others read an empty group and allow everything; D1 The homepage JSON-LD does not parse (trailing comma); M1 llms.txt does not start with an H1 title

Partly (1). R6 The Sitemap line is a relative path; it must be an absolute URL (Declared: /sitemap.xml. ... The sitemap probe could not be completed, so this could not be assessed.)

Where it said the opposite of the truth:

  • S4 ClaudeBot is redirected (302) from every page to /unavailable: “Not blocked by bot detection 6/6 pts”
  • J1 /pricing prices exist only after JavaScript runs (the HTML says 'Loading prices...'): “Prices are reachable without JavaScript or login 4/4 ... A pricing page is linked from the homepage.”

Missed (17) on pages or files it did read; never looked where the other 40 live.

On the clean twin: no untrue claims. Advisories only: no Content-Signal; no markdown negotiation; no Link headers; no WebMCP.

Evidence quality 1 of 3. Findings are named ("Blocked by robots.txt: ClaudeBot.", missing "# " heading, no valid JSON-LD) without the rule, line, status code or raw response; observed values appear only on passing or advisory rows (byte counts, Content-Type for Accept: text/markdown).

Good at things the key does not reward. Actually tests markdown negotiation and reports the observed response: "Homepage returned 'text/html; charset=utf-8' for Accept: text/markdown." Probes a random URL for a real 404 and checks for an MCP server card. Measures readable text in raw HTML: "Raw HTML contains 1830 characters of readable text."

Knowatoa AI Search Console 2.5 of 63 · 2.5 of the 13 it looked at

How it checks. Requests the homepage once as each of 25 AI user agents and reports the HTTP status for each.

What it fetched from the lab (from the lab's request log): 25 requests, 1 distinct paths, sent as 24 user agents.

Caught (2). S1 PerplexityBot is answered with HTTP 403 on every page; S5 GPTBot gets HTTP 429 on every request

Partly (1). S4 ClaudeBot is redirected (302) from every page to /unavailable ({"status":"success","code":"302","message":"Found"})

Where it said the opposite of the truth:

  • S2 Applebot gets HTTP 200 with a 'Just a moment...' challenge page instead of content: “{"status":"success","code":"200","message":"OK"}”

Missed (9) on pages or files it did read; never looked where the other 50 live.

On the clean twin: no untrue claims.

Evidence quality 2 of 3. Names each agent with the HTTP status code it got; no request detail, no redirect target, no explanation or standard.

Good at things the key does not reward. Live homepage fetch with 25 real crawler user-agent strings, including legacy tokens (anthropic-ai, claude-web), Diffbot, Timpibot, omgili, LinkedInBot and AI2Bot (request log 1922266-1927852). Fetches from Amazon AWS rather than a single CDN, one agent at a time. Clean twin: zero false alarms.

isitagentready.com 2 of 63 · 2 of the 21 it looked at

How it checks. Probes 20+ agent-protocol endpoints (MCP server card, A2A card, OAuth discovery, API catalog, agent skills, payments), DNS records, markdown negotiation, robots.txt and the sitemap index; renders the homepage headless to detect WebMCP.

What it fetched from the lab (from the lab's request log): 33 requests, 27 distinct paths, sent as 2 user agents.

Caught (1). R1 ClaudeBot's robots group holds only a Crawl-delay, so its access depends on the parser: Google's reference parser merges it into the next group and blocks it site-wide (line 11); others read an empty group and allow everything

Partly (2). R2 /assets/ (the stylesheet and the script every page needs) is disallowed for all crawlers ({"directive": "disallow", "pattern": "/assets/"}); R6 The Sitemap line is a relative path; it must be an absolute URL (No Sitemap directives found in robots.txt)

Missed (18) on pages or files it did read; never looked where the other 42 live.

On the clean twin: no untrue claims. Advisories only: no Link headers; no DNS-AID records; no markdown negotiation; no Content Signals.

Evidence quality 3 of 3. Every check carries the request it made, the response status, selected headers and a body preview (e.g. the full robots.txt), so findings are reproducible; but it catches almost none of the key.

Good at things the key does not reward. Probes 20+ agent-protocol endpoints (MCP server card, A2A agent card, OAuth discovery, api-catalog, agent skills, UCP/ACP, x402) with the request and status shown for each. DNS-AID lookups over DoH with the queries listed (checks.discoverability.dnsAid.details.queriesAttempted). Markdown content negotiation test (Accept: text/markdown).

Swetrix AI Crawlability Checker 1.5 of 63 · 1.5 of the 22 it looked at

How it checks. Reads robots.txt for 8 AI crawlers and shows the matched rule, checks that llms.txt and a sitemap exist, counts structured-data blocks, reads title, description and canonical.

What it fetched from the lab (from the lab's request log): 4 requests, 4 distinct paths, sent as 1 user agents.

Caught (1). R1 ClaudeBot's robots group holds only a Crawl-delay, so its access depends on the parser: Google's reference parser merges it into the next group and blocks it site-wide (line 11); others read an empty group and allow everything

Partly (1). R6 The Sitemap line is a relative path; it must be an absolute URL (Sitemap Failed /sitemap.xml)

Missed (20) on pages or files it did read; never looked where the other 41 live.

On the clean twin: no untrue claims. Advisories only: no llms-full.txt.

Evidence quality 2 of 3. Names the agent and the matched robots rule ("ClaudeBot | No | disallow: /") and status codes for llms files, but no line numbers, raw responses or live crawler-UA requests.

Good at things the key does not reward. Shows the matched rule per crawler, so a reader can see why each verdict was reached. Reports title, description and canonical of the homepage. Clean twin: zero false alarms; all eight crawlers "allow: /" correctly.

Google Rich Results Test 1 of 63 · 1 of the 20 it looked at

How it checks. Fetches one URL as Google-InspectionTool, renders it, and tests its structured data for rich-result eligibility.

What it fetched from the lab (from the lab's request log): 6 requests, 6 distinct paths, sent as 2 user agents.

Caught (1). D1 The homepage JSON-LD does not parse (trailing comma)

Missed (19) on pages or files it did read; never looked where the other 43 live.

On the clean twin: no untrue claims. Advisories only: LocalBusiness non-critical issues.

Evidence quality 2 of 3. Names the issue at the tested URL with the parser's observed error message; the capture holds no line number or raw response (the tool UI highlights the line, but that is not in the capture).

Good at things the key does not reward. Renders the page with Google's own crawler, so its structured-data verdict is what Google itself sees. On lab2 Google-InspectionTool did not fetch /assets/site.css or /assets/site.js (it did on clean): it honoured R2's Disallow: /assets/. The tool's page-resources view probably reports this, but it is not in the capture, so R2 is graded missed. Clean twin: zero false alarms.

Schema.org Validator 1 of 63 · 1 of the 13 it looked at

How it checks. Fetches one page with a rendering agent and parses its structured data.

What it fetched from the lab (from the lab's request log): 7 requests, 7 distinct paths, sent as 2 user agents.

Caught (1). D1 The homepage JSON-LD does not parse (trailing comma)

Missed (12) on pages or files it did read; never looked where the other 50 live.

On the clean twin: no untrue claims.

Evidence quality 3 of 3. Names the exact error class, gives the character offset, and returns the fetched HTML so the error can be located and reproduced.

Good at things the key does not reward. Returns the rendered HTML it validated (isRendered: true) with character offsets for every node and error. Fetches page subresources with a rendering agent, so script-injected JSON-LD would be seen.

Writesonic AI Crawl Checker 0.5 of 63 · 0.5 of the 28 it looked at

How it checks. Fetches six pages as its own bot and the homepage in a browser, compares word counts, and prints a 16-bot table of robots.txt verdicts with a “can read” column.

What it fetched from the lab (from the lab's request log): 11 requests, 10 distinct paths, sent as 3 user agents.

Caught (0). Nothing.

Partly (1). D1 The homepage JSON-LD does not parse (trailing comma) ("label": "Structured data (JSON-LD)", "value": "none", "status": "fail")

Where it said the opposite of the truth:

  • S1 PerplexityBot is answered with HTTP 403 on every page: “"name": "PerplexityBot", ... "robots": "allow", "canRead": "yes"”
  • S2 Applebot gets HTTP 200 with a 'Just a moment...' challenge page instead of content: “"name": "Applebot", ... "robots": "allow", "canRead": "yes"”
  • S4 ClaudeBot is redirected (302) from every page to /unavailable: “"name": "ClaudeBot", ... "robots": "allow", "canRead": "yes"”
  • S5 GPTBot gets HTTP 429 on every request: “"name": "GPTBot", ... "robots": "allow", "canRead": "yes"”
  • S6 Googlebot user agents get an extra keyword block no other visitor sees (cloaking): “"dynamic": {"checked": true, "cloaking": false, "botWords": 169, "browserWords": 169}”
  • J1 /pricing prices exist only after JavaScript runs (the HTML says 'Loading prices...'): “"url": "https://lab2.crawlcheck.io/pricing", "verdict": "readable", ... "mode": "Server-rendered"”
  • J3 /reviews content is rendered entirely by JavaScript into an empty container: “"url": "https://lab2.crawlcheck.io/reviews", "verdict": "readable", "words": 39, ... "mode": "Server-rendered"”

Missed (20) on pages or files it did read; never looked where the other 35 live.

On the clean twin: no untrue claims. Advisories only: thin homepage; schema rated warn with no reason given; short page word count.

Evidence quality 1 of 3. Gives labels and counts (words, links, "canRead") with no status codes, agents actually used or rules; the per-bot verdicts are not backed by any fetch as those bots.

Good at things the key does not reward. Crawls 6 pages (homepage plus 5 linked pages) and reports words/links/render mode per page. Raw-HTML vs rendered word comparison and a bot-vs-browser cloaking check (against its own UA). Detects llms.txt and robots.txt presence.

What we got wrong

Our own misses, our two false alarms, and a Round 1 correction

Round 1 correction. In Round 1 we said aicrawlercheck.com and Swetrix “quoted another group's line” when they cited the GPTBot group's Allow line for ClaudeBot. We built Google's reference robots.txt parser (github.com/google/robotstxt) and ran it on that file: a User-agent line followed only by Crawl-delay joins the next group, so line 9 is exactly the line that applies. Both tools were right and we were wrong. The Round 1 page now says so, dated. The same rule decides fault R1 here: under the reference parser ClaudeBot is blocked site-wide by a rule written for Google's image crawler (line 11), while Python's and npm's parsers say it is allowed. We graded “blocked, line 11” as a catch and “allowed” as a miss, not as wrong.

CrawlCheck's first run: 33 of 63, 1 wrong. It fetched every page and file that holds a fault, so every miss is a miss, not a blind spot. The ones that matter most:

  • R5. A robots group for “Perplexity-Bot” (not PerplexityBot) applies to nobody. Never mentioned.
  • S7. Bingbot gets a 503 on /pricing. CrawlCheck probed Bingbot on the homepage only.
  • D2–D7. Six structured-data faults below the homepage (a LocalBusiness with no address, a schema phone that differs from the printed one, a self-serving AggregateRating, two Organization nodes with different names, a dead sameAs, Articles without dates or authors). The crawl read the pages and reported none of them.
  • M3, M4. security.txt was fetched (200) and reported as “absent”, so its expired date and missing Contact went unread.
  • X1. The sitemap index names /sitemap-blog.xml, which returned 404 on all five fetches. Not reported.
  • T2, T3. A mixed-content image and a link to a staging host. Not reported.
  • I7, graded wrong. The crawl table shows /about's canonical as “self”; it points at the http:// version of the page.

Two false alarms on the clean twin. First, “Business phone on the page: none found”, with the schema number described as “structured data only, not shown to readers”. The number is printed in the body and the footer; the check read only tel: links. Any customer site that prints its number without a tel: link got the same false finding. Second, a sitemap finding whose detail line was true (all 35 entries carry one build-stamp date) but whose explanation and fix were the “no lastmod dates at all” text. Both were fixed on 4 November, after grading; a re-scan of the clean twin now reads the printed number and the /contact page's schema-vs-printed phone mismatch (D3) becomes a reported conflict. The scores above are the first run and do not include this.

What a free user does not see. On the faulty site the free homepage report lists five findings by title; detail, evidence and fix for four of them are locked behind a licence, as are 35 fix-impact rows and 11 sections. The grading counted locked findings by their title only, and no verdict depended on locked content. We say this because a comparison that scores the paid view against other tools' free views would not be a fair one.

Reach

What each tool actually fetched

From the test site's own request log, matched to each run by time and user agent. This is why single-page tools score low on 63 faults and why the “of the faults it looked at” figure is shown as well.

ToolRequestsPathsCrawler identities sentFaults it could have seen
CrawlCheck541103PerplexityBot, GPTBot, Mozilla/5.0 Chrome/130, Applebot, OAI-SearchBot, ClaudeBot, Googlebot, bingbot, CrawlCheck/1.0; +https://crawlcheck.io/bot, Claude-SearchBot, Amazonbot, Bytespider, meta-externalagent, CCBot…63 of 63
aicrawlercheck.com4210AICrawlerCheck, AICrawlerCheck-GEOAudit, AICrawlerCheck-Diagnostic, GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-SearchBot, Claude-User, PerplexityBot, Perplexity-User, bingbot, Googlebot, meta-externalagent…23 of 63
GEO Toolbox3421OAI-SearchBot, PerplexityBot, Googlebot, GPTBot, ClaudeBot, CCBot, ChatGPT-User, Perplexity-User, AI-Readiness-Probe30 of 63
Hostinger AI Visibility Checker1914Hostinger-Web2Agent, ClaudeBot23 of 63
Knowatoa AI Search Console251AI2Bot, Amazonbot, anthropic-ai, ClaudeBot, claude-web, Applebot, BingBot, Bytespider, CCBot, ChatGPT-User, GPTBot, OAI-SearchBot, cohere-ai, Diffbot…13 of 63
isitagentready.com3327AgentReadinessScanner21 of 63
Swetrix AI Crawlability Checker44Swetrix-Free-SEO-Tools22 of 63
Google Rich Results Test66Googlebot20 of 63
Schema.org Validator77Google-Structured-Data-Testing-Tool13 of 63
Writesonic AI Crawl Checker1110WritesonicBot28 of 63

Not run this round

Two tools hit their daily cap; the paid tools are unchanged from Round 1

SEOptimer and Seobility both refused a new report on 3 November (“maximum number of reports in a day”, “no more checks available today”), and again after midnight on 4 November. SEOptimer did show its overview for the faulty site (B overall; A- on-page, A- links, F usability, A performance, A+ social, 11 recommendations) with the report itself blurred; section grades name no faults, so it is recorded but not graded. Both will be run again and added here with the date. The tools that need an account (Screaming Frog, Ahrefs, Semrush, Moz, Cloudflare AI Crawl Control, and the AI-visibility trackers) are not ranked; Round 1 lists what each documents.

Method

How to check our work

The faulty site is https://lab2.crawlcheck.io; its twin without faults is https://lab2-clean.crawlcheck.io. Both say on every page that the business does not exist. The answer key is /answer-key.json Each tool was run once with default settings: the API-driven ones from a container on 3 November between 10:57 and 11:02 PM Mountain Time, the browser-only ones from a desktop Chrome between 11:03 and 11:23 PM; CrawlCheck's runs are its first scans of the site on the evening of 2 November, before any change was made to it.

Grading. Caught: the output names the fault or its direct symptom at the right place, so an owner reading it would find and fix it. Partly: the symptom is visible but misdescribed or unlocated (“no JSON-LD” for JSON-LD that exists but does not parse; a points deduction with no statement of what is wrong). Wrong: the output states the opposite of the truth for that fault, as fact. Never looked there: the fault lives on a page or file the tool never fetched, from its output and the request log; it still scores zero. A statement that only reflects robots.txt (“allowed”) is not wrong about a server-side block unless the tool claims the crawler can actually read the page. Evidence quality, 0–3: a score only; names the issue; names it with the URL or agent and the observed value; adds the standard or a reproducible check. The complete grading rules, the fault list, every verdict with its quote (each tool's grade sheet), the verification pass and the request-log summaries are published with the raw outputs: all evidence.

If a tool has changed since, or we misread a result, send it to our corrections page and we will re-run it and date the change.

Questions about this page

QWhich free AI audit tool caught the most faults?
CrawlCheck, which publishes the test, caught 33 of 63 on its first run. Among the others, aicrawlercheck.com caught 9.5 and GEO Toolbox 7. Every verdict and raw output is published so the result can be checked.
QDid any tool say the opposite of the truth?
Yes. Writesonic's checker said four crawlers could read the page when the server refused all four; Hostinger and Knowatoa each had wrong verdicts too. They are listed with the tool's own words.