# Sitebulb Crawler Test Site > Deterministic fixture routes for exercising web crawlers. Machine-readable > expectations live in the canonical manifest, never in page content. ## Manifests - [Canonical manifest](https://crawler-test-site.uk.sitebulb.com/manifest.json): every fixture with full expectations - [Safe manifest](https://crawler-test-site.uk.sitebulb.com/manifest.safe.json): fixtures safe for broad crawling - [Risky manifest](https://crawler-test-site.uk.sitebulb.com/manifest.risky.json): direct-entry-only and risky fixtures - [Default sitemap](https://crawler-test-site.uk.sitebulb.com/sitemap.xml): safe crawl entry points ## accessibility - [Body hidden from assistive technology](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/aria-hidden-body): A fully compliant scaffold whose body carries aria-hidden, suppressing the whole accessibility tree. - [ARIA accessible name violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/aria-names): Eight unnamed ARIA widgets, each carrying its required state attributes so only the name rule fires. - [ARIA structure and hidden content violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/aria-structure): Broken parent and child role requirements, nested interactives, unreachable scroll regions, and hidden focusable content. - [ARIA validity violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/aria-validity): Seven elements carrying disallowed, missing, misspelled, invalid, or conflicting ARIA attributes and roles. - [Colour contrast violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/color-contrast): Text at roughly 2.85:1 contrast, AA-passing but AAA-failing text, and a link distinguished by colour alone. - [Invalid document language](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/doc-lang-invalid): A fully compliant scaffold whose html lang attribute is the invalid value xx1. - [Mismatched lang and xml lang](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/doc-lang-mismatch): A compliant scaffold declaring lang="en" and xml:lang="fr" on the html element. - [Document metadata violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/doc-metadata): No html lang attribute, no title element, and a span with an invalid lang attribute. - [Duplicate id violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/duplicate-ids): Duplicate ids on plain elements, on focusable elements, and on a target referenced by ARIA. - [Form labelling violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/form-labels): One form with eight differently mislabelled controls, from a bare text input to a mismatched accessible name. - [Frame title and focus violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/frames): An untitled iframe, two iframes sharing a title, and a focusable-content iframe removed from the tab order. - [Heading order violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/headings): An h1 followed directly by an h4, then an empty h2. - [Image and graphic violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/images): Missing alt text, redundant alt text, unnamed graphics, an altless image-map area, and a server-side map. - [Keyboard and focus violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/keyboard-focus): A positive tabindex, duplicated access keys, a broken skip link, and two undersized touch targets. - [Landmarks and headings missing](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/landmarks-missing): A valid document whose content sits in plain divs with no landmarks, no headings, and no skip link. - [Landmark structure violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/landmarks-structure): Duplicate and nested banner, contentinfo, main, and complementary landmarks plus two indistinguishable navs. - [Link and button name violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/link-button-names): A nameless link, a nameless button, and two identical "Read more" links pointing at different pages. - [List structure violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/lists): A ul with a div child, an orphan li, a dl containing a p, and dt and dd pairs outside any dl. - [Media caption and autoplay violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/media): Audio and video elements without caption tracks, plus an autoplaying audio element without controls. - [Meta refresh and viewport violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/meta-directives): A 71,100 second meta refresh plus a viewport that disables user scaling and caps zoom below five. - [Presentational and obsolete markup](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/presentational-markup): A bold paragraph styled as a heading, forced letter spacing, an orientation lock, hidden content, blink, and marquee. - [Table semantics violations](https://crawler-test-site.uk.sitebulb.com/tests/accessibility/tables): Seven small single-fault tables covering header, scope, caption, and association rules. ## ai-modern-crawlers - [Bot-specific content marker](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/bot-marker): An endpoint whose marker names the AI bot identity the server matched in the User-Agent, or generic otherwise. - [JavaScript execution detection reference](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/rendering/js-execution-detection): A documentation page cross-referencing the group 07 JavaScript-execution proof fixtures rather than duplicating them. - [JavaScript-gated article content](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/rendering/js-gated): The raw HTML carries only the raw marker; the article content and rendered marker are inserted by an inline script after load. - [llms.txt — missing](https://crawler-test-site.uk.sitebulb.com/llms.txt): The llms-missing origin returning a genuine 404 for its root llms.txt. - [llms.txt — optional section](https://crawler-test-site.uk.sitebulb.com/llms.txt): The llms-optional origin serving a valid llms.txt that adds an Optional section of lower-priority links. - [llms.txt — valid](https://crawler-test-site.uk.sitebulb.com/llms.txt): The llms-valid origin serving a well-formed llms.txt with H1 title, blockquote summary, and a Docs section with two links. - [Bot-scoped meta robots — GPTBot noindex](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/directives/meta-gptbot-noindex): A 200 page carrying a meta robots directive scoped to the GPTBot agent name. - [AI robots blocked target — Amazonbot](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/blocked/amazonbot): A 200 target page whose path the generated robots.txt disallows for the Amazonbot user-agent token only. - [AI robots blocked target — ChatGPT-User](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/blocked/chatgpt-user): A 200 target page whose path the generated robots.txt disallows for the ChatGPT-User user-agent token only. - [AI robots blocked target — Claude-Web](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/blocked/claude-web): A 200 target page whose path the generated robots.txt disallows for the Claude-Web user-agent token only. - [AI robots blocked target — ClaudeBot](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/blocked/claudebot): A 200 target page whose path the generated robots.txt disallows for the ClaudeBot user-agent token only. - [AI robots blocked target — cohere-ai](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/blocked/cohere-ai): A 200 target page whose path the generated robots.txt disallows for the cohere-ai user-agent token only. - [AI robots blocked target — Google-Extended](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/blocked/google-extended): A 200 target page whose path the generated robots.txt disallows for the Google-Extended user-agent token only. - [AI robots blocked target — GPTBot](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/blocked/gptbot): A 200 target page whose path the generated robots.txt disallows for the GPTBot user-agent token only. - [AI robots blocked target — OAI-SearchBot](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/blocked/oai-searchbot): A 200 target page whose path the generated robots.txt disallows for the OAI-SearchBot user-agent token only. - [AI robots blocked target — PerplexityBot](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/blocked/perplexitybot): A 200 target page whose path the generated robots.txt disallows for the PerplexityBot user-agent token only. - [Search-bot allow reference](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/policies/search-bot-allow): Explains the OAI-SearchBot-allowed-but-GPTBot-disallowed contrast created by the per-bot stanzas in this group. - [Server-rendered equivalent control](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/rendering/ssr-equivalent): The same article content as the JS-gated fixture, served in raw HTML so the comparison pair is complete. - [Training-control disallow reference](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/policies/training-disallow): Explains the Google-Extended-disallowed-but-Googlebot-allowed contrast created by the per-bot stanzas in this group. - [Bot-scoped X-Robots-Tag — ClaudeBot noindex](https://crawler-test-site.uk.sitebulb.com/tests/ai-modern-crawlers/directives/xrobots-claudebot-noindex): A 200 response whose X-Robots-Tag header scopes noindex to the ClaudeBot agent. ## asset-weight - [Bulk stylesheet 1](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/bulk-1.css): A generated deterministic minified stylesheet of exactly 194,560 bytes with its own content seed. - [Bulk stylesheet 2](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/bulk-2.css): A generated deterministic minified stylesheet of exactly 194,560 bytes with its own content seed. - [Bulk stylesheet 3](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/bulk-3.css): A generated deterministic minified stylesheet of exactly 194,560 bytes with its own content seed. - [Bundle script 1](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/bundle-1.js): A generated deterministic minified script of exactly 286,720 bytes with its own content seed. - [Bundle script 2](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/bundle-2.js): A generated deterministic minified script of exactly 286,720 bytes with its own content seed. - [Combined CSS weight page](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/combined-css): Links three bulk stylesheets whose combined weight of 583,680 bytes exceeds the 500 KB budget. - [Combined webfont weight page](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/combined-fonts): Renders five paragraphs in five distinct font families whose combined weight of 245,760 bytes exceeds the 200 KB budget. - [Combined image weight page](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/combined-images): Embeds eleven images whose combined weight of 1,081,344 bytes exceeds the 1,000 KB budget. - [Combined JS weight page](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/combined-js): Loads two deferred bundles whose combined weight of 573,440 bytes exceeds the 500 KB budget. - [Duplicate stylesheet variant v1](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/dup.css?v=1): A 256-byte minified stylesheet served byte-identically regardless of the query string. - [Duplicate stylesheet variant v2](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/dup.css?v=2): A 256-byte minified stylesheet served byte-identically regardless of the query string. - [Duplicate script variant v1](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/dup.js?v=1): A 256-byte minified script served byte-identically regardless of the query string. - [Duplicate script variant v2](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/dup.js?v=2): A 256-byte minified script served byte-identically regardless of the query string. - [Duplicate query-variant resources](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/duplicate): Loads the same stylesheet and script under two query-string variants each. - [Webfont 1](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/font-1.woff2): A generated deterministic binary of exactly 49,152 bytes, deliberately under the 50 KB per-font threshold. - [Webfont 2](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/font-2.woff2): A generated deterministic binary of exactly 49,152 bytes, deliberately under the 50 KB per-font threshold. - [Webfont 3](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/font-3.woff2): A generated deterministic binary of exactly 49,152 bytes, deliberately under the 50 KB per-font threshold. - [Webfont 4](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/font-4.woff2): A generated deterministic binary of exactly 49,152 bytes, deliberately under the 50 KB per-font threshold. - [Webfont 5](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/font-5.woff2): A generated deterministic binary of exactly 49,152 bytes, deliberately under the 50 KB per-font threshold. - [Webfont stylesheet](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/fonts.css): A committed minified stylesheet declaring five @font-face rules, each with font-display swap. - [Identical stylesheet a](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/identical-a.css): A committed 256-byte minified stylesheet byte-identical to its sibling copy. - [Identical stylesheet b](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/identical-b.css): A committed 256-byte minified stylesheet byte-identical to its sibling copy. - [Identical script a](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/identical-a.js): A committed 256-byte minified script byte-identical to its sibling copy. - [Identical script b](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/identical-b.js): A committed 256-byte minified script byte-identical to its sibling copy. - [Identical resources at different URLs](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/identical): Loads byte-identical stylesheet and script bodies from URLs whose paths differ beyond the query string. - [Weight payload image 01](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-01.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 02](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-02.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 03](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-03.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 04](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-04.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 05](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-05.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 06](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-06.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 07](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-07.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 08](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-08.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 09](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-09.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 10](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-10.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Weight payload image 11](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/image-11.jpg): A generated image of exactly 98,304 bytes, deliberately under the 100 KB per-image threshold. - [Large stylesheet](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/large.css): A committed minified UTF-8 stylesheet of exactly 20,480 bytes, over the 14.5 KB threshold. - [Large stylesheet page](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/large-stylesheet): Links one minified stylesheet over the 14.5 KB large-stylesheet threshold. - [Many same-origin requests page](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/many-requests): References 36 distinct same-origin subresources: 30 tile images and 6 deferred no-op scripts. - [Request-count no-op script 1](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/noop-1.js): A one-line generated no-op script, discoverable only through the many-requests page. - [Request-count no-op script 2](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/noop-2.js): A one-line generated no-op script, discoverable only through the many-requests page. - [Request-count no-op script 3](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/noop-3.js): A one-line generated no-op script, discoverable only through the many-requests page. - [Request-count no-op script 4](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/noop-4.js): A one-line generated no-op script, discoverable only through the many-requests page. - [Request-count no-op script 5](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/noop-5.js): A one-line generated no-op script, discoverable only through the many-requests page. - [Request-count no-op script 6](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/noop-6.js): A one-line generated no-op script, discoverable only through the many-requests page. - [Request-count tile 01](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-01.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 02](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-02.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 03](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-03.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 04](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-04.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 05](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-05.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 06](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-06.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 07](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-07.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 08](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-08.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 09](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-09.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 10](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-10.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 11](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-11.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 12](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-12.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 13](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-13.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 14](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-14.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 15](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-15.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 16](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-16.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 17](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-17.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 18](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-18.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 19](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-19.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 20](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-20.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 21](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-21.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 22](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-22.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 23](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-23.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 24](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-24.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 25](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-25.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 26](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-26.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 27](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-27.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 28](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-28.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 29](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-29.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Request-count tile 30](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/tile-30.png): A tiny generated 8x8 tile image, discoverable only through the many-requests page. - [Unminified stylesheet (UTF-16LE)](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/unminified.css): A UTF-16LE stylesheet with BOM, comments, blank lines, and four-space indentation, exactly 8,192 bytes. - [Unminified script (UTF-16LE)](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/assets/unminified.js): A UTF-16LE script with BOM, comments, blank lines, and four-space indentation, exactly 8,192 bytes. - [Unminified page](https://crawler-test-site.uk.sitebulb.com/tests/asset-weight/unminified): Pretty-printed HTML linking one unminified stylesheet and one unminified script. ## auth-access-control - [HTTP 403 forbidden without challenge](https://crawler-test-site.uk.sitebulb.com/tests/auth/403-forbidden): A plain 403 with no WWW-Authenticate header, distinguishing forbidden-without-challenge from the 401 fixtures. - [Session cookie setter](https://crawler-test-site.uk.sitebulb.com/tests/auth/cookie-setter): Sets the fixture session cookie and links to the cookie-gated content page. - [IP-based access control reference](https://crawler-test-site.uk.sitebulb.com/tests/auth/ip-based-profile-reference): A documentation page pointing at the fingerprinting profile; contains no IP or fingerprint logic of its own. - [Visible login form](https://crawler-test-site.uk.sitebulb.com/tests/auth/login-form-visible): An indexable 200 login page with a POST form; the POST handler is a stub that always re-renders the form. - [Noindexed login form](https://crawler-test-site.uk.sitebulb.com/tests/auth/noindex-login-page): A fetchable 200 login form carrying a meta robots noindex directive. - [Redirect to login](https://crawler-test-site.uk.sitebulb.com/tests/auth/redirect-to-login): Unconditionally bounces to the visible login form — the classic protected-page-to-login pattern without a session. - [Robots-accessible login form](https://crawler-test-site.uk.sitebulb.com/tests/auth/robots-accessible-login): The robots-allowed, sitemap-listed login form variant intended for broad discovery. ## canonical-tags - [Canonical — body placement is ignored](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/body-placement): An HTML page whose only canonical link element sits inside the body, where it has no effect. - [Canonical — case variant of its own path](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/case-variant): An HTML page whose canonical nominates an uppercase case-variant of its own path. - [Canonical — points at the preferred page](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/to-preferred-page): An HTML page whose head canonical nominates a different preferred page. - [Canonical — href carries a fragment](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/fragment): An HTML page whose canonical href includes a #section fragment that crawlers must strip. - [Canonical — HTML head vs HTTP Link header conflict](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/html-http-conflict): An HTML response whose head canonical disagrees with the canonical in its HTTP Link header. - [Canonical — HTTP Link header](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/http-link-header): An HTML response whose only canonical declaration arrives in an HTTP Link header. - [Canonical — multiple conflicting head canonicals](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/multiple-conflicting): An HTML page declaring two head canonicals that nominate different URLs. - [Canonical — disagrees with og:url](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/og-url-conflict): An HTML page whose head canonical and og:url meta tag nominate different URLs. - [Canonical — explicit default port](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/port-normalisation): A page whose canonical advertises an explicit :443 port that normalises away for https. - [Canonical preferred page](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/preferred-page): The plain crawlable page that cross-page and conflict fixtures nominate as canonical. - [Canonical — http page nominates its https equivalent](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/protocol-mismatch): A plain-HTTP page whose canonical nominates the https URL of the same path on the primary site. - [Canonical — relative URL](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/relative-url): An HTML page whose head canonical uses a root-relative href instead of an absolute URL. - [Canonical — self-referencing](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/self): An HTML page whose head canonical points at its own absolute URL. - [Canonical — target returns 404](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/to-404): An HTML page whose canonical nominates a URL that returns HTTP 404. - [Canonical — target is noindex](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/to-noindex): An HTML page whose canonical nominates a page that declares meta robots noindex. - [Canonical — target redirects](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/to-redirect): An HTML page whose canonical nominates a URL that 301-redirects to the preferred page. - [Canonical — trailing-slash variant of its own path](https://crawler-test-site.uk.sitebulb.com/tests/canonicals/trailing-slash): An HTML page served without a trailing slash whose canonical adds one. ## content-meta-tags - [Charset — HTTP/HTML conflict](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/charset/http-html-conflict): An endpoint whose Content-Type header declares UTF-8 while the meta charset claims ISO-8859-1. - [Charset — ISO-8859-1](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/charset/iso-8859-1): An endpoint declaring ISO-8859-1 in both the Content-Type header and meta charset, serving genuine Latin-1 bytes. - [Charset — header/body mismatch](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/charset/mismatch): An endpoint whose Content-Type header declares ISO-8859-1 while the body is UTF-8 with a UTF-8 meta charset. - [Charset — undeclared](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/charset/missing): An endpoint sending text/html with no charset parameter and no meta charset, forcing auto-detection. - [Charset — UTF-8 baseline](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/charset/utf-8): An HTML page declaring UTF-8 via meta charset and carrying multi-byte body text. - [Meta description — duplicated tag](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/description/duplicate): An HTML page whose head contains two meta description elements. - [Meta description — empty](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/description/empty): An HTML page whose meta description exists with an empty content attribute. - [Meta description — long](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/description/long): An HTML page with a deterministic meta description of roughly 400 characters. - [Meta description — missing](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/description/missing): An HTML page whose head contains no meta description at all. - [Content — duplicate pair (primary)](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/content/duplicate): The first of two pages sharing an identical 120-word body for duplicate-content detection. - [Content — duplicate pair (twin)](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/content/duplicate-twin): The twin page sharing the identical 120-word body with the primary duplicate fixture. - [Headings — H1 missing](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/headings/h1-missing): An HTML page whose top-level heading is an H2 with no H1 anywhere. - [Headings — multiple H1s](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/headings/h1-multiple): An HTML page containing two H1 elements. - [Headings — out of order](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/headings/out-of-order): An HTML page that opens with an H3 before its H1, breaking heading hierarchy. - [Content — thin](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/content/thin): An HTML page whose entire body copy is one short sentence. - [Title — inside body only](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/title/in-body): An HTML page whose only title element sits inside the body, not the head. - [Title — empty](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/title/empty): An HTML page whose title element exists but contains no text. - [Title — HTML entities](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/title/entities): An HTML page whose title contains raw HTML entities that must decode consistently. - [Title — long](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/title/long): An HTML page with a deterministic title of roughly 280 characters. - [Title — missing](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/title/missing): An HTML page whose head contains no title element at all. - [Title — multiple](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/title/multiple): An HTML page whose head contains two distinct title elements. - [Title — newline in text](https://crawler-test-site.uk.sitebulb.com/tests/content-meta/title/newlines): An HTML page whose title text contains a literal line break. ## content-quality - [A very difficult reading page with long words](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/readability/very-difficult): Sentences of thirty plus polysyllabic words designed for a Flesch-Kincaid score of 10 or lower. - [A very easy reading page with short plain words](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/readability/very-easy): Short, mostly monosyllabic sentences designed for a Flesch-Kincaid score of 100 or higher. - [Rendered word divergence calibration fixture](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/rendered/word-divergence): Raw body of exactly 150 content words; an inline script appends two paragraphs totalling exactly 100 more. - [A strongly negative review of the station diner](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/sentiment/strongly-negative): Committed copy seeding AFINN-listed negative words to a designed sentiment sum below -120. - [A strongly positive review of the harbour cafe](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/sentiment/strongly-positive): Committed copy seeding AFINN-listed positive words to a designed sentiment sum above +120. - [Template subtraction sibling page A of four](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/template/page-a): Shared 150-word nav and aside template with exactly 200 words of pottery main content. - [Template subtraction sibling page B of four](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/template/page-b): Shared 150-word nav and aside template with exactly 300 words of weaving main content. - [Template subtraction sibling page C of four](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/template/page-c): Shared 150-word nav and aside template with exactly 400 words of beekeeping main content. - [Template subtraction sibling page D of four](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/template/page-d): Shared 150-word nav and aside template with exactly 500 words of printmaking main content. - [Word count calibration page at one twenty](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/word-count/exact-120): Committed copy of exactly 120 content words, h1 included, in paragraphs only. - [Word count calibration page at twelve hundred](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/word-count/exact-1200): Committed copy of exactly 1,200 content words, above the 501 to 900 bin. - [Word count calibration page at seven fifty](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/word-count/exact-750): Committed copy of exactly 750 content words, landing mid-band in the 501 to 900 bin. - [Similarity gradient base copy with garden notes](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/similarity/base): The 20-paragraph, 1,000-word reference copy for the near-duplicate similarity gradient. - [Similarity gradient variant at seventy percent](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/similarity/variant-70): Base copy with paragraphs 15 to 20 replaced; the boundary probe for the default similarity threshold. - [Similarity gradient variant at eighty five percent](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/similarity/variant-85): Base copy with paragraphs 18 to 20 replaced; design-target similarity to base of roughly 85 percent. - [Similarity gradient variant at ninety five percent](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/similarity/variant-95): Base copy with paragraph 20 replaced; design-target similarity to base of roughly 95 percent. - [A field guide to auditing one page at a time](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/custom-dictionary-trap): English page whose only spelling errors are five invented brand-like words, flipping to zero once they enter the custom dictionary. - [Unser Intresse an guter Handwerksarbeit nimmt zu](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/de): German page seeding five misspellings checked against the de dictionary. - [Die Entwiklung unserer kleinen Tischlerei geht weiter](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/dictionary-fallback): German page declared as de-DE, which has no exact dictionary, proving base-language fallback to de. - [Booking a stay we can accomodate without any fuss](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/en-gb): English (en-GB) page seeding five misspellings across title, description, h1, and body, plus an alt-text negative probe. - [Un exelente comienzo para nuestro nuevo proyecto](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/es): Spanish page seeding five non-word misspellings checked against the es dictionary. - [Un apartement lumineux au bord de la vieille ville](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/fr): French page seeding five misspellings checked against the fr dictionary. - [Una efficenza sorprendente nel nostro laboratorio](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/it): Italian page seeding five misspellings checked against the it dictionary. - [Een acommodatie met uitzicht over de oude haven](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/nl): Dutch page seeding five misspellings checked against the nl dictionary. - [Uma excessão notável entre as casas antigas da vila](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/pt): Portuguese page seeding five misspellings checked against the pt dictionary. - [Симпотичный домик у самого края соснового леса](https://crawler-test-site.uk.sitebulb.com/tests/content-quality/spelling/ru): Russian page seeding five Cyrillic misspellings checked against the ru dictionary. ## crawl-scope - [One-stop scope audit page](https://crawler-test-site.uk.sitebulb.com/tests/scope/audit-all): A page whose five anchors cover every scope class in this group: subdomain, external, CDN, tracking, and protocol variants. - [CDN asset — image](https://crawler-test-site.uk.sitebulb.com/tests/scope/cdn/image.png): The committed 64x64 PNG the CDN embedding page references, with its marker in a tEXt chunk. - [CDN asset — script](https://crawler-test-site.uk.sitebulb.com/tests/scope/cdn/script.js): The committed no-op JavaScript file the CDN embedding page references, served from the asset host. - [CDN asset — stylesheet](https://crawler-test-site.uk.sitebulb.com/tests/scope/cdn/styles.css): The committed CSS file the CDN embedding page references, served from the asset host. - [CDN-hosted first-party resources](https://crawler-test-site.uk.sitebulb.com/tests/scope/cdn-embedded-resources): A page embedding a stylesheet, a script, and an image served from the CDN-style asset host. - [External link scope](https://crawler-test-site.uk.sitebulb.com/tests/scope/external-link): A page whose single anchor is the shared external target constant, so external classification is observable. - [Scheme and default-port scope variants](https://crawler-test-site.uk.sitebulb.com/tests/scope/protocol-port-variants): A page whose three anchors are the plain, explicit-:443, and http:// variants of one primary-host path. - [Scheme and port variants target](https://crawler-test-site.uk.sitebulb.com/tests/scope/protocol-variants-target): The stable primary-host page the scheme and default-port variant anchors all resolve to. - [Subdomain scope link](https://crawler-test-site.uk.sitebulb.com/tests/scope/subdomain-link): A page whose single anchor points at a sibling-subdomain page, so subdomain scope classification is observable. - [Subdomain scope target](https://crawler-test-site.uk.sitebulb.com/tests/scope/subdomain-target): The sibling-subdomain page the scope link points at, with one anchor back into primary scope. - [Tracking stub — analytics script](https://crawler-test-site.uk.sitebulb.com/tests/scope/tracking/analytics.js): The committed no-op analytics script stub, served from the tracking-stub host; performs no tracking. - [Tracking stub — beacon pixel](https://crawler-test-site.uk.sitebulb.com/tests/scope/tracking/collect.png): The committed 1x1 PNG pixel stub, served from the tracking-stub host, with its marker in a tEXt chunk. - [Third-party tracking stubs](https://crawler-test-site.uk.sitebulb.com/tests/scope/tracking-stub-page): A page embedding a self-labelled analytics script stub and a 1x1 pixel stub from the tracking-stub host. ## custom-extraction-search - [Extraction target — attribute-borne data](https://crawler-test-site.uk.sitebulb.com/tests/extraction/extract-attribute-page): Frozen values carried in data attributes, a head meta content attribute, and a link href. - [Extraction target — contact page](https://crawler-test-site.uk.sitebulb.com/tests/extraction/extract-contact-page): Frozen contact values: two emails, UK and US phone numbers, and ISO and UK-format dates. - [Extraction target — empty selector](https://crawler-test-site.uk.sitebulb.com/tests/extraction/extract-empty-target): Documents the no-match path: the sb-absent class genuinely appears on no element anywhere in the markup. - [Extraction target — product page](https://crawler-test-site.uk.sitebulb.com/tests/extraction/extract-product-page): Frozen product values: four price formats, a SKU, an availability flag, and a seven-word description. - [Extraction target — regex edge cases](https://crawler-test-site.uk.sitebulb.com/tests/extraction/extract-regex-edge): Regex-hostile frozen values: a versioned token with a decoy, literal regex special characters, multi-line text, and a case-sensitivity pair. - [Extraction target — rendered-only values](https://crawler-test-site.uk.sitebulb.com/tests/extraction/extract-rendered-only): Price and SKU containers ship empty in the raw HTML; an inline script fills them only after JavaScript execution. - [Extraction target — repeated elements](https://crawler-test-site.uk.sitebulb.com/tests/extraction/extract-repeated-elements): Exactly 12 li.sb-item elements, item-01 through item-12 in order, and no other li on the page. - [Extraction target — data table](https://crawler-test-site.uk.sitebulb.com/tests/extraction/extract-table-page): One table with exactly 4 header cells, 6 body rows, and 24 body cells; first-column names are frozen. - [Search target — case variants](https://crawler-test-site.uk.sitebulb.com/tests/extraction/search-case-variants): One token in three casings: mixed twice, lower twice, upper once, for the IgnoreCase pair. - [Search target — German locale](https://crawler-test-site.uk.sitebulb.com/tests/extraction/search-german-locale): UTF-8 German page with umlaut and sharp-s tokens that freeze character-level case folding behaviour. - [Search target — keyword frequency](https://crawler-test-site.uk.sitebulb.com/tests/extraction/search-keyword-frequency): Body text carries one invented token exactly 7 times and a second exactly 3 times, always as whole words. - [Search target — negative term](https://crawler-test-site.uk.sitebulb.com/tests/extraction/search-negative-term): A counted token appears exactly 4 times next to a single negative-trigger token that suppresses the count. - [Search target — selector scope](https://crawler-test-site.uk.sitebulb.com/tests/extraction/search-selector-scope): One token placed with exact scope counts: once in the head title, three times in the body, one of those inside an anchor. - [Search target — word boundaries](https://crawler-test-site.uk.sitebulb.com/tests/extraction/search-word-boundary): A whole word appears exactly 4 times alongside superstring traps that word-boundary matching must not count. - [Snippet target — static DOM counts](https://crawler-test-site.uk.sitebulb.com/tests/extraction/snippet-dom-counts): A server-rendered DOM with exactly 9 nodes of one class, of which exactly 4 carry a modifier class. - [Snippet target — frozen JS global](https://crawler-test-site.uk.sitebulb.com/tests/extraction/snippet-global-state): An inline script freezes window.sbFixture with a known id, version, items array, and nested ratio. - [Snippet target — load-event timing](https://crawler-test-site.uk.sitebulb.com/tests/extraction/snippet-timing-state): A head script sets a global immediately and rewrites it in the window load handler, proving snippet timing is honoured. ## exotic-advanced-tests - [Custom element with shadow content](https://crawler-test-site.uk.sitebulb.com/tests/exotic-advanced-tests/web-components/custom-elements): The raw HTML carries only the undefined custom tag and the raw marker; the rendered marker exists only in shadow content. - [Legacy HTML4 frameset](https://crawler-test-site.uk.sitebulb.com/tests/exotic-advanced-tests/frameset/legacy): A frameset document with no body element and two frame src targets. - [Sandboxed same-origin iframe](https://crawler-test-site.uk.sitebulb.com/tests/exotic-advanced-tests/iframes/sandbox): A page embedding a same-origin iframe whose bare sandbox attribute omits allow-scripts. - [HTTP method resource — DELETE 405](https://crawler-test-site.uk.sitebulb.com/tests/exotic-advanced-tests/methods/resource): DELETE returns 405 Method Not Allowed with the advertised method set. - [HTTP method resource — HEAD](https://crawler-test-site.uk.sitebulb.com/tests/exotic-advanced-tests/methods/resource): HEAD returns 200 with the exact GET headers and Content-Length but an empty body. - [HTTP method resource — OPTIONS](https://crawler-test-site.uk.sitebulb.com/tests/exotic-advanced-tests/methods/resource): OPTIONS returns 204 with the advertised method set and no body. - [HTTP method resource — PATCH 405](https://crawler-test-site.uk.sitebulb.com/tests/exotic-advanced-tests/methods/resource): PATCH returns 405 Method Not Allowed with the advertised method set. - [HTTP method resource — PUT 405](https://crawler-test-site.uk.sitebulb.com/tests/exotic-advanced-tests/methods/resource): PUT returns 405 Method Not Allowed with the advertised method set. - [Parser stress — deep nesting](https://crawler-test-site.uk.sitebulb.com/tests/exotic-advanced-tests/parser/nested): 512 balanced nested div elements with the full-depth marker at the bottom. ## foundation-example - [Hello — Status 200](https://crawler-test-site.uk.sitebulb.com/fixtures/hello-status-200): A minimal page that returns HTTP 200, the simplest possible crawl target. ## http-headers - [Compression — brotli encoded response](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/compression/brotli): Serves HTML with Content-Encoding: br negotiated at the proxy layer. - [Conflicting cache headers](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/cache/conflicting): Serves the self-contradictory Cache-Control: no-store, max-age=31536000 plus a far-future Expires. - [Cache-Control one-year max-age](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/cache/max-age-31536000): Serves Cache-Control: public, max-age=31536000, a one-year shared-cache lifetime. - [Cache-Control max-age=0](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/cache/max-age-0): Serves Cache-Control: max-age=0, an immediately stale but cacheable response. - [Cache-Control no-cache](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/cache/no-cache): Serves an explicit Cache-Control: no-cache, forcing revalidation on every reuse. - [Cache-Control no-store](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/cache/no-store): Serves an explicit Cache-Control: no-store, forbidding any caching of the response. - [Cache-Control private](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/cache/private): Serves Cache-Control: private, max-age=600, cacheable only by the end client. - [Content-Type malformed](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/content-type/malformed): Serves HTML under the malformed media type texthtml, which has no type/subtype slash. - [CSP blocks an external script](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/security/csp-external-block): Serves Content-Security-Policy: script-src 'none' so the referenced probe script never executes. - [CSP blocks inline scripts](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/security/csp-inline-block): Serves Content-Security-Policy: script-src 'self' so the inline script never rewrites the result element. - [Delayed response — 5 seconds](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/timing/delay-5s): Holds the whole response for exactly 5 seconds before serving the 200 page. - [ETag conditional flow](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/cache/etag): An unconditional GET returns 200 with a fixed ETag; a matching If-None-Match earns a 304. - [Expires header](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/cache/expires): Serves a far-future Expires date alongside Cache-Control: public so the legacy header stays operative. - [Compression — gzip encoded response](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/compression/gzip): Serves HTML with Content-Encoding: gzip negotiated at the proxy layer. - [HSTS — long max-age with preload](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/security/hsts-preload): Serves Strict-Transport-Security: max-age=63072000; includeSubDomains; preload over HTTPS. - [HSTS — short max-age](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/security/hsts-short): Serves Strict-Transport-Security: max-age=300 over HTTPS. - [Last-Modified conditional flow](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/cache/last-modified): An unconditional GET returns 200 with a fixed Last-Modified; a matching If-Modified-Since earns a 304. - [X-Content-Type-Options nosniff](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/security/nosniff): Serves X-Content-Type-Options: nosniff alongside an accurate HTML Content-Type. - [HTML body served as text/plain](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/content-type/text-plain-html): Serves a complete HTML document under Content-Type: text/plain so markup must not be interpreted. - [Vary on User-Agent with identical content](https://crawler-test-site.uk.sitebulb.com/tests/http-headers/negotiation/vary-user-agent): Serves byte-identical HTML to every User-Agent while declaring Vary: User-Agent. ## http-status-codes - [HTTP 102 Processing](https://crawler-test-site.uk.sitebulb.com/tests/http-status/informational/102-processing): An interim 102 Processing followed by a final 200; needs wire-level server support. - [HTTP 103 Early Hints](https://crawler-test-site.uk.sitebulb.com/protocol/103-early-hints): An interim 103 with preload hints followed by the final 200 page. - [HTTP 200 OK](https://crawler-test-site.uk.sitebulb.com/tests/http-status/success/200-ok): The baseline crawlable HTML page for the status-code group. - [HTTP 204 No Content](https://crawler-test-site.uk.sitebulb.com/tests/http-status/success/204-no-content): A successful response with deliberately no body at all. - [HTTP 206 Partial Content](https://crawler-test-site.uk.sitebulb.com/tests/http-status/success/206-partial-content): Serves byte ranges: 206 with Content-Range for a Range request, 200 with Accept-Ranges otherwise. - [HTTP 300 Multiple Choices](https://crawler-test-site.uk.sitebulb.com/tests/http-status/redirect/300-multiple-choices): A 300 response advertising the baseline page in its Location header. - [HTTP 301 Moved Permanently](https://crawler-test-site.uk.sitebulb.com/tests/http-status/redirect/301): Returns exactly HTTP 301 (Moved Permanently) pointing at the baseline 200 page. - [HTTP 302 Found](https://crawler-test-site.uk.sitebulb.com/tests/http-status/redirect/302): Returns exactly HTTP 302 (Found) pointing at the baseline 200 page. - [HTTP 303 See Other](https://crawler-test-site.uk.sitebulb.com/tests/http-status/redirect/303): Returns exactly HTTP 303 (See Other) pointing at the baseline 200 page. - [HTTP 304 Not Modified](https://crawler-test-site.uk.sitebulb.com/tests/http-status/conditional/304-not-modified): An unconditional GET returns 200 with validators; a conditional GET earns the 304. - [HTTP 307 Temporary Redirect](https://crawler-test-site.uk.sitebulb.com/tests/http-status/redirect/307): Returns exactly HTTP 307 (Temporary Redirect) pointing at the baseline 200 page. - [HTTP 308 Permanent Redirect](https://crawler-test-site.uk.sitebulb.com/tests/http-status/redirect/308): Returns exactly HTTP 308 (Permanent Redirect) pointing at the baseline 200 page. - [HTTP 400 Bad Request](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/400): Returns exactly HTTP 400 (Bad Request) with a machine-readable marker. - [HTTP 401 Unauthorized](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/401): Returns exactly HTTP 401 (Unauthorized) with a machine-readable marker. - [HTTP 402 Payment Required](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/402): Returns exactly HTTP 402 (Payment Required) with a machine-readable marker. - [HTTP 403 Forbidden](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/403): Returns exactly HTTP 403 (Forbidden) with a machine-readable marker. - [HTTP 404 Not Found](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/404): Returns exactly HTTP 404 (Not Found) with a machine-readable marker. - [HTTP 405 Method Not Allowed](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/405): Returns exactly HTTP 405 (Method Not Allowed) with a machine-readable marker. - [HTTP 406 Not Acceptable](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/406): Returns exactly HTTP 406 (Not Acceptable) with a machine-readable marker. - [HTTP 407 Proxy Authentication Required](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/407): Returns exactly HTTP 407 (Proxy Authentication Required) with a machine-readable marker. - [HTTP 408 Request Timeout](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/408): Returns exactly HTTP 408 (Request Timeout) with a machine-readable marker. - [HTTP 409 Conflict](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/409): Returns exactly HTTP 409 (Conflict) with a machine-readable marker. - [HTTP 410 Gone](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/410-gone): Returns exactly HTTP 410 (Gone) with a machine-readable marker. - [HTTP 411 Length Required](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/411): Returns exactly HTTP 411 (Length Required) with a machine-readable marker. - [HTTP 412 Precondition Failed](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/412): Returns exactly HTTP 412 (Precondition Failed) with a machine-readable marker. - [HTTP 413 Content Too Large](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/413): Returns exactly HTTP 413 (Content Too Large) with a machine-readable marker. - [HTTP 414 URI Too Long](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/414): Returns exactly HTTP 414 (URI Too Long) with a machine-readable marker. - [HTTP 415 Unsupported Media Type](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/415): Returns exactly HTTP 415 (Unsupported Media Type) with a machine-readable marker. - [HTTP 416 Range Not Satisfiable](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/416): Returns exactly HTTP 416 (Range Not Satisfiable) with a machine-readable marker. - [HTTP 417 Expectation Failed](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/417): Returns exactly HTTP 417 (Expectation Failed) with a machine-readable marker. - [HTTP 418 I'm a teapot](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/418): Returns exactly HTTP 418 (I'm a teapot) with a machine-readable marker. - [HTTP 421 Misdirected Request](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/421): Returns exactly HTTP 421 (Misdirected Request) with a machine-readable marker. - [HTTP 422 Unprocessable Content](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/422): Returns exactly HTTP 422 (Unprocessable Content) with a machine-readable marker. - [HTTP 423 Locked](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/423): Returns exactly HTTP 423 (Locked) with a machine-readable marker. - [HTTP 424 Failed Dependency](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/424): Returns exactly HTTP 424 (Failed Dependency) with a machine-readable marker. - [HTTP 425 Too Early](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/425): Returns exactly HTTP 425 (Too Early) with a machine-readable marker. - [HTTP 426 Upgrade Required](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/426): Returns exactly HTTP 426 (Upgrade Required) with a machine-readable marker. - [HTTP 428 Precondition Required](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/428): Returns exactly HTTP 428 (Precondition Required) with a machine-readable marker. - [HTTP 429 Too Many Requests](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/429): Returns exactly HTTP 429 (Too Many Requests) with a machine-readable marker. - [HTTP 431 Request Header Fields Too Large](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/431): Returns exactly HTTP 431 (Request Header Fields Too Large) with a machine-readable marker. - [HTTP 451 Unavailable For Legal Reasons](https://crawler-test-site.uk.sitebulb.com/tests/http-status/client-error/451-unavailable-for-legal-reasons): Returns exactly HTTP 451 (Unavailable For Legal Reasons) with a machine-readable marker. - [HTTP 500 Internal Server Error](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/500): Returns exactly HTTP 500 (Internal Server Error) with a machine-readable marker. - [HTTP 501 Not Implemented](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/501): Returns exactly HTTP 501 (Not Implemented) with a machine-readable marker. - [HTTP 502 Bad Gateway](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/502): Returns exactly HTTP 502 (Bad Gateway) with a machine-readable marker. - [HTTP 503 Service Unavailable](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/503): Returns exactly HTTP 503 (Service Unavailable) with a machine-readable marker. - [HTTP 503 with Retry-After](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/503-retry-after): A 503 carrying an explicit Retry-After backoff signal. - [HTTP 504 Gateway Timeout](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/504): Returns exactly HTTP 504 (Gateway Timeout) with a machine-readable marker. - [HTTP 505 HTTP Version Not Supported](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/505): Returns exactly HTTP 505 (HTTP Version Not Supported) with a machine-readable marker. - [HTTP 506 Variant Also Negotiates](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/506): Returns exactly HTTP 506 (Variant Also Negotiates) with a machine-readable marker. - [HTTP 507 Insufficient Storage](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/507): Returns exactly HTTP 507 (Insufficient Storage) with a machine-readable marker. - [HTTP 508 Loop Detected](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/508): Returns exactly HTTP 508 (Loop Detected) with a machine-readable marker. - [HTTP 510 Not Extended](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/510): Returns exactly HTTP 510 (Not Extended) with a machine-readable marker. - [HTTP 511 Network Authentication Required](https://crawler-test-site.uk.sitebulb.com/tests/http-status/server-error/511): Returns exactly HTTP 511 (Network Authentication Required) with a machine-readable marker. - [Soft 404 — noindex with 200](https://crawler-test-site.uk.sitebulb.com/tests/http-status/soft-404/noindex-200): Returns HTTP 200 with not-found language plus a meta robots noindex. - [Soft 404 — thin content](https://crawler-test-site.uk.sitebulb.com/tests/http-status/soft-404/thin-content): Returns HTTP 200 with almost no content, a thin soft-404 candidate. - [Soft 404 — not-found title and body](https://crawler-test-site.uk.sitebulb.com/tests/http-status/soft-404/not-found-title-body): Returns HTTP 200 while the title and body read as a not-found page. - [Soft 404 — title says 404, status says 200](https://crawler-test-site.uk.sitebulb.com/tests/http-status/soft-404/title-says-404-status-200): Returns HTTP 200 while the title claims a 404 error. ## images - [Animated GIF over the video threshold](https://crawler-test-site.uk.sitebulb.com/tests/images/animated-gif): Embeds the animation as a GIF image over the 102,400-byte video-format threshold. - [Animated GIF asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/animation.gif): A deterministic generated 480x270 image served as image/gif with its fixture marker in a tEXt chunk. - [Animation delivered as video](https://crawler-test-site.uk.sitebulb.com/tests/images/animated-video): The recommended replacement: the same animation delivered via an autoplaying, looping, muted MP4 video. - [MP4 video asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/animation.mp4): A deterministic generated 480x270 image served as video/mp4 with its fixture marker in a tEXt chunk. - [Decorative image asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/decorative-alt.png): A deterministic generated 64x64 image served as image/png with its fixture marker in a tEXt chunk. - [Decorative image with empty alt](https://crawler-test-site.uk.sitebulb.com/tests/images/decorative-alt): Correct decorative markup (alt="" with role="presentation") that the empty-alt predicate still flags. - [Inefficiently encoded image — large saving](https://crawler-test-site.uk.sitebulb.com/tests/images/encoding-q100): Embeds the largest fixture photo at natural size, the anchor case for recompression and next-gen savings. - [Large-saving photo asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/photo-q100.jpg): A deterministic generated 1200x800 image served as image/jpeg with its fixture marker in a tEXt chunk. - [Inefficiently encoded image — moderate saving](https://crawler-test-site.uk.sitebulb.com/tests/images/encoding-q92): Embeds the moderate-saving fixture photo at natural size, bracketing the encoding threshold from above. - [Moderate-saving photo asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/photo-q92.jpg): A deterministic generated 800x533 image served as image/jpeg with its fixture marker in a tEXt chunk. - [16x16 favicon asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/favicon-16.png): A deterministic generated 16x16 image served as image/png with its fixture marker in a tEXt chunk. - [180x180 apple-touch icon asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/apple-touch-180.png): A deterministic generated 180x180 image served as image/png with its fixture marker in a tEXt chunk. - [32x32 favicon asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/favicon-32.png): A deterministic generated 32x32 image served as image/png with its fixture marker in a tEXt chunk. - [Favicon link to a 404 target](https://crawler-test-site.uk.sitebulb.com/tests/images/favicon-missing): Declares a rel="icon" link pointing at a registered 404 favicon target. - [Missing favicon target](https://crawler-test-site.uk.sitebulb.com/tests/images/favicon/missing.ico): A deliberately missing favicon URL registered so the broken icon reference is a validated 404 fixture. - [Multiple sized icon links](https://crawler-test-site.uk.sitebulb.com/tests/images/favicon-multi-size): Declares 16x16 and 32x32 icons plus a 180x180 apple-touch-icon. - [Favicon with a mismatched content type](https://crawler-test-site.uk.sitebulb.com/tests/images/favicon-wrong-content-type): Declares a rel="icon" link whose target serves image bytes under Content-Type text/plain. - [Wrong-content-type icon](https://crawler-test-site.uk.sitebulb.com/tests/images/favicon/wrong-type.ico): Image bytes served as Content-Type text/plain, so the declared type and actual bytes deliberately disagree. - [Hidden eager image](https://crawler-test-site.uk.sitebulb.com/tests/images/hidden): An eager image inside a display:none wrapper, followed by a deliberate ~200 ms long task. - [Hidden image asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/hidden.jpg): A deterministic generated 800x533 image served as image/jpeg with its fixture marker in a tEXt chunk. - [Linked alt-less image asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/linked-missing-alt.png): A deterministic generated 64x64 image served as image/png with its fixture marker in a tEXt chunk. - [Linked image missing alt text](https://crawler-test-site.uk.sitebulb.com/tests/images/linked-missing-alt): An anchor whose only content is an alt-less image, so the missing alt also removes the link anchor text. - [Alt-less image asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/missing-alt.png): A deterministic generated 64x64 image served as image/png with its fixture marker in a tEXt chunk. - [Images missing alt text](https://crawler-test-site.uk.sitebulb.com/tests/images/missing-alt): Embeds the same PNG twice: once via a plain img with no alt attribute, once via srcset with an empty alt. - [Image without declared dimensions](https://crawler-test-site.uk.sitebulb.com/tests/images/missing-dimensions): Embeds an 800x533 image with alt text but no width, height, or CSS sizing. - [Undeclared-dimensions image asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/no-dimensions.jpg): A deterministic generated 800x533 image served as image/jpeg with its fixture marker in a tEXt chunk. - [Photographic truecolour PNG](https://crawler-test-site.uk.sitebulb.com/tests/images/nextgen-png): Embeds a photographic-class PNG, the canonical WebP/AVIF-would-win case. - [Photographic PNG asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/photo.png): A deterministic generated 800x533 image served as image/png with its fixture marker in a tEXt chunk. - [Offscreen eager image](https://crawler-test-site.uk.sitebulb.com/tests/images/offscreen): A 3,000px spacer pushes an eager image fully below the fold, followed by the same deliberate long task. - [Offscreen image asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/offscreen.jpg): A deterministic generated 800x533 image served as image/jpeg with its fixture marker in a tEXt chunk. - [Browser-scaled image](https://crawler-test-site.uk.sitebulb.com/tests/images/scaled): A 1600x1067 image rendered inside a 200px container, discarding almost all downloaded pixels. - [Scaled 1600x1067 image asset](https://crawler-test-site.uk.sitebulb.com/tests/images/assets/scaled-1600.jpg): A deterministic generated 1600x1067 image served as image/jpeg with its fixture marker in a tEXt chunk. ## international-hreflang - [Hreflang cluster A — Deutsch](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-a/de): The German member of a five-page reciprocal cluster declaring all alternates (hreflang de) via head link elements. - [Hreflang cluster A — English](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-a/en): The English member of a five-page reciprocal cluster declaring all alternates (hreflang en) via head link elements. - [Hreflang cluster A — Español](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-a/es): The Spanish member of a five-page reciprocal cluster declaring all alternates (hreflang es) via head link elements. - [Hreflang cluster A — Français](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-a/fr): The French member of a five-page reciprocal cluster declaring all alternates (hreflang fr) via head link elements. - [Hreflang cluster A — language selector](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-a/x-default): The language-selector member of a five-page reciprocal cluster declaring all alternates (hreflang x-default) via head link elements. - [Hreflang broken — alternate target redirects](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/target-301/en): An English page declaring a German alternate whose URL answers a 301 redirect. - [Hreflang broken — the redirect destination](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/target-301/de-final): The German page the redirecting alternate lands on; it declares no alternates of its own. - [Hreflang broken — alternate target returns 404](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/target-404/en): An English page declaring a German alternate whose URL returns HTTP 404. - [Hreflang broken — the missing German alternate](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/target-404/de): The declared German alternate that deliberately answers 404. - [Hreflang broken — html lang vs Content-Language conflict](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/lang-conflict): A page whose html lang attribute says en while the Content-Language response header says de. - [Hreflang cluster B — English (Link header)](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-b/en): The English member of a two-page reciprocal cluster whose alternates are declared only via the HTTP Link response header. - [Hreflang cluster B — Deutsch (Link header)](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-b/de): The German member of a two-page reciprocal cluster whose alternates are declared only via the HTTP Link response header. - [Hreflang broken — invalid language codes](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/invalid-language-code): An English page declaring a valid en alternate plus the invalid hreflang values en-UK and english. - [Hreflang broken — missing reciprocal, declaring side](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/missing-reciprocal/a): An English page declaring itself and a German alternate that never declares it back. - [Hreflang broken — missing reciprocal, silent side](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/missing-reciprocal/b): The German page that declares only itself, deliberately omitting the return link to its English counterpart. - [Hreflang broken — German page canonicalised to English](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/mixed-locale-canonical/de): A German page in a reciprocal en/de pair whose canonical nominates the English page instead of itself. - [Hreflang broken — the self-canonical English counterpart](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/mixed-locale-canonical/en): The English counterpart with the same reciprocal pair and a self-referencing canonical; it anchors the conflict on the German side. - [Hreflang broken — multiple x-default declarations](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/multiple-x-default): An English page declaring two x-default entries with different hrefs alongside its valid self-reference. - [Hreflang broken — the second x-default target](https://crawler-test-site.uk.sitebulb.com/tests/international/broken/multiple-x-default/alternate): The reachable second x-default target; it deliberately declares no alternates back. - [RTL fixture — Arabic](https://crawler-test-site.uk.sitebulb.com/tests/international/rtl/arabic): A standalone right-to-left document with html lang ar, dir rtl, and a native-script Arabic paragraph. - [RTL fixture — Hebrew](https://crawler-test-site.uk.sitebulb.com/tests/international/rtl/hebrew): A standalone right-to-left document with html lang he, dir rtl, and a native-script Hebrew paragraph. - [Hreflang cluster C — xhtml:link fixture sitemap](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-c/sitemap.xml): The XML sitemap that is the only channel declaring the reciprocal en/de alternates for the cluster C pages. - [Hreflang cluster C — Deutsch (sitemap channel)](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-c/de): The German member of a two-page cluster whose alternates exist only as xhtml:link entries in the cluster C fixture sitemap. - [Hreflang cluster C — English (sitemap channel)](https://crawler-test-site.uk.sitebulb.com/tests/international/cluster-c/en): The English member of a two-page cluster whose alternates exist only as xhtml:link entries in the cluster C fixture sitemap. ## international-sites - [Über Altona Travel](https://crawler-test-site.uk.sitebulb.com/intl/altona/de/about): Deutsch about page of the Altona Travel micro-site; member of the about hreflang cluster. - [Kontakt zur Redaktion](https://crawler-test-site.uk.sitebulb.com/intl/altona/de/contact): Deutsch contact page of the Altona Travel micro-site; member of the contact hreflang cluster. - [Küstenweg-Führer](https://crawler-test-site.uk.sitebulb.com/intl/altona/de/guide-coast): Deutsch guide-coast page of the Altona Travel micro-site; member of the guide-coast hreflang cluster. - [Bergtäler-Führer](https://crawler-test-site.uk.sitebulb.com/intl/altona/de/guide-mountains): Deutsch guide-mountains page of the Altona Travel micro-site; member of the guide-mountains hreflang cluster. - [Altona Travel — Reiseführer](https://crawler-test-site.uk.sitebulb.com/intl/altona/de): Deutsch home of the Altona Travel micro-site; member of the homepage hreflang cluster. - [About Altona Travel](https://crawler-test-site.uk.sitebulb.com/intl/altona/en/about): English about page of the Altona Travel micro-site; member of the about hreflang cluster. - [Contact the editors](https://crawler-test-site.uk.sitebulb.com/intl/altona/en/contact): English contact page of the Altona Travel micro-site; member of the contact hreflang cluster. - [Coast path guide](https://crawler-test-site.uk.sitebulb.com/intl/altona/en/guide-coast): English guide-coast page of the Altona Travel micro-site; member of the guide-coast hreflang cluster. - [Mountain valleys guide](https://crawler-test-site.uk.sitebulb.com/intl/altona/en/guide-mountains): English guide-mountains page of the Altona Travel micro-site; member of the guide-mountains hreflang cluster. - [Altona Travel — Travel guides](https://crawler-test-site.uk.sitebulb.com/intl/altona/en): English home of the Altona Travel micro-site; member of the homepage hreflang cluster. - [Sobre Altona Travel](https://crawler-test-site.uk.sitebulb.com/intl/altona/es/about): Español about page of the Altona Travel micro-site; member of the about hreflang cluster. - [Contacto con la redacción](https://crawler-test-site.uk.sitebulb.com/intl/altona/es/contact): Español contact page of the Altona Travel micro-site; member of the contact hreflang cluster. - [Guía del sendero costero](https://crawler-test-site.uk.sitebulb.com/intl/altona/es/guide-coast): Español guide-coast page of the Altona Travel micro-site; member of the guide-coast hreflang cluster. - [Guía de los valles de montaña](https://crawler-test-site.uk.sitebulb.com/intl/altona/es/guide-mountains): Español guide-mountains page of the Altona Travel micro-site; member of the guide-mountains hreflang cluster. - [Altona Travel — Guías de viaje](https://crawler-test-site.uk.sitebulb.com/intl/altona/es): Español home of the Altona Travel micro-site; member of the homepage hreflang cluster. - [À propos d'Altona Travel](https://crawler-test-site.uk.sitebulb.com/intl/altona/fr/about): Français about page of the Altona Travel micro-site; member of the about hreflang cluster. - [Contacter la rédaction](https://crawler-test-site.uk.sitebulb.com/intl/altona/fr/contact): Français contact page of the Altona Travel micro-site; member of the contact hreflang cluster. - [Guide du sentier côtier](https://crawler-test-site.uk.sitebulb.com/intl/altona/fr/guide-coast): Français guide-coast page of the Altona Travel micro-site; member of the guide-coast hreflang cluster. - [Guide des hautes vallées](https://crawler-test-site.uk.sitebulb.com/intl/altona/fr/guide-mountains): Français guide-mountains page of the Altona Travel micro-site; member of the guide-mountains hreflang cluster. - [Altona Travel — Guides de voyage](https://crawler-test-site.uk.sitebulb.com/intl/altona/fr): Français home of the Altona Travel micro-site; member of the homepage hreflang cluster. - [Altona Travel — Choose your language](https://crawler-test-site.uk.sitebulb.com/intl/altona): Language selector for the Altona Travel micro-site; serves as the homepage cluster x-default. - [Baltic (de) — Authentifizierung bei der Baltic API](https://crawler-test-site.uk.sitebulb.com/intl/baltic/de/authentication): The German authentication page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (de) — Baltic API Fehlerreferenz](https://crawler-test-site.uk.sitebulb.com/intl/baltic/de/errors): The German errors page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (de) — Baltic API Dokumentation](https://crawler-test-site.uk.sitebulb.com/intl/baltic/de): The German home page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (de) — Installation des Baltic-Clients](https://crawler-test-site.uk.sitebulb.com/intl/baltic/de/install): The German install page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (de) — localized endpoint reference PDF](https://crawler-test-site.uk.sitebulb.com/intl/baltic/de/reference.pdf): The German endpoint-reference PDF of the Baltic API Docs micro-site; hreflang annotations exist solely in the HTTP Link header. - [Baltic (en) — Authenticating with the Baltic API](https://crawler-test-site.uk.sitebulb.com/intl/baltic/en/authentication): The English authentication page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (en) — Baltic API error reference](https://crawler-test-site.uk.sitebulb.com/intl/baltic/en/errors): The English errors page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (en) — Baltic API documentation](https://crawler-test-site.uk.sitebulb.com/intl/baltic/en): The English home page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (en) — Installing the Baltic client](https://crawler-test-site.uk.sitebulb.com/intl/baltic/en/install): The English install page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (en) — localized endpoint reference PDF](https://crawler-test-site.uk.sitebulb.com/intl/baltic/en/reference.pdf): The English endpoint-reference PDF of the Baltic API Docs micro-site; hreflang annotations exist solely in the HTTP Link header. - [Baltic (fr) — Authentification auprès de l'API Baltic](https://crawler-test-site.uk.sitebulb.com/intl/baltic/fr/authentication): The French authentication page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (fr) — Référence des erreurs de l'API Baltic](https://crawler-test-site.uk.sitebulb.com/intl/baltic/fr/errors): The French errors page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (fr) — Documentation de l'API Baltic](https://crawler-test-site.uk.sitebulb.com/intl/baltic/fr): The French home page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (fr) — Installation du client Baltic](https://crawler-test-site.uk.sitebulb.com/intl/baltic/fr/install): The French install page of the Baltic API Docs micro-site; hreflang declared only via the HTTP Link header. - [Baltic (fr) — localized endpoint reference PDF](https://crawler-test-site.uk.sitebulb.com/intl/baltic/fr/reference.pdf): The French endpoint-reference PDF of the Baltic API Docs micro-site; hreflang annotations exist solely in the HTTP Link header. - [Alpinzelt — Corsica Outdoor DE](https://crawler-test-site.uk.sitebulb.com/intl/corsica/de-de/tents/alpine-tent): Corsica Outdoor de-DE alpine-tent page; its hreflang cluster is declared only in the site-local XML sitemap. - [Corsica Outdoor DE — Ausrüstung für Camping und Wandern](https://crawler-test-site.uk.sitebulb.com/intl/corsica/de-de): Corsica Outdoor de-DE home page; its hreflang cluster is declared only in the site-local XML sitemap. - [Zelte — Corsica Outdoor DE](https://crawler-test-site.uk.sitebulb.com/intl/corsica/de-de/tents): Corsica Outdoor de-DE tents page; its hreflang cluster is declared only in the site-local XML sitemap. - [Trekkingrucksack — Corsica Outdoor DE](https://crawler-test-site.uk.sitebulb.com/intl/corsica/de-de/tents/trail-pack): Corsica Outdoor de-DE trail-pack page; its hreflang cluster is declared only in the site-local XML sitemap. - [Alpine Tent — Corsica Outdoor UK](https://crawler-test-site.uk.sitebulb.com/intl/corsica/en-gb/tents/alpine-tent): Corsica Outdoor en-GB alpine-tent page; its hreflang cluster is declared only in the site-local XML sitemap. - [Corsica Outdoor UK — Camping and Hiking Kit](https://crawler-test-site.uk.sitebulb.com/intl/corsica/en-gb): Corsica Outdoor en-GB home page; its hreflang cluster is declared only in the site-local XML sitemap. - [Tents — Corsica Outdoor UK](https://crawler-test-site.uk.sitebulb.com/intl/corsica/en-gb/tents): Corsica Outdoor en-GB tents page; its hreflang cluster is declared only in the site-local XML sitemap. - [Trail Pack — Corsica Outdoor UK](https://crawler-test-site.uk.sitebulb.com/intl/corsica/en-gb/tents/trail-pack): Corsica Outdoor en-GB trail-pack page; its hreflang cluster is declared only in the site-local XML sitemap. - [Alpine Tent — Corsica Outdoor US](https://crawler-test-site.uk.sitebulb.com/intl/corsica/en-us/tents/alpine-tent): Corsica Outdoor en-US alpine-tent page; its hreflang cluster is declared only in the site-local XML sitemap. - [Corsica Outdoor US — Camping and Hiking Gear](https://crawler-test-site.uk.sitebulb.com/intl/corsica/en-us): Corsica Outdoor en-US home page; its hreflang cluster is declared only in the site-local XML sitemap. - [Tents — Corsica Outdoor US](https://crawler-test-site.uk.sitebulb.com/intl/corsica/en-us/tents): Corsica Outdoor en-US tents page; its hreflang cluster is declared only in the site-local XML sitemap. - [Trail Pack — Corsica Outdoor US](https://crawler-test-site.uk.sitebulb.com/intl/corsica/en-us/tents/trail-pack): Corsica Outdoor en-US trail-pack page; its hreflang cluster is declared only in the site-local XML sitemap. - [Darwin Journal — Klimanachrichten](https://crawler-test-site.uk.sitebulb.com/intl/darwin/de): The German home of the Darwin Journal micro-site; correct 4-way reciprocal home cluster. - [Wüsten wachsen und bedrohen Weideland](https://crawler-test-site.uk.sitebulb.com/intl/darwin/de/wuesten-wachsen): German target that declares the reciprocal en/de pair but canonicalises to its v2 URL. - [Wüsten wachsen — aktualisierte Ausgabe](https://crawler-test-site.uk.sitebulb.com/intl/darwin/de/wuesten-wachsen-v2): The self-canonical v2 article the deserts target canonicalises to; declares nothing (documented fallout). - [Desert spread threatens grasslands](https://crawler-test-site.uk.sitebulb.com/intl/darwin/en/desert-spread): English article whose declared German alternate canonicalises away to a v2 URL. - [Darwin Journal — Climate news](https://crawler-test-site.uk.sitebulb.com/intl/darwin/en): The English home of the Darwin Journal micro-site; correct 4-way reciprocal home cluster. - [Waldverlust setzt sich in den Tropen fort](https://crawler-test-site.uk.sitebulb.com/intl/darwin/blocked/wald-verlust): Robots-disallowed German target that declares the reciprocal en/de pair; contributes the blocked stanza. - [Forest loss continues in the tropics](https://crawler-test-site.uk.sitebulb.com/intl/darwin/en/forest-loss): English article whose declared German alternate sits on a robots-disallowed path. - [Darwin Journal — Actualités du climat](https://crawler-test-site.uk.sitebulb.com/intl/darwin/fr): The French home of the Darwin Journal micro-site; correct 4-way reciprocal home cluster. - [Glacier melt accelerates across the Alps](https://crawler-test-site.uk.sitebulb.com/intl/darwin/en/glacier-melt): English article declaring an en/fr pair whose French side never declares back. - [La fonte des glaciers s’accélère dans les Alpes](https://crawler-test-site.uk.sitebulb.com/intl/darwin/fr/fonte-des-glaciers): French article that declares only itself, omitting the English side of the glacier pair. - [Isole remote di fronte al cambiamento climatico](https://crawler-test-site.uk.sitebulb.com/intl/darwin/it/isole-remote): Indexable Italian article in an annotated section that carries no hreflang annotations at all. - [Darwin Journal — Notizie sul clima](https://crawler-test-site.uk.sitebulb.com/intl/darwin/it): The Italian home of the Darwin Journal micro-site; correct 4-way reciprocal home cluster. - [Ocean heat reaches new highs](https://crawler-test-site.uk.sitebulb.com/intl/darwin/en/ocean-heat): English article whose declared French alternate carries meta robots noindex. - [La chaleur des océans atteint des records](https://crawler-test-site.uk.sitebulb.com/intl/darwin/fr/chaleur-oceans): Noindexed French target that declares the reciprocal en/fr pair. - [Flüsse steigen nach Rekordregen](https://crawler-test-site.uk.sitebulb.com/intl/darwin/de/fluesse-steigen-neu): The 200 landing page of the rivers redirect; declares no annotations (documented fallout). - [Rivers rising after record rainfall](https://crawler-test-site.uk.sitebulb.com/intl/darwin/en/rivers-rising): English article whose declared German alternate answers with a 301 redirect. - [Vulkan-Beobachtung — Seite nicht gefunden](https://crawler-test-site.uk.sitebulb.com/intl/darwin/de/vulkan-beobachtung): The 404 German target nominated by the volcano article hreflang declaration. - [Volcano watch: new vents under observation](https://crawler-test-site.uk.sitebulb.com/intl/darwin/en/volcano-watch): English article whose declared German alternate returns HTTP 404. - [Echo App — switch languages without losing your thread](https://crawler-test-site.uk.sitebulb.com/intl/echo/anchor-attr): Carries zero head alternates; its body language switcher puts hreflang on an anchor tag. - [Echo App — feature comparison, referrer A](https://crawler-test-site.uk.sitebulb.com/intl/echo/conflict/ref-a): Declares de toward the conflict target and is fully reciprocal with it. - [Echo App — feature comparison, referrer B](https://crawler-test-site.uk.sitebulb.com/intl/echo/conflict/ref-b): Declares fr toward the conflict target, conflicting with ref-a and lacking a return tag. - [Echo App — Funktionsvergleich für Ihr Team](https://crawler-test-site.uk.sitebulb.com/intl/echo/conflict/target): German page that receives de from ref-a and fr from ref-b, creating conflicting incoming annotations. - [Echo App — Team-Messaging, das jeden Markt synchron hält](https://crawler-test-site.uk.sitebulb.com/intl/echo/de): Echo de home: the correct German counterpart of the en home, completing the control cluster. - [Echo App — choose your French edition](https://crawler-test-site.uk.sitebulb.com/intl/echo/dup-lang): Declares fr twice, once per French URL, alongside its own en self-reference. - [Echo App — édition française, bulletin concis](https://crawler-test-site.uk.sitebulb.com/intl/echo/dup-lang/fr-un): First French edition; fully reciprocal with the duplicate-language page. - [Echo App — édition française, récit complet](https://crawler-test-site.uk.sitebulb.com/intl/echo/dup-lang/fr-deux): Second French edition; fully reciprocal with the duplicate-language page. - [Echo App — one destination for two markets](https://crawler-test-site.uk.sitebulb.com/intl/echo/dup-url): Declares the same German target URL under both fr and de; the fr edge has no return tag. - [Echo App — Ihre Zielseite für den deutschen Markt](https://crawler-test-site.uk.sitebulb.com/intl/echo/dup-url/ziel): German target page that reciprocates only the de edge of the duplicate-URL declaration. - [Echo App — team messaging that keeps every market in sync](https://crawler-test-site.uk.sitebulb.com/intl/echo): Echo en home: correct reciprocal en/de pair with the German home; links every fault page on the site. - [Echo App — Sicherheit für regulierte Teams](https://crawler-test-site.uk.sitebulb.com/intl/echo/hreflang-no-lang/de): German counterpart of the pair, also without an html lang attribute. - [Echo App — security built for regulated teams](https://crawler-test-site.uk.sitebulb.com/intl/echo/hreflang-no-lang/en): Valid reciprocal en/de pair member whose html element carries no lang attribute. - [Echo App — supported languages](https://crawler-test-site.uk.sitebulb.com/intl/echo/invalid-codes): Self-referencing hreflang set that declares en plus the invalid values en-UK and english. - [Echo App — join the beta programme](https://crawler-test-site.uk.sitebulb.com/intl/echo/invalid-html-lang): The html lang attribute is the invalid value xx-XX and the page has no hreflang annotations. - [Echo App — regional rollouts, side A](https://crawler-test-site.uk.sitebulb.com/intl/echo/invalid-pair/a): Declares en for itself and the invalid code zz-AA toward its pair page. - [Echo App — regional rollouts, side B](https://crawler-test-site.uk.sitebulb.com/intl/echo/invalid-pair/b): Self-references under the invalid code zz-AA and points en back at its pair page, structurally reciprocal. - [Echo App — Lösungen für große Unternehmen](https://crawler-test-site.uk.sitebulb.com/intl/echo/lang-mismatch): German page with html lang de whose only hreflang declaration is an en self-reference. - [Echo App — pricing for the United Kingdom](https://crawler-test-site.uk.sitebulb.com/intl/echo/multi-self): Self-references twice, under en and en-GB. - [Echo App — Ihre Kanäle für unterwegs](https://crawler-test-site.uk.sitebulb.com/intl/echo/no-canonical/de): German counterpart of the missing-canonical pair, served with a normal self-canonical. - [Echo App — take your channels mobile](https://crawler-test-site.uk.sitebulb.com/intl/echo/no-canonical/en): Valid reciprocal en/de pair member served without a rel=canonical declaration. - [Echo App — changelog](https://crawler-test-site.uk.sitebulb.com/intl/echo/no-html-lang): The html element carries no lang attribute and the page has no hreflang annotations. - [Echo App — integrations that meet you where you work](https://crawler-test-site.uk.sitebulb.com/intl/echo/relative): Both hreflang hrefs are root-relative instead of absolute. - [Echo App — Integrationen für Ihren Arbeitsalltag](https://crawler-test-site.uk.sitebulb.com/intl/echo/relative/de): German counterpart that declares correct absolute hrefs back at the relative page. - [Echo App — about the company](https://crawler-test-site.uk.sitebulb.com/intl/echo/unannotated): Plain indexable English page in the site navigation with no hreflang annotations. - [Okonomiyaki — Fuji Kitchen (UK)](https://crawler-test-site.uk.sitebulb.com/intl/fuji/casing/a): Declares its own value with non-canonical casing EN-GB; the pair must unify into one valid cluster. - [Okonomiyaki — Fuji Kitchen (US)](https://crawler-test-site.uk.sitebulb.com/intl/fuji/casing/b): Refers to its partner with the lowercase-region value en-gb; case-insensitive values, zero invalid-code issues. - [Ramen shoyu — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/dual-conflict/fr-tete): Reciprocates the head-channel fr edge of the dual-conflict page via head links. - [Ramen shoyu (entête) — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/dual-conflict/fr-entete): Reciprocates the header-channel fr edge of the dual-conflict page via head links. - [Shoyu Ramen — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/dual-conflict): Head links and the Link header agree on en but map fr to two different URLs — the deliberate cross-channel duplicate. - [Miso Soup — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/dual-consistent/en): Declares the identical en/ja set in both head links and the HTTP Link header; consistent sets, multiple channels. - [味噌汁 — フジキッチン](https://crawler-test-site.uk.sitebulb.com/intl/fuji/dual-consistent/ja): The Japanese member of the dual-channel consistent cluster; head links and Link header carry the same set. - [Fuji Kitchen — Japanese Home Cooking](https://crawler-test-site.uk.sitebulb.com/intl/fuji/en): The Fuji Kitchen entry page; correct reciprocal en/ja head-link pair and links to every edge-case page. - [Sushi Rolls — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/external): Declares en (self) plus a de alternate on the external domain https://example.com/ — the documented hreflang exit. - [フジキッチン — 日本の家庭料理](https://crawler-test-site.uk.sitebulb.com/intl/fuji/ja): The Japanese homepage; the reciprocal partner of the en entry page. - [Matcha-Kekse — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/de): The de member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [Matcha Cookies — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/en): The en member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [Galletas de matcha — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/es): The es member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [Biscuits au matcha — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/fr): The fr member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [Biscotti al matcha — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/it): The it member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [抹茶クッキー — フジキッチン](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/ja): The ja member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [말차 쿠키 — 후지 키친](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/ko): The ko member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [Matchakoekjes — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/nl): The nl member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [Ciasteczka matcha — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/pl): The pl member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [Biscoitos de matcha — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/large/pt-br): The pt-BR member of the ten-locale fully reciprocal large cluster; ten head-link annotations, zero expected issues. - [Gyoza — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/mixed-xd/en): The en/fr pair member that carries both the en annotation and the x-default annotation pointing at itself. - [Gyoza — Fuji Kitchen (FR)](https://crawler-test-site.uk.sitebulb.com/intl/fuji/mixed-xd/fr): The French counterpart; declares the same set, including x-default pointing at the en URL. - [كاتسو كاري — مطبخ فوجي](https://crawler-test-site.uk.sitebulb.com/intl/fuji/rtl/ar): Arabic RTL member of the reciprocal pair; html lang ar with dir rtl and genuinely Arabic content. - [Katsu Curry — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/rtl/en): The en member of the correct en/ar pair whose Arabic counterpart is an RTL document. - [Japanese Fried Rice — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/script/en): The en member of the script-subtag cluster pairing zh-Hans and zh-Hant; valid codes, zero expected issues. - [日式炒饭 — 富士厨房](https://crawler-test-site.uk.sitebulb.com/intl/fuji/script/zh-hans): Simplified Chinese member of the script-subtag cluster; html lang zh-Hans. - [日式炒飯 — 富士廚房](https://crawler-test-site.uk.sitebulb.com/intl/fuji/script/zh-hant): Traditional Chinese member of the script-subtag cluster; html lang zh-Hant. - [Tempura — Fuji Kitchen](https://crawler-test-site.uk.sitebulb.com/intl/fuji/sitemap-head/en): Declares the identical en/ja set in head links and in the site-local sitemap xhtml:link entries. - [天ぷら — フジキッチン](https://crawler-test-site.uk.sitebulb.com/intl/fuji/sitemap-head/ja): The Japanese member of the head-plus-sitemap dual-channel cluster. ## javascript-rendering - [All body text rendered by JavaScript](https://crawler-test-site.uk.sitebulb.com/tests/javascript/proof/body-text-only-js): The raw body carries only the raw marker; every visible sentence is created by JavaScript. - [All links rendered by JavaScript](https://crawler-test-site.uk.sitebulb.com/tests/javascript/proof/links-only-js): The raw body carries only the raw marker; both anchors are built at runtime from path fragments. - [Canonical inserted by JavaScript](https://crawler-test-site.uk.sitebulb.com/tests/javascript/metadata/canonical): An inline script inserts a self-referencing canonical link element after load. - [Content delayed by 2000ms](https://crawler-test-site.uk.sitebulb.com/tests/javascript/delays/2000ms): A setTimeout of exactly 2000ms appends the rendered marker and delayed content. - [Content delayed by 500ms](https://crawler-test-site.uk.sitebulb.com/tests/javascript/delays/500ms): A setTimeout of exactly 500ms appends the rendered marker and delayed content. - [Meta description inserted by JavaScript](https://crawler-test-site.uk.sitebulb.com/tests/javascript/metadata/description): An inline script inserts a meta description reading JS rendered description after load. - [Content via document.write](https://crawler-test-site.uk.sitebulb.com/tests/javascript/content/document-write): An inline script document.writes the rendered marker and visible content during parse. - [Content loaded over fetch](https://crawler-test-site.uk.sitebulb.com/tests/javascript/content/fetch-loaded): An inline script fetches the fetch-data helper JSON and renders its payload plus the rendered marker. - [Content via innerHTML](https://crawler-test-site.uk.sitebulb.com/tests/javascript/content/inner-html): An inline script assigns innerHTML to inject the rendered marker and visible content. - [Content revealed by IntersectionObserver](https://crawler-test-site.uk.sitebulb.com/tests/javascript/events/intersection-observer): A sentinel div far below the fold triggers an IntersectionObserver that appends the rendered marker. - [JSON-LD injected by JavaScript](https://crawler-test-site.uk.sitebulb.com/tests/javascript/metadata/json-ld): An inline script appends an application/ld+json Article block to the head after load. - [Content inside an open shadow root](https://crawler-test-site.uk.sitebulb.com/tests/javascript/shadow-dom/open): An inline script attaches an open shadow root whose runtime-built text is the rendered marker. - [SPA shell hydration](https://crawler-test-site.uk.sitebulb.com/tests/javascript/spa/hydration-control): The raw HTML serves an app shell placeholder; an inline script hydrates it with content and the rendered marker. - [Content via textContent](https://crawler-test-site.uk.sitebulb.com/tests/javascript/content/text-content): An inline script creates elements and sets textContent to inject the rendered marker. - [Title changed by JavaScript](https://crawler-test-site.uk.sitebulb.com/tests/javascript/metadata/title): An inline script changes document.title to JS Rendered Title after load. ## links - [Anchor injected from an AJAX response](https://crawler-test-site.uk.sitebulb.com/tests/links/javascript/ajax-loaded): Inline script fetches a JSON helper and injects the anchor it describes. - [Base href changes link resolution](https://crawler-test-site.uk.sitebulb.com/tests/links/base-href): A base element redirects relative anchor resolution into the targets directory. - [Anchors inside a comment and a template](https://crawler-test-site.uk.sitebulb.com/tests/links/hidden/comment-template): Anchor markup inside an HTML comment and a template element, neither a live link. - [data-href span](https://crawler-test-site.uk.sitebulb.com/tests/links/nonstandard/data-href): A span carrying the URL in a data-href attribute instead of an anchor. - [Empty and broken anchors](https://crawler-test-site.uk.sitebulb.com/tests/links/empty-and-broken): Anchors with empty, missing, whitespace-only, and scheme-only hrefs. - [Follow and nofollow anchors to the same target](https://crawler-test-site.uk.sitebulb.com/tests/links/nofollow/same-target-conflict): Two anchors to one target: one followed, one rel="nofollow". - [Same-domain iframe](https://crawler-test-site.uk.sitebulb.com/tests/links/iframes/same-domain): A page embedding a same-site iframe whose document carries one internal anchor. - [Image-wrapped anchor](https://crawler-test-site.uk.sitebulb.com/tests/links/image-link): An anchor whose only content is an inline SVG image. - [Anchor href built by string concatenation](https://crawler-test-site.uk.sitebulb.com/tests/links/javascript/string-concat): Inline script concatenates path fragments and injects the anchor after load. - [Nested anchors](https://crawler-test-site.uk.sitebulb.com/tests/links/malformed/nested-anchors): Deliberately invalid markup nesting one anchor inside another. - [rel=nofollow anchor](https://crawler-test-site.uk.sitebulb.com/tests/links/nofollow/basic): A single internal anchor carrying rel="nofollow". - [Anchor inside noscript](https://crawler-test-site.uk.sitebulb.com/tests/links/hidden/noscript): The only anchor on the page lives inside a noscript element. - [pushState navigation](https://crawler-test-site.uk.sitebulb.com/tests/links/javascript/pushstate): A SPA-style anchor whose click handler mutates the URL with history.pushState. - [Relative, root-relative, and protocol-relative anchors](https://crawler-test-site.uk.sitebulb.com/tests/links/url-forms): Three URL forms that all resolve to real target pages. - [Anchor inside an open shadow root](https://crawler-test-site.uk.sitebulb.com/tests/links/shadow-dom/open): Inline script attaches an open shadow root containing the only anchor. - [Standard external anchor](https://crawler-test-site.uk.sitebulb.com/tests/links/standard/external): A single anchor leaving the fixture site for the controlled external target. - [Standard internal anchors](https://crawler-test-site.uk.sitebulb.com/tests/links/standard/internal): Two plain internal anchors pointing at real 200 target pages. - [Link target A](https://crawler-test-site.uk.sitebulb.com/tests/links/targets/target-a): A real 200 page that link fixtures in this group point at (target a). - [Link target B](https://crawler-test-site.uk.sitebulb.com/tests/links/targets/target-b): A real 200 page that link fixtures in this group point at (target b). - [Link target C](https://crawler-test-site.uk.sitebulb.com/tests/links/targets/target-c): A real 200 page that link fixtures in this group point at (target c). - [rel=ugc sponsored anchor](https://crawler-test-site.uk.sitebulb.com/tests/links/nofollow/ugc-sponsored): A single internal anchor carrying rel="ugc sponsored". - [Whitespace and percent-encoded hrefs](https://crawler-test-site.uk.sitebulb.com/tests/links/url-edge-cases): Anchors with surrounding whitespace, a percent-encoded path, and an entity-encoded query. ## loading - [Delayed blocking stylesheet asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/blocking.css): Serves 1,024 bytes of minified CSS after a fixed 200ms delay, under the 2,048-byte unused-code floor. - [Delayed blocking script asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/blocking.js): Serves 1,024 bytes of minified JavaScript after a fixed 200ms delay, under the 2,048-byte unused-code floor. - [FOIT webfont asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/foit.ttf): Committed TrueType font of exactly 24,576 bytes for the no-font-display fixture. - [Webfont asset 1 of 6](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/many-1.ttf): Committed TrueType font of exactly 24,576 bytes with distinct per-family content. - [Webfont asset 2 of 6](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/many-2.ttf): Committed TrueType font of exactly 24,576 bytes with distinct per-family content. - [Webfont asset 3 of 6](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/many-3.ttf): Committed TrueType font of exactly 24,576 bytes with distinct per-family content. - [Webfont asset 4 of 6](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/many-4.ttf): Committed TrueType font of exactly 24,576 bytes with distinct per-family content. - [Webfont asset 5 of 6](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/many-5.ttf): Committed TrueType font of exactly 24,576 bytes with distinct per-family content. - [Webfont asset 6 of 6](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/many-6.ttf): Committed TrueType font of exactly 24,576 bytes with distinct per-family content. - [Overweight webfont asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/overweight.ttf): Committed TrueType font of exactly 61,440 bytes (60KB), above the 50KB per-font threshold. - [FOIT stylesheet asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/foit.css): Committed minified CSS declaring one font face with no font-display descriptor plus one class rule. - [Six-webfont stylesheet asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/many.css): Committed minified CSS declaring six font-display:swap font faces plus six class rules; passes the font-display check. - [Overweight-webfont stylesheet asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/fonts/overweight.css): Committed minified CSS declaring one font-display:swap font face plus one class rule. - [Late critical CSS stylesheet asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/late.css): Committed 512-byte minified stylesheet whose rules the critical-css-late page uses; too small to trip any size or coverage hint. - [Print-only stylesheet asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/print.css): Committed 512-byte print-only stylesheet; the PrintStyleSheets hint is recorded on this CSS resource with IsPrint = true. - [Synchronous script asset 1 of 5](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/sync-1.js): Committed 64-byte one-line script with distinct numbered content so duplicate-resource families never match it. - [Synchronous script asset 2 of 5](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/sync-2.js): Committed 64-byte one-line script with distinct numbered content so duplicate-resource families never match it. - [Synchronous script asset 3 of 5](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/sync-3.js): Committed 64-byte one-line script with distinct numbered content so duplicate-resource families never match it. - [Synchronous script asset 4 of 5](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/sync-4.js): Committed 64-byte one-line script with distinct numbered content so duplicate-resource families never match it. - [Synchronous script asset 5 of 5](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/sync-5.js): Committed 64-byte one-line script with distinct numbered content so duplicate-resource families never match it. - [Unused-CSS coverage bundle asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/unused-bulk.css): Committed 20,480-byte minified stylesheet: 20 used rules and 180 rules targeting classes that appear nowhere. - [Unused-JavaScript coverage bundle asset](https://crawler-test-site.uk.sitebulb.com/tests/loading/assets/unused-bulk.js): Committed 20,480-byte minified script: one invoked init function and 40 dead functions. - [Critical CSS present but after stylesheet links](https://crawler-test-site.uk.sitebulb.com/tests/loading/head/critical-css-late): The head links an external stylesheet first and only then carries its inline critical style block; no head scripts. - [Print stylesheet download](https://crawler-test-site.uk.sitebulb.com/tests/loading/head/print-stylesheet): The head links a media="print" stylesheet after an inline-first style block, so only the print signal is present. - [Render-blocking head resources](https://crawler-test-site.uk.sitebulb.com/tests/loading/head/render-blocking): Head loads a synchronous 200ms-delayed script then a 200ms-delayed stylesheet, with no inline critical CSS anywhere. - [Single point of failure — delayed cross-origin script](https://crawler-test-site.uk.sitebulb.com/tests/loading/head/spof-delayed-origin): The head synchronously loads a script from the protocol-edge origin that answers only after a fixed 5s delay. - [Single point of failure — external head script](https://crawler-test-site.uk.sitebulb.com/tests/loading/head/spof-external): The head synchronously loads a third-party script from example.com with no async, defer, integrity, or crossorigin. - [Too many synchronous head scripts](https://crawler-test-site.uk.sitebulb.com/tests/loading/head/sync-scripts): The head loads five synchronous scripts with no async or defer; each asset is 64 bytes so only the sync count fires. - [Unused CSS via Chrome coverage](https://crawler-test-site.uk.sitebulb.com/tests/loading/coverage/unused-css): Links a committed 20,480-byte stylesheet where 20 rules match page classes and 180 rules match nothing, ~90% unused. - [Unused JavaScript via Chrome coverage](https://crawler-test-site.uk.sitebulb.com/tests/loading/coverage/unused-js): Defers a committed 20,480-byte script whose init path runs and writes the rendered marker while 40 functions stay dead. - [Webfont with no font-display](https://crawler-test-site.uk.sitebulb.com/tests/loading/fonts/foit): Links a stylesheet whose single font face omits font-display entirely, so text is invisible during the default block period. - [Overweight webfont](https://crawler-test-site.uk.sitebulb.com/tests/loading/fonts/overweight): Links a stylesheet declaring one font-display:swap font face whose file is exactly 61,440 bytes, above the 50KB threshold. - [Too many webfonts](https://crawler-test-site.uk.sitebulb.com/tests/loading/fonts/too-many): Links a stylesheet declaring six font-display:swap font faces, each applied to visible text so all six fonts download. ## mobile-responsive - [AMP relationship — canonical source](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/amp-canonical-source): An ordinary HTML article advertising its AMP page via rel="amphtml" with a self-referencing canonical. - [AMP relationship — AMP page](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/amp-page): An AMP-flavoured page flagged with the amp and lightning html attributes, declaring the source article as canonical. - [CSS media-query visibility markers](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/css-media-query-marker): Two markers both present in the raw HTML; a 640px-breakpoint stylesheet makes exactly one visible per viewport width. - [Dynamic serving with Vary on User-Agent](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/dynamic-serving-vary-user-agent): The base dynamic-serving fixture; the UA token Mobile selects the mobile body, otherwise desktop, always with Vary on User-Agent. - [Alternate mobile URL — desktop page](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/mobile-alternate-desktop): The desktop half of a separate-mobile-URL pair, annotating its mobile alternate and self-referencing canonical. - [Alternate mobile URL — mobile page](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/mobile-alternate-mobile): The mobile half of the separate-mobile-URL pair, declaring the desktop URL as canonical. - [Dynamic serving — H1 differs per variant](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/mobile-h1-different): UA-switched fixture whose H1 text differs between variants while title and links stay identical. - [Dynamic serving — outbound links differ per variant](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/mobile-outbound-links-different): UA-switched fixture linking five fixture routes on the desktop variant and only the first two on the mobile variant. - [Dynamic serving — title differs per variant](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/mobile-title-different): UA-switched fixture whose title differs between the desktop and mobile variants while the bodies otherwise match. - [Dynamic serving — word count differs per variant](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/mobile-word-count-different): UA-switched fixture serving 200 words of fixed copy to desktop UAs and the first 50 words to mobile UAs. - [Responsive single URL](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/responsive-single-url): One URL serving byte-identical responsive HTML to every User-Agent, with a valid viewport meta and a media-query stylesheet. - [Undersized touch targets](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/touch-target-marker): Two adjacent links each styled to exactly 24x24px with a 4px gap, an undersized-tap-target sample. - [Viewport meta invalid](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/viewport-invalid): An HTML page with a viewport meta whose content is the unparseable value wibble. - [Viewport meta missing](https://crawler-test-site.uk.sitebulb.com/tests/mobile-responsive/viewport-missing): An HTML page whose head contains no viewport meta tag at all. ## non-html-resources - [Broken resource references](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-404-file-reference): An HTML page referencing one missing image and one missing stylesheet, both registered 404 targets. - [Missing image target](https://crawler-test-site.uk.sitebulb.com/tests/non-html/missing/sb-fixture-missing.png): A deliberately missing image URL registered so the broken reference is a validated 404 fixture. - [Missing stylesheet target](https://crawler-test-site.uk.sitebulb.com/tests/non-html/missing/sb-fixture-missing.css): A deliberately missing stylesheet URL registered so the broken reference is a validated 404 fixture. - [Atom feed](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-atom.xml): A minimal valid Atom feed whose two entry links are absolute URLs to the same feed-item target pages as the RSS variant. - [CSV resource](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-csv.csv): A committed CSV of one header row and two data rows, one data cell carrying the fixture marker. - [Download attachment disposition](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-download-content-disposition): A plain-text body served with Content-Disposition attachment and an explicit download filename. - [Feed item target — one](https://crawler-test-site.uk.sitebulb.com/tests/non-html/feed-items/one): A plain HTML page reachable only via a feed link or the manifest, proving feed-based discovery. - [Feed item target — two](https://crawler-test-site.uk.sitebulb.com/tests/non-html/feed-items/two): The second plain HTML feed-item target page, excluded from every sitemap like the first. - [Image embedded from HTML](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-image-linked-from-html): An HTML page embedding the committed PNG via an img element with alt text. - [PNG image resource](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-image-png.png): A committed 64x64 PNG under 1 KB whose fixture marker lives in a tEXt chunk, discoverable only via the embedding page. - [JSON resource](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-json.json): A committed JSON document whose body is exactly one object with a single fixture property. - [PDF resource — basic](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-pdf-basic.pdf): A committed one-page PDF whose page text carries the fixture marker, served with no robots directives. - [PDF resource — X-Robots-Tag noindex](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-pdf-x-robots-noindex.pdf): An endpoint serving the committed basic-PDF bytes with an added X-Robots-Tag noindex header. - [Range request file](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-range-request-file.bin): A generated 1,048,576-byte octet-stream supporting partial content: 206 for valid ranges and 416 beyond EOF. - [Redirect to a PDF resource](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-redirect-to-pdf): A 302 whose single hop lands on the committed basic PDF rather than an HTML page. - [RSS 2.0 feed](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-rss.xml): A minimal valid RSS 2.0 feed whose two item links are absolute URLs to the registered feed-item target pages. - [Plain text resource](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-text-plain.txt): A committed UTF-8 text file carrying the fixture marker on its own line. - [Unknown MIME type](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-unknown-mime): A small text body served with the unregistered content type application/x-sitebulb-fixture. - [Wrong content type](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-wrong-content-type): The committed PNG bytes served with Content-Type text/html, so the declared type and the actual bytes deliberately disagree. - [Generic XML resource](https://crawler-test-site.uk.sitebulb.com/tests/non-html/resource-xml.xml): A committed XML document with a single root element carrying the fixture marker attribute, neither a feed nor a sitemap. ## pagination - [Pagination canonical-to-page-1 series — page 1 of 5](https://crawler-test-site.uk.sitebulb.com/tests/pagination/all-canonical-page-1/page-1): Page 1 of a five-page series in which the deeper pages all canonicalise to page 1; page 1 is self-canonical. - [Pagination duplicate-content series — page 1 of 5](https://crawler-test-site.uk.sitebulb.com/tests/pagination/duplicate/page-1): Page 1 of a five-page series in which pages 2 and 3 share a byte-identical item-list block. - [Pagination empty-final series — page 4 of 4](https://crawler-test-site.uk.sitebulb.com/tests/pagination/empty-final/page-4): Final page of the empty-final series: a 200 HTML page with zero items, the empty marker, and a prev anchor only. - [Pagination empty-final series — page 1 of 4](https://crawler-test-site.uk.sitebulb.com/tests/pagination/empty-final/page-1): Page 1 of a four-page series whose final page serves 200 with zero items. - [Pagination — infinite scroll without URL updates](https://crawler-test-site.uk.sitebulb.com/tests/pagination/infinite-scroll-no-url-updates): Scrolling near the bottom appends a ten-item batch while the URL never changes, hard-capped at five batches. - [Pagination — infinite scroll with URL updates](https://crawler-test-site.uk.sitebulb.com/tests/pagination/infinite-scroll-url-updates): Scrolling near the bottom appends a ten-item batch and pushState-updates the URL to ?batch={n}, hard-capped at five batches. - [Pagination large-range boundary hub](https://crawler-test-site.uk.sitebulb.com/tests/pagination/large-range): One page rendering numbered anchors 1 to 50 into the parameterised large-range endpoint; 50 is the hard cap. - [Pagination — load-more button](https://crawler-test-site.uk.sitebulb.com/tests/pagination/load-more-button): A button appends a ten-item batch per click up to five batches in total; the button is removed after the last batch. - [Pagination noindex series — page 2 of 3](https://crawler-test-site.uk.sitebulb.com/tests/pagination/noindex/page-2): Page 2 of the noindex series carrying a meta robots noindex while its anchors stay followable. - [Pagination noindex series — page 1 of 3](https://crawler-test-site.uk.sitebulb.com/tests/pagination/noindex/page-1): Page 1 of a three-page series whose middle page is noindexed; page 1 carries no robots meta. - [Pagination classic series — page 1 of 5](https://crawler-test-site.uk.sitebulb.com/tests/pagination/classic/page-1): Page 1 of a five-page anchor-linked series with ten items, a next anchor, no prev anchor, and no canonical. - [Pagination classic series — page 2 of 5](https://crawler-test-site.uk.sitebulb.com/tests/pagination/classic/page-2): Page 2 of the classic series with prev and next anchors to pages 1 and 3. - [Pagination classic series — page 3 of 5](https://crawler-test-site.uk.sitebulb.com/tests/pagination/classic/page-3): Page 3 of the classic series with prev and next anchors to pages 2 and 4. - [Pagination rel-next/prev series — page 1 of 5](https://crawler-test-site.uk.sitebulb.com/tests/pagination/rel/page-1): Page 1 of a five-page series whose head declares a rel-next link only, alongside the visible anchors. - [Pagination self-canonical series — page 1 of 5](https://crawler-test-site.uk.sitebulb.com/tests/pagination/self-canonical/page-1): Page 1 of a five-page series in which every page declares its own absolute URL as canonical. - [Pagination sitemap-only series — page 3 of 3](https://crawler-test-site.uk.sitebulb.com/tests/pagination/sitemap-only/page-3): Final page of the sitemap-only series, listed in the pagination scenario sitemap and linked from nowhere. - [Pagination sitemap-only series — page 1 of 3](https://crawler-test-site.uk.sitebulb.com/tests/pagination/sitemap-only/page-1): Page 1 of a three-page series whose final page is discoverable only via the pagination scenario sitemap. ## redirects - [Redirect chain — ends in 404](https://crawler-test-site.uk.sitebulb.com/tests/redirects/chains/ends-404): A 301 whose target deliberately returns HTTP 404. - [Redirect chain — ends in 410](https://crawler-test-site.uk.sitebulb.com/tests/redirects/chains/ends-410): A 301 whose target deliberately returns HTTP 410 Gone. - [Redirect chain — five hops](https://crawler-test-site.uk.sitebulb.com/tests/redirects/chains/five-hop): Five consecutive 301 redirects before the final 200 target, long enough to probe depth limits. - [Redirect chain — robots-disallowed final URL](https://crawler-test-site.uk.sitebulb.com/tests/redirects/chains/robots-disallowed-final): A 301 whose final URL is disallowed by robots.txt while still serving HTTP 200 content. - [Redirect chain — robots-disallowed middle hop](https://crawler-test-site.uk.sitebulb.com/tests/redirects/chains/robots-disallowed-middle): A 301 through a robots-disallowed intermediate hop that redirects on to the final 200 target. - [Redirect chain — three mixed hops](https://crawler-test-site.uk.sitebulb.com/tests/redirects/chains/three-hop-mixed): A 301, then a 302, then a 301 before landing on the final 200 target. - [Redirect chain — two hops of 301](https://crawler-test-site.uk.sitebulb.com/tests/redirects/chains/two-hop-301): A 301 to a helper hop that 301s again before landing on the final 200 target. - [Redirect edge — absolute same-site URL](https://crawler-test-site.uk.sitebulb.com/tests/redirects/edge/absolute-url): A 301 whose Location header is the absolute primary-site URL of the final 200 target. - [Redirect edge — fragment in Location](https://crawler-test-site.uk.sitebulb.com/tests/redirects/edge/fragment): A 301 whose Location header carries a URL fragment a crawler must normalise. - [Redirect edge — HTTP Refresh header](https://crawler-test-site.uk.sitebulb.com/tests/redirects/edge/http-refresh-header): An HTTP 200 response carrying a non-standard Refresh header pointing at the final 200 target. - [Redirect edge — PDF target](https://crawler-test-site.uk.sitebulb.com/tests/redirects/edge/pdf-target): A 302 whose target is a PDF resource rather than an HTML page. - [Redirect edge — query preservation](https://crawler-test-site.uk.sitebulb.com/tests/redirects/edge/query-preservation?source=redirects&keep=1): A 302 that echoes the incoming query string onto the final 200 target. - [JavaScript redirect — SPA pushState](https://crawler-test-site.uk.sitebulb.com/tests/redirects/javascript/spa-pushstate): An HTTP 200 page whose script mutates the URL via history.pushState without any network redirect. - [JavaScript redirect — window.location.href](https://crawler-test-site.uk.sitebulb.com/tests/redirects/javascript/window-location-href): An HTTP 200 page whose inline script assigns window.location.href to the final 200 target on load. - [JavaScript redirect — window.location.replace](https://crawler-test-site.uk.sitebulb.com/tests/redirects/javascript/window-location-replace): An HTTP 200 page whose inline script calls window.location.replace with the final 200 target on load. - [Meta refresh — delayed 5s](https://crawler-test-site.uk.sitebulb.com/tests/redirects/meta/delayed-5s): An HTTP 200 page whose meta refresh waits five seconds before pointing at the final 200 target. - [Meta refresh — immediate](https://crawler-test-site.uk.sitebulb.com/tests/redirects/meta/immediate): An HTTP 200 page whose meta refresh points immediately at the final 200 target. - [Redirect 301 Moved Permanently](https://crawler-test-site.uk.sitebulb.com/tests/redirects/standard/301): Returns a raw HTTP 301 (Moved Permanently) pointing at the final 200 target page. - [Redirect 302 Found](https://crawler-test-site.uk.sitebulb.com/tests/redirects/standard/302): Returns a raw HTTP 302 (Found) pointing at the final 200 target page. - [Redirect 303 See Other](https://crawler-test-site.uk.sitebulb.com/tests/redirects/standard/303): Returns a raw HTTP 303 (See Other) pointing at the final 200 target page. - [Redirect 307 Temporary Redirect](https://crawler-test-site.uk.sitebulb.com/tests/redirects/standard/307): Returns a raw HTTP 307 (Temporary Redirect) pointing at the final 200 target page. - [Redirect 308 Permanent Redirect](https://crawler-test-site.uk.sitebulb.com/tests/redirects/standard/308): Returns a raw HTTP 308 (Permanent Redirect) pointing at the final 200 target page. - [Redirect target — final 200](https://crawler-test-site.uk.sitebulb.com/tests/redirects/targets/final-200): The shared 200 HTML landing page every safe redirect fixture in this group resolves to. - [Redirect target — PDF resource](https://crawler-test-site.uk.sitebulb.com/tests/redirects/resources/redirect-target.pdf): A minimal valid PDF served as the non-HTML landing resource for the pdf-target redirect. ## robots-protocol - [Root robots.txt — HTTP 404](https://crawler-test-site.uk.sitebulb.com/robots.txt): An origin with no robots.txt; the request returns HTTP 404. - [Root robots.txt — UTF-8 BOM](https://crawler-test-site.uk.sitebulb.com/robots.txt): A robots.txt whose body begins with a UTF-8 byte-order mark. - [Root robots.txt — Crawl-delay variants](https://crawler-test-site.uk.sitebulb.com/robots.txt): A robots.txt declaring Crawl-delay values of 0, 1, and 10 across user-agent groups. - [Meta robots — body placement is ignored](https://crawler-test-site.uk.sitebulb.com/tests/robots/meta/body-placement): An HTML page whose only robots meta tag sits inside the body, where it has no effect. - [Meta robots — bot-specific googlebot tag](https://crawler-test-site.uk.sitebulb.com/tests/robots/meta/bot-specific-googlebot): An HTML page declaring noindex only for googlebot via a bot-named meta tag. - [Meta robots — conflicting tags](https://crawler-test-site.uk.sitebulb.com/tests/robots/meta/conflicting-tags): An HTML page with two meta robots tags declaring contradictory noindex and index directives. - [Meta robots — combined nofollow, none, noarchive](https://crawler-test-site.uk.sitebulb.com/tests/robots/meta/directives): An HTML page combining nofollow, none, and noarchive in one meta robots tag. - [Meta robots — noindex](https://crawler-test-site.uk.sitebulb.com/tests/robots/meta/noindex): An HTML page declaring meta robots noindex in its head. - [Meta robots — uppercase NOINDEX](https://crawler-test-site.uk.sitebulb.com/tests/robots/meta/uppercase-noindex): An HTML page declaring meta robots NOINDEX in uppercase; directives are case-insensitive. - [Root robots.txt — multiple user-agent groups](https://crawler-test-site.uk.sitebulb.com/robots.txt): A robots.txt with several user-agent groups so crawlers must pick the most specific. - [Root robots.txt — redirect before content](https://crawler-test-site.uk.sitebulb.com/robots.txt): A robots.txt that 301-redirects once before serving its content. - [Root robots.txt — allow all](https://crawler-test-site.uk.sitebulb.com/robots.txt): An origin whose robots.txt permits every user agent everywhere. - [Root robots.txt — Allow overrides Disallow](https://crawler-test-site.uk.sitebulb.com/robots.txt): A robots.txt mixing a broad Disallow with a more specific Allow override. - [Root robots.txt — blank Disallow](https://crawler-test-site.uk.sitebulb.com/robots.txt): A robots.txt whose Disallow value is blank, which means allow all. - [Root robots.txt — valid and missing sitemap references](https://crawler-test-site.uk.sitebulb.com/robots.txt): A robots.txt referencing one resolvable sitemap and one that returns 404. - [Root robots.txt — wildcard and end-anchor patterns](https://crawler-test-site.uk.sitebulb.com/robots.txt): A robots.txt using * wildcards and $ end anchors in its rules. - [X-Robots-Tag — noindex on HTML](https://crawler-test-site.uk.sitebulb.com/tests/robots/x-robots/html-noindex): An HTML response carrying an X-Robots-Tag: noindex header. - [X-Robots-Tag — noindex on PDF](https://crawler-test-site.uk.sitebulb.com/tests/robots/x-robots/pdf-noindex): A minimal generated PDF carrying an X-Robots-Tag: noindex header. ## sitemaps - [Gzipped sitemap file](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/gzip-sitemap.xml.gz): A gzipped single-URL urlset served as application/gzip with no Content-Encoding header. - [Hreflang sitemap](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/hreflang-sitemap.xml): A urlset carrying reciprocal en/de xhtml:link alternates for two pages. - [Image extension sitemap](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/image-sitemap.xml): A urlset using the Google image 1.1 extension to associate one image with one page. - [News extension sitemap](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/news-sitemap.xml): A urlset using the Google news 0.9 extension with a frozen publication date. - [Sitemap listing a noindex URL](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/noindex-url.xml): A valid single-URL sitemap whose loc carries a meta robots noindex. - [Sitemap listing a non-canonical URL](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/non-canonical-url.xml): A valid single-URL sitemap whose loc canonicalises to a different page. - [Sitemap absent from robots.txt](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/not-referenced-in-robots.xml): A valid single-URL sitemap that contributes no robots.txt line, so it never surfaces via robots auto-discovery. - [Broken sitemap reference in robots.txt](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/robots-referenced-404.xml): A robots.txt Sitemap line pointing at this path, which returns 404 instead of XML. - [Sample sitemap image asset](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/assets/sample-image.png): The committed 1x1 PNG referenced by the image and video sitemaps. - [Sample sitemap video asset](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/assets/sample-video.mp4): The committed one-second MP4 clip referenced by the video sitemap. - [Sitemap index](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/sitemap-index.xml): A valid sitemapindex referencing exactly two child fixture sitemaps. - [Sitemap-only unlinked page](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/sitemap-only-unlinked-page): A 200 page referenced only by the valid single-URL sitemap, never by any HTML anchor. - [Redirecting sitemap target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/redirect-301): The single-hop 301 listed by the url-301 fixture sitemap. - [Missing sitemap target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/missing): The 404 page listed by the url-404 fixture sitemap. - [Gone sitemap target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/gone): The 410 page listed by the url-410 fixture sitemap. - [Canonical sitemap target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/canonical): The self-canonical destination of the non-canonical sitemap target. - [Hreflang German target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/hreflang-de): The German member of the reciprocal hreflang pair. - [Hreflang English target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/hreflang-en): The English member of the reciprocal hreflang pair. - [Image sitemap target page](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/image-page): The landing page embedding the committed sample image. - [Index child A target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/index-a): The page discovered via the index to child-a chain. - [Index child B target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/index-b): The page discovered via the index to child-b chain. - [News sitemap article page](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/news-article): The article page listed by the news sitemap. - [Noindex sitemap target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/noindex): A 200 page carrying a meta robots noindex while listed in a sitemap. - [Non-canonical sitemap target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/non-canonical): A 200 page whose canonical points at a different URL than the sitemap lists. - [Shared 200 sitemap target](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/valid-200): The healthy 200 page that several fixture sitemaps list. - [Video sitemap target page](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/targets/video-page): The landing page for the video sitemap entry. - [Sitemap listing a redirecting URL](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/url-301.xml): A valid single-URL sitemap whose loc 301-redirects to the shared 200 target. - [Sitemap listing a 404 URL](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/url-404.xml): A valid single-URL sitemap whose loc returns 404. - [Sitemap listing a 410 URL](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/url-410.xml): A valid single-URL sitemap whose loc returns 410 Gone. - [Valid single-URL sitemap](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/valid-single-url.xml): A schema-valid urlset with exactly one URL, referenced from the generated robots.txt for auto-discovery. - [Video extension sitemap](https://crawler-test-site.uk.sitebulb.com/tests/sitemaps/fixtures/video-sitemap.xml): A urlset using the Google video 1.1 extension with title, description, thumbnail, and content URLs. ## spider-traps - [Hidden link — display:none](https://crawler-test-site.uk.sitebulb.com/tests/spider-traps/hidden-links/display-none): A page carrying a single anchor with inline style display:none, pointing at a target reachable only through it. - [Hidden link — visibility:hidden](https://crawler-test-site.uk.sitebulb.com/tests/spider-traps/hidden-links/visibility-hidden): A page carrying a single anchor with inline style visibility:hidden, pointing at a target reachable only through it. - [Hidden link — white on white](https://crawler-test-site.uk.sitebulb.com/tests/spider-traps/hidden-links/white-on-white): A page carrying a single anchor with inline style color:#fff;background-color:#fff, pointing at a target reachable only through it. - [Hidden link — noscript only](https://crawler-test-site.uk.sitebulb.com/tests/spider-traps/hidden-links/noscript-only): A page carrying a single anchor present only inside a noscript element, pointing at a target reachable only through it. ## structured-data - [JSON-LD Article (valid)](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-article-valid): One application/ld+json script in the head carrying a valid Article payload. - [JSON-LD body placement](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-body-location): The identical Article payload as the only script, placed immediately before the closing body tag. - [JSON-LD BreadcrumbList (valid)](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-breadcrumb-valid): One head script carrying a valid BreadcrumbList payload with two positioned ListItem entries. - [JSON-LD FAQPage (valid)](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-faq-valid): One head script carrying a valid FAQPage payload with two question and answer pairs. - [JSON-LD head placement](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-head-location): The Article payload as the only script, placed inside the head. - [JSON-LD injected by JavaScript](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-js-injected): Raw HTML ships zero JSON-LD blocks; an inline script injects the Article payload into the head after load. - [JSON-LD malformed JSON](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-malformed-json): A script block whose content fails JSON parsing while the surrounding HTML stays fully parseable. - [JSON-LD Product missing required field](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-missing-required-field): A Product payload that parses cleanly but deliberately omits the name property. - [JSON-LD multiple blocks](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-multiple-blocks): Two separate valid head scripts: the Article payload and the BreadcrumbList payload. - [JSON-LD nonexistent type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-nonexistent-type): Syntactically valid JSON-LD declaring the unknown type FooBarWidget. - [JSON-LD Organization (valid)](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-organization-valid): One head script carrying a valid Organization payload with name, url, and logo. - [JSON-LD Product (valid)](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-product-valid): One head script carrying a valid Product payload with a name and an Offer. - [JSON-LD versus visible content conflict](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/jsonld-visible-content-conflict): Product JSON-LD declares price 19.99 while the visible page price element states 29.99. - [Microdata Product (basic)](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/microdata-basic): An itemscope/itemtype/itemprop Product snippet in the body with no JSON-LD on the page. - [RDFa Product (basic)](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/rdfa-basic): A vocab/typeof/property Product snippet in the body with no JSON-LD on the page. ## structured-data-features - [Article — author as plain string](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/article/author-string): Valid Article payload whose author is a plain string instead of a typed object. - [Article — malformed image URL](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/article/image-malformed-url): Valid Article payload whose first image entry is a malformed URL. - [Article — invalid datePublished](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/article/invalid-datepublished): Valid Article payload with a datePublished that does not parse as ISO 8601. - [Article — missing headline](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/article/missing-headline): Valid Article payload with the recommended headline absent. - [Article — fully valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/article/valid): Article with every recommended property, three image ratios, one Person author. - [Article — bare type only](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/article/valid-minimal): Bare Article with @type only; Google defines no required properties for Article. - [NewsArticle — fully valid subtype](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/article/valid-newsarticle): NewsArticle subtype, fully populated, two authors (Person + Organization). - [Breadcrumb — malformed item URL](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/breadcrumb/malformed-item-url): Valid trail except the second ListItem carries a malformed item URL. - [Breadcrumb — missing name](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/breadcrumb/missing-name): Valid trail except the second ListItem lacks its required name. - [Breadcrumb — position gap](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/breadcrumb/position-gap): Valid trail except the third position jumps to 4, leaving a sequence gap. - [Breadcrumb — position as string](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/breadcrumb/position-string): Valid trail except the second position is a string where an integer is required. - [Breadcrumb — single item trail](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/breadcrumb/single-item): BreadcrumbList whose itemListElement holds only one ListItem, below the two-item minimum. - [Breadcrumb — fully valid trail](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/breadcrumb/valid): Three-item trail where every ListItem carries position, name and item. - [Breadcrumb — final item omits item](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/breadcrumb/valid-minimal): Same trail but the final ListItem omits item, exercising the documented relaxation. - [Breadcrumb — two independent trails](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/breadcrumb/valid-multiple-trails): Two independent BreadcrumbList objects on one page, each fully valid. - [Carousel — Recipe detail page 1](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/detail-1): Recipe detail page backing summary item 1; valid Recipe markup. - [Carousel — Recipe detail page 2](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/detail-2): Recipe detail page backing summary item 2; valid Recipe markup. - [Carousel — Recipe detail page 3](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/detail-3): Recipe detail page backing summary item 3; valid Recipe markup. - [Carousel — item as plain string](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/item-string): All-in-one list whose second item is a plain string instead of a typed object. - [Carousel — malformed item URL](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/malformed-url): All-in-one list whose second nested Recipe carries a malformed url. - [Carousel — missing position](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/missing-position): All-in-one list whose second ListItem lacks its required position. - [Carousel — mixed item types](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/mixed-types): All-in-one list where a Movie sits among Recipe items, breaking type homogeneity. - [Carousel — single item list](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/single-item): All-in-one list holding only one ListItem, below the two-item minimum. - [Carousel — all-in-one Recipe list](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/valid): All-in-one ItemList: three ListItems with nested Recipe items and anchored same-page URLs. - [Carousel — summary page list](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/carousel/valid-minimal): Summary-page mode: three ListItems with only position and url, linking to the detail routes. - [Course List — duplicate course URL](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/course-list/duplicate-url): Valid list except the second course reuses the first course URL. - [Course List — malformed course URL](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/course-list/invalid-url): Valid list except the second course URL carries a malformed scheme. - [Course List — missing description](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/course-list/missing-description): Valid list except the second course lacks its required description. - [Course List — position as string](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/course-list/position-wrong-type): Valid list except the second ListItem position is a string, not an integer. - [Course List — too few courses](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/course-list/too-few-items): Only two courses in the list, below the three-course minimum. - [Course List — fully valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/course-list/valid): ItemList of 3 courses, all required + recommended properties. - [Course List — required only](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/course-list/valid-minimal): Same 3 courses, required properties only (no provider). - [Dataset — description too short](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/dataset/description-too-short): Fully populated Dataset whose description is 14 characters, below the 50-character minimum. - [Dataset — distribution as plain string](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/dataset/distribution-wrong-type): Fully populated Dataset whose distribution is a string where a DataDownload object is expected. - [Dataset — malformed download URL](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/dataset/invalid-download-url): Fully populated Dataset whose distribution contentUrl carries a malformed scheme. - [Dataset — invalid temporalCoverage](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/dataset/invalid-temporalcoverage): Fully populated Dataset whose temporalCoverage is prose rather than ISO 8601. - [Dataset — missing name](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/dataset/missing-name): Fully populated Dataset with the required name removed. - [Dataset — fully valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/dataset/valid): Dataset with all required + recommended properties, one CSV distribution. - [Dataset — required only](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/dataset/valid-minimal): Dataset carrying only the required name and description. - [Discussion forum: comment wrong type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/discussion-forum/comment-wrong-type): `comment` is a plain string instead of Comment object(s). - [Discussion forum: invalid datePublished](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/discussion-forum/invalid-datepublished): `datePublished` is `05/06/2026 14:30`, not ISO 8601. - [Discussion forum: invalid interactionType](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/discussion-forum/invalid-interactiontype): `interactionStatistic` uses unsupported `https://schema.org/UpvoteAction`. - [Discussion forum: missing author](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/discussion-forum/missing-author): Posting lacks required `author`. - [Discussion forum: missing content](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/discussion-forum/missing-content): Posting has no `text`, `image`, or `video`. - [Discussion forum: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/discussion-forum/valid): Full thread: posting with all required and recommended properties, two comments, one nested reply. - [Discussion forum: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/discussion-forum/valid-minimal): Posting with `author.name`, `datePublished`, `text` only. - [Education Q&A: bad eduQuestionType](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/education-qa/bad-eduquestiontype): First `Question` declares `eduQuestionType: "MultipleChoice"`. - [Education Q&A: missing acceptedAnswer](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/education-qa/missing-acceptedanswer): First `Question` has no `acceptedAnswer`. - [Education Q&A: multiple acceptedAnswers](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/education-qa/multiple-acceptedanswers): First `Question` carries an array of two `Answer` objects in `acceptedAnswer`. - [Education Q&A: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/education-qa/valid): Full `Quiz` with `about`, `educationalAlignment` (subject + level) and two complete flashcard `Question`s. - [Education Q&A: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/education-qa/valid-minimal): Required-only `Quiz` (`hasPart` questions with `eduQuestionType`, `text`, `acceptedAnswer`); no `about`, no `educationalAlignment`. - [Education Q&A: wrong type acceptedAnswer](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/education-qa/wrong-type-acceptedanswer): First `Question.acceptedAnswer` is a plain string instead of an `Answer` object. - [Employer aggregate rating: bad ratingValue](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/employer-aggregate-rating/bad-ratingvalue): `ratingValue` is the word `"excellent"` — not a number, fraction, or percentage. - [Employer aggregate rating: missing count](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/employer-aggregate-rating/missing-count): Both `ratingCount` and `reviewCount` removed. - [Employer aggregate rating: missing itemReviewed](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/employer-aggregate-rating/missing-itemreviewed): `itemReviewed` removed entirely. - [Employer aggregate rating: out of bounds](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/employer-aggregate-rating/out-of-bounds): `ratingValue` of `6.3` against the declared 1–5 scale. - [Employer aggregate rating: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/employer-aggregate-rating/valid): Full entity: `itemReviewed` Organization with `name` + `sameAs`, `ratingValue`, both `ratingCount` and `reviewCount`, explicit `bestRating`/`worstRating`. - [Employer aggregate rating: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/employer-aggregate-rating/valid-minimal): Required-only: `itemReviewed` (name only), `ratingValue`, `ratingCount`. - [Employer aggregate rating: wrong type itemReviewed](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/employer-aggregate-rating/wrong-type-itemreviewed): `itemReviewed` is a plain string instead of an `Organization` object. - [Event: bad availability](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/event/bad-availability): `offers.availability` is `https://schema.org/Available` — not in {`InStock`, `SoldOut`, `PreOrder`}. - [Event: bad startDate](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/event/bad-startdate): `startDate` is `"18th September 2026, 7:30pm"` — not ISO-8601. - [Event: endDate before startDate](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/event/enddate-before-startdate): `endDate` is the evening before `startDate`. - [Event: missing startDate](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/event/missing-startdate): `startDate` removed. - [Event: rescheduled missing previousStartDate](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/event/rescheduled-missing-previousstartdate): `eventStatus` set to `EventRescheduled` with no `previousStartDate`. - [Event: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/event/valid): Full `Event`: all required plus `description`, `endDate`, `eventStatus`, three `image` URLs (16x9/4x3/1x1), `offers`, `performer`, `organizer`, `location.name`. - [Event: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/event/valid-minimal): Required-only: `name`, `startDate`, `location` with full `PostalAddress`. - [Event: wrong type location](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/event/wrong-type-location): `location` is a plain string instead of a `Place` object. - [FAQ: bad question type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/faq/bad-question-type): First `mainEntity` item typed `FAQItem` instead of `Question`. - [FAQ: missing acceptedAnswer](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/faq/missing-acceptedanswer): First `Question` lacks `acceptedAnswer`. - [FAQ: missing mainEntity](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/faq/missing-mainentity): `FAQPage` node with no `mainEntity`. - [FAQ: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/faq/valid): Three-question `FAQPage`, answers using allowed HTML. - [FAQ: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/faq/valid-minimal): Single-question `FAQPage`, plain-text answer. - [FAQ: wrong answer type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/faq/wrong-answer-type): First `acceptedAnswer` is a plain string instead of an `Answer` object. - [Image Metadata: invalid license URL](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/image-metadata/invalid-license-url): `license` holds free text instead of a URL. - [Image Metadata: missing all credit](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/image-metadata/missing-all-credit): `contentUrl` only; none of `creator`/`creditText`/`copyrightNotice`/`license` present. - [Image Metadata: missing contentUrl](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/image-metadata/missing-contenturl): Required `contentUrl` omitted. - [Image Metadata: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/image-metadata/valid): Full `ImageObject`: `contentUrl` plus all five credit/licensing properties (`license`, `acquireLicensePage`, `creator`, `creditText`, `copyrightNotice`). - [Image Metadata: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/image-metadata/valid-minimal): Required-only: `contentUrl` plus `creditText` satisfying the one-of group. - [Image Metadata: wrong creator type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/image-metadata/wrong-creator-type): `creator` is a plain string instead of a `Person`/`Organization` object. - [Job Posting: bad datePosted](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/bad-dateposted): `datePosted` is `09/06/2026` — not ISO 8601. - [Job Posting: bad employmentType](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/bad-employmenttype): `employmentType` is `Full-Time` — not in the case-sensitive enum. - [Job Posting: missing jobLocation](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/missing-joblocation): Non-remote posting with `jobLocation` removed — no `jobLocationType`, no `applicantLocationRequirements`. - [Job Posting: missing title](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/missing-title): Required `title` omitted. - [Job Posting: remote missing applicantLocationRequirements](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/remote-missing-applicantlocation): TELECOMMUTE posting with `applicantLocationRequirements` removed and no `jobLocation`. - [Job Posting: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/valid): On-site role with all required + recommended properties: full address, salary range, enum employment type, far-future `validThrough`, identifier, `directApply`. - [Job Posting: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/valid-minimal): Required-only on-site role: `title`, `datePosted`, `description`, `hiringOrganization`, full `jobLocation`. - [Job Posting: valid remote](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/valid-remote): 100% remote role: `jobLocationType: "TELECOMMUTE"` plus `applicantLocationRequirements`, no `jobLocation`. - [Job Posting: validThrough in the past](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/validthrough-past): `validThrough` is `2020-01-01` — before `datePosted` and in the past. - [Job Posting: wrong hiringOrganization type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/job-posting/wrong-hiringorganization-type): `hiringOrganization` is a plain string instead of an `Organization` object. - [Local Business: address as plain string](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/local-business/address-string): Valid payload with `address` as a plain string instead of a `PostalAddress` object. - [Local Business: bad opening hours](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/local-business/bad-opening-hours): Valid payload with one `opens` value as `"11:30 AM"` instead of `hh:mm:ss`. - [Local Business: geo out of range](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/local-business/geo-out-of-range): Valid payload with `geo.latitude` set to `153.38113` — outside -90..90. - [Local Business: missing address](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/local-business/missing-address): Valid payload with the required `address` property removed. - [Local Business: priceRange too long](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/local-business/pricerange-too-long): Valid payload with a 119-character `priceRange` value — the limit is under 100 characters. - [Local Business: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/local-business/valid): Full `Restaurant`: all required + recommended properties, carousel-grade image set, late-night and closed-day opening hours, nested department. - [Local Business: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/local-business/valid-minimal): `LocalBusiness` with only the required `name` and `address`. - [Math Solver: bad eduQuestionType](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/math-solver/bad-eduquestiontype): Valid payload with `eduQuestionType` containing `"Quantum Mechanics"` in place of `"Derivative"`. - [Math Solver: bad target URL](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/math-solver/bad-target-url): Valid payload with `potentialAction.target` as a relative URL instead of a fully-qualified URL. - [Math Solver: missing usageInfo](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/math-solver/missing-usageinfo): Valid payload with the required `usageInfo` property removed. - [Math Solver: potentialAction as plain string](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/math-solver/potentialaction-string): Valid payload with `potentialAction` as a plain URL string instead of a `SolveMathAction` object. - [Math Solver: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/math-solver/valid): Full `["MathSolver", "LearningResource"]` payload with all required + recommended properties and `learningResourceType: "Math Solver"`. - [Math Solver: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/math-solver/valid-minimal): Required-only `MathSolver`: `url`, `usageInfo`, and a `SolveMathAction` with `target` + `mathExpression-input`. - [Movie: bad dateCreated](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/movie/bad-datecreated): Valid payload with the first movie's `dateCreated` set to `"13-45-2026"` — not valid ISO-8601. - [Movie: director as plain string](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/movie/director-string): Valid payload with the first movie's `director` as a plain string instead of a `Person` object. - [Movie: duplicate position](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/movie/duplicate-position): Valid payload with both `ListItem` elements declaring `position: 1`. - [Movie: missing image](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/movie/missing-image): Valid payload with the required `image` property removed from the first movie. - [Movie: standalone (no ItemList)](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/movie/standalone): The first `Movie` from the valid payload published standalone, with no `ItemList` wrapper. - [Movie: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/movie/valid): All-in-one `ItemList` of two `Movie` items, each with all required + recommended properties and 6:9 poster images. - [Movie: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/movie/valid-minimal): Same two-item `ItemList` with required properties only: `position`, `item.name`, `item.url`, `item.image`. - [Organization: contactPoint wrong type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/organization/contactpoint-wrong-type): `contactPoint` is a bare string instead of a `ContactPoint` object. - [Organization: invalid country code](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/organization/invalid-country-code): `addressCountry` is `"United Kingdom"` instead of the two-letter ISO 3166-1 alpha-2 code `GB`. - [Organization: logo too small](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/organization/logo-too-small): `logo` references a 64x64px image, below the 112x112px minimum. - [Organization: malformed iso6523Code](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/organization/malformed-iso6523): `iso6523Code` lacks the colon separating the ICD prefix from the identifier. - [Organization: missing name](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/organization/missing-name): `name` removed; Google lists no required Organization properties, so this must warn, not error. - [Organization: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/organization/valid): Full `Organization`: name, legal identity, 600x600 logo, address, contactPoint, sameAs, foundingDate, numberOfEmployees, and all identifier properties. - [Organization: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/organization/valid-minimal): Minimal useful entity: `name` + `url` only; Google requires no Organization properties. - [Paywalled Content: invalid cssSelector](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/paywalled-content/invalid-cssselector): Identical to valid but `cssSelector` is the ID selector `#paywall`. - [Paywalled Content: missing isAccessibleForFree](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/paywalled-content/missing-isaccessibleforfree): Identical to valid but top-level `isAccessibleForFree` removed. - [Paywalled Content: selector no match](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/paywalled-content/selector-no-match): Identical to valid but `cssSelector` is `.premium-content`, which matches no element in the page HTML. - [Paywalled Content: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/paywalled-content/valid): `NewsArticle` with `isAccessibleForFree: false` and one `hasPart` `WebPageElement` using the `.paywall` class selector. - [Paywalled Content: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/paywalled-content/valid-minimal): Required-only: `isAccessibleForFree: false`, no `hasPart`. - [Paywalled Content: valid multi-section](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/paywalled-content/valid-multi-section): `hasPart` array with two `WebPageElement` entries (`.section1`, `.section2`), non-nested gated sections. - [Paywalled Content: wrong type hasPart](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/paywalled-content/wrong-type-haspart): Identical to valid but `hasPart` is the string `".paywall"` instead of a `WebPageElement` object. - [Product: bad availability enum](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/bad-availability-enum): `availability` is `https://schema.org/Available` — not an `ItemAvailability` member. - [Product: invalid currency](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/invalid-currency): `priceCurrency` is `"POUNDS"` — not a three-letter ISO 4217 code. - [Product: invalid price](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/invalid-price): `price` is `"£89.99"` — a currency symbol in a numeric field. - [Product: merchant valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/merchant-valid): Offer-based merchant listing: name, three image ratios, brand, sku, description, Offer with price, ISO 4217 currency, availability, itemCondition, priceValidUntil, url, shippingDetails, hasMerchantReturnPolicy. - [Product: missing name](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/missing-name): Merchant-valid payload with required `name` removed. - [Product: no snippet signal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/no-signal): A Product with neither `offers` nor `review` nor `aggregateRating`. - [Product: offers wrong type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/offers-wrong-type): `offers` is the string `"89.99 GBP"` instead of an `Offer` object. - [Product: rating out of bounds](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/rating-out-of-bounds): `aggregateRating.ratingValue` is `6` with a declared `bestRating` of 5. - [Product: snippet valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/snippet-valid): Review/rating-based product snippet: name, three image ratios, brand, sku, mpn, description, review with pros and cons, aggregateRating, Offer. - [Product: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/product/valid-minimal): Snippet minimum only: `name` plus an `aggregateRating` from the review/rating/offers one-of group. - [Profile Page: invalid dateCreated](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/profile-page/invalid-datecreated): `dateCreated` is `"23/12/2024 12:34pm"` — not ISO 8601. - [Profile Page: mainEntity wrong type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/profile-page/mainentity-wrong-type): `mainEntity` is a plain string instead of a `Person`/`Organization` object. - [Profile Page: missing mainEntity](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/profile-page/missing-mainentity): Required `mainEntity` removed. - [Profile Page: mainEntity missing name](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/profile-page/missing-name): Person `mainEntity` without `name` and without an `alternateName` fallback. - [Profile Page: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/profile-page/valid): Full `ProfilePage`: dateCreated, dateModified, and a Person mainEntity with name, alternateName, identifier, description, image, sameAs, and both interaction statistic kinds. - [Profile Page: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/profile-page/valid-minimal): Required-only: `ProfilePage` with a Person `mainEntity` carrying `name` only. - [Q&A Page: answer missing text](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/qa-page/answer-missing-text): The acceptedAnswer's required `text` removed. - [Q&A Page: answer wrong type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/qa-page/answer-wrong-type): `acceptedAnswer` is a plain string instead of an `Answer` object. - [Q&A Page: invalid datePublished](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/qa-page/invalid-datepublished): Question `datePublished` is `"02/11/2025 9:15am"` — not ISO 8601. - [Q&A Page: missing answerCount](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/qa-page/missing-answercount): Required `answerCount` removed from the Question. - [Q&A Page: multiple questions](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/qa-page/multiple-questions): `mainEntity` is an array of two Question objects; QAPage allows exactly one Question per page. - [Q&A Page: negative upvoteCount](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/qa-page/negative-upvotecount): Question `upvoteCount` is `-4`; it must be a non-negative aggregate integer. - [Q&A Page: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/qa-page/valid): Full `QAPage`: one Question with all required and recommended properties, one acceptedAnswer and two suggestedAnswers (answerCount 3). - [Q&A Page: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/qa-page/valid-minimal): Required-only: Question with `name`, `answerCount`, and one suggestedAnswer carrying `text` only. - [Recipe: cookTime without prepTime](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/recipe/cooktime-without-preptime): `prepTime` removed while `cookTime` remains, violating the documented pairing rule. - [Recipe: invalid cookTime](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/recipe/invalid-cooktime): `cookTime` is `"45 minutes"` — not an ISO 8601 duration. - [Recipe: missing image](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/recipe/missing-image): Required `image` removed. - [Recipe: nutrition wrong type](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/recipe/nutrition-wrong-type): `nutrition` is a plain string instead of a `NutritionInformation` object. - [Recipe: rating out of bounds](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/recipe/rating-out-of-bounds): `aggregateRating.ratingValue` is `"6"`, outside the default 1-5 bounds (no bestRating override). - [Recipe: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/recipe/valid): Full `Recipe`: all required plus recommended properties, HowToStep instructions, nutrition with yield, paired prep/cook times, aggregateRating, VideoObject. - [Recipe: valid carousel ItemList](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/recipe/valid-itemlist): Carousel summary page: `ItemList` of ListItems with sequential positions and unique recipe URLs. - [Recipe: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/recipe/valid-minimal): Required-only: `name` + `image`. - [Recipe: valid text instructions](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/recipe/valid-text-instructions): `recipeInstructions` is a single plain-text block — the documented Text shape Google auto-splits; must not be flagged. - [Review Snippet: aggregate missing count](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/review-snippet/aggregate-missing-count): `AggregateRating` with neither `ratingCount` nor `reviewCount`. - [Review Snippet: missing author](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/review-snippet/missing-author): Full valid payload with `Review.author` removed. - [Review Snippet: rating out of bounds](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/review-snippet/rating-out-of-bounds): `reviewRating.ratingValue` of 6 against an explicit `bestRating` of 5. - [Review Snippet: self-serving](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/review-snippet/self-serving): The page's own `LocalBusiness` entity carries an `aggregateRating` about itself. - [Review Snippet: unsupported itemReviewed](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/review-snippet/unsupported-itemreviewed): Standalone `Review` whose `itemReviewed` is a `Person` — not a supported review-snippet type. - [Review Snippet: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/review-snippet/valid): `Product` with fully populated nested `Review` and `AggregateRating` (all required + recommended properties). - [Review Snippet: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/review-snippet/valid-minimal): `Product` with nested `Review` carrying required properties only — no `datePublished`, no explicit `bestRating`/`worstRating`, no `AggregateRating`. - [Review Snippet: wrong type reviewRating](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/review-snippet/wrong-type-reviewrating): `reviewRating` supplied as the string `"4.5"` instead of a `Rating` object. - [Software App: invalid category](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/software-app/invalid-category): `applicationCategory` set to `"CookingApplication"`, not in Google's supported list. - [Software App: missing name](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/software-app/missing-name): Full valid payload with `name` removed. - [Software App: missing offers price](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/software-app/missing-offers-price): `Offer` present but without `price`. - [Software App: no rating or review](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/software-app/no-rating-or-review): Neither `aggregateRating` nor `review` present. - [Software App: rating out of bounds](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/software-app/rating-out-of-bounds): `aggregateRating.ratingValue` of 5.6 against an explicit `bestRating` of 5. - [Software App: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/software-app/valid): `SoftwareApplication` with all required + recommended properties: `offers`, `aggregateRating`, `review`, `applicationCategory`, `operatingSystem`. - [Software App: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/software-app/valid-minimal): Required-only: `name`, free `offers` (`price: 0`), `aggregateRating`; no `applicationCategory` or `operatingSystem`. - [Software App: wrong type offers](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/software-app/wrong-type-offers): `offers` supplied as the string `"USD 1.99"` instead of an `Offer` object. - [Speakable: both selectors](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/speakable/both-selectors): `cssSelector` and `xpath` combined in one `SpeakableSpecification`. - [Speakable: empty selector](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/speakable/empty-selector): `cssSelector` present but an empty array. - [Speakable: missing selector](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/speakable/missing-selector): `SpeakableSpecification` with neither `cssSelector` nor `xpath`. - [Speakable: selector no match](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/speakable/selector-no-match): `cssSelector` includes `.speakable-missing`, which matches nothing in the served HTML. - [Speakable: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/speakable/valid): News-style `Article` with `speakable` using `cssSelector` targeting headline + summary elements. - [Speakable: valid xpath](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/speakable/valid-xpath): Same article with `speakable` using `xpath` locators instead of `cssSelector`. - [Speakable: wrong type speakable](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/speakable/wrong-type-speakable): `speakable` supplied as the bare string `".speakable-headline"` instead of a `SpeakableSpecification` object. - [Vacation Rental: invalid checkinTime](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/vacation-rental/invalid-checkintime): Minimal payload plus `checkinTime: "6pm"` (not ISO 8601). - [Vacation Rental: low precision coords](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/vacation-rental/low-precision-coords): Minimal payload with `latitude: 51.5`, `longitude: -0.1` (fewer than 5 decimal places). - [Vacation Rental: missing identifier](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/vacation-rental/missing-identifier): Minimal payload with `identifier` removed. - [Vacation Rental: too few images](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/vacation-rental/too-few-images): Minimal payload with only 3 images (Google requires a minimum of 8). - [Vacation Rental: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/vacation-rental/valid): Full `VacationRental` with all required and recommended properties: accommodation detail, address, ratings, reviews, eight images. - [Vacation Rental: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/vacation-rental/valid-minimal): Required-only: `containsPlace` with `occupancy`, `identifier`, eight images, `latitude`, `longitude`, `name`. - [Vacation Rental: wrong type occupancy](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/vacation-rental/wrong-type-occupancy): Minimal payload with `occupancy` as the bare integer 4 instead of a `QuantitativeValue` object. - [Video: clip duplicate start](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/clip-duplicate-start): Clips payload where both clips share `startOffset: 30` (start times must be unique per page). - [Video: clip offset order](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/clip-offset-order): Clips payload where the first clip has `endOffset: 20` with `startOffset: 30`. - [Video: invalid duration](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/invalid-duration): Valid payload with `duration: "1:30"` (not ISO 8601). - [Video: missing thumbnailUrl](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/missing-thumbnailurl): Valid payload with required `thumbnailUrl` removed. - [Video: valid](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/valid): Full `VideoObject` with all required and recommended properties (`regionsAllowed` chosen over `ineligibleRegion`). - [Video: valid clips](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/valid-clips): Full `VideoObject` plus two `Clip` entries in `hasPart` with unique start offsets and deep-link URLs. - [Video: valid live](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/valid-live): Full `VideoObject` plus a `BroadcastEvent` in `publication` (`isLiveBroadcast: true`, start and end dates). - [Video: valid minimal](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/valid-minimal): Required-only: `name`, `thumbnailUrl`, `uploadDate` (deliberately timezone-less, which the doc permits). - [Video: valid SeekToAction](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/valid-seektoaction): Full `VideoObject` plus a `SeekToAction` `potentialAction` with the `{seek_to_second_number}` URL template. - [Video: wrong type interactionStatistic](https://crawler-test-site.uk.sitebulb.com/tests/structured-data/features/video/wrong-type-interactionstatistic): `interactionStatistic` supplied as the bare number 5647018 instead of an `InteractionCounter` object. ## tech-fingerprints - [CDN/WAF signatures — Akamai](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/cdn-waf/akamai): A 200 page carrying X-Akamai-Transformed, Akamai-Origin-Hop, and Server: AkamaiGHost so all three detection paths fire. - [CDN/WAF signatures — Cloudflare](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/cdn-waf/cloudflare): A 200 page carrying the CF-Ray, CF-Cache-Status, and Server: cloudflare signature headers. - [CDN/WAF signatures — Cloudflare 403 challenge](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/cdn-waf/cloudflare-block-403): A 403 page carrying CF-Ray, cf-mitigated: challenge, and Server: cloudflare to exercise the WAF-block logging path. - [CDN/WAF signatures — Amazon CloudFront](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/cdn-waf/cloudfront): A 200 page carrying the X-Amz-Cf-Id and X-Amz-Cf-Pop signature headers. - [CDN/WAF signatures — DataDome](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/cdn-waf/datadome): A 200 page carrying the X-DataDome header and the datadome cookie. - [CDN/WAF signatures — F5 BIG-IP](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/cdn-waf/f5-big-ip): A 200 page carrying Server: BigIP plus BIGipServer-prefixed and TS-regex cookies so all three detection paths fire. - [CDN/WAF signatures — Fastly](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/cdn-waf/fastly): A 200 page carrying the X-Served-By and X-Fastly-Request-Id signature headers. - [CDN/WAF signatures — Imperva](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/cdn-waf/imperva): A 200 page carrying X-Iinfo, X-CDN: Incapsula, and both visid_incap_ and incap_ses_ cookies. - [CDN/WAF signatures — multiple providers](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/cdn-waf/multi-provider): A 200 page carrying both CF-Ray and X-Served-By, proving the provider flags combine rather than overwrite. - [Technology signals — Drupal (header only)](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/tech-drupal): Emits the X-Generator response header with no Drupal markup, scripts, or JS globals. - [Technology signals — Gatsby](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/tech-gatsby): Carries the ___gatsby root div and the Gatsby generator meta tag (html and meta signals). - [Technology signals — jQuery (script src only)](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/tech-jquery): References a versioned jquery-3.7.1.min.js stub whose filename is the only jQuery signal; no jQuery global exists. - [Technology signals — Laravel (cookie only)](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/tech-laravel): Sets exactly one laravel_session cookie; the cookie name is the only Laravel signal. - [Technology signals — Next.js (header only)](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/tech-nextjs): Emits the X-Powered-By response header with no __NEXT_DATA__ global. - [Technology signals — React (JS global only)](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/tech-react): An inline script sets window.React.version after render; a non-rendering crawl sees no React evidence in the DOM. - [Technology signals — Squarespace (HTML comment only)](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/tech-squarespace): Carries the literal Squarespace HTML comment with no Squarespace header or JS global. - [Technology signals — WordPress](https://crawler-test-site.uk.sitebulb.com/tests/tech-fingerprints/tech-wordpress): Emits the WordPress generator meta tag plus /wp-content/ stylesheet and script URLs (meta, script-src, and html signals). ## urls-normalisation - [Default document — default.html](https://crawler-test-site.uk.sitebulb.com/tests/urls/default-documents/default.html): A literal default.html file so default-document URL handling is visible without directory rewriting. - [Double-encoded percent sign in path](https://crawler-test-site.uk.sitebulb.com/tests/urls/encoding/double-encoded-%2520): A path containing %2520 (a double-encoded space) that must not be collapsed by intermediate decoding. - [Double slash in path](https://crawler-test-site.uk.sitebulb.com/tests/urls//double-slash): A path containing an empty segment (//) that must reach the app without slash merging. - [Duplicate query keys](https://crawler-test-site.uk.sitebulb.com/tests/urls/query/duplicate-keys?a=1&a=2): An endpoint that echoes every value parsed for a repeated query key. - [Fragment link source page](https://crawler-test-site.uk.sitebulb.com/tests/urls/fragments/source): A stable page whose anchors point at same-page fragments, which are never sent to the server. - [Hostname case normalisation](https://crawler-test-site.uk.sitebulb.com/tests/urls/host-case): A fixture page requested with a mixed-case hostname against the lowercase-registered host profile. - [Default document — index.htm](https://crawler-test-site.uk.sitebulb.com/tests/urls/default-documents/index.htm): A literal index.htm file so default-document URL handling is visible without directory rewriting. - [Default document — index.html](https://crawler-test-site.uk.sitebulb.com/tests/urls/default-documents/index.html): A literal index.html file so default-document URL handling is visible without directory rewriting. - [Path case sensitivity](https://crawler-test-site.uk.sitebulb.com/tests/urls/case/Page.html): An uppercase path variant served alongside a lowercase twin with a distinct marker. - [Punycode IDN host](https://crawler-test-site.uk.sitebulb.com/tests/urls/idn): A fixture page served from the internationalised (punycode) hostname profile. - [Query parameter order — a then b](https://crawler-test-site.uk.sitebulb.com/tests/urls/query/order?a=1&b=2): The a-first variant of the query-order pair; the endpoint echoes the raw query string. - [Query parameter order — b then a](https://crawler-test-site.uk.sitebulb.com/tests/urls/query/order?b=2&a=1): The b-first variant of the query-order pair; the endpoint echoes the raw query string. - [Session ID parameter](https://crawler-test-site.uk.sitebulb.com/tests/urls/parameters/session-id?sessionid=abc123): An endpoint that echoes a session-style query parameter so session-ID URLs are identifiable. - [Percent-encoded space in path](https://crawler-test-site.uk.sitebulb.com/tests/urls/encoding/space%20encoded): A path whose final segment contains a percent-encoded space (%20). - [Trailing-dot FQDN host](https://crawler-test-site.uk.sitebulb.com/tests/urls/trailing-dot): An ordinary page whose fixture variant requests the same route with a trailing-dot fully qualified Host header. - [Trailing slash — with slash](https://crawler-test-site.uk.sitebulb.com/tests/urls/trailing-slash/with-slash/): The trailing-slash variant of the pair: the framework 301-redirects it to the slashless form. - [Trailing slash — slashless redirect target](https://crawler-test-site.uk.sitebulb.com/tests/urls/trailing-slash/with-slash): The slashless landing page of the trailing-slash redirect. - [Trailing slash — without slash](https://crawler-test-site.uk.sitebulb.com/tests/urls/trailing-slash/without-slash): The slashless variant of the trailing-slash pair, served as an ordinary page. - [Triple slash in path](https://crawler-test-site.uk.sitebulb.com/tests/urls///triple-slash): A path containing two empty segments (///) that must reach the app without slash merging. - [International URL — Arabic](https://crawler-test-site.uk.sitebulb.com/tests/urls/international/arabic-%D9%85%D8%B1%D8%AD%D8%A8%D8%A7): A path whose final segment contains percent-encoded Arabic characters. - [International URL — Hebrew](https://crawler-test-site.uk.sitebulb.com/tests/urls/international/hebrew-%D7%A9%D7%9C%D7%95%D7%9D): A path whose final segment contains percent-encoded Hebrew characters. - [International URL — Japanese](https://crawler-test-site.uk.sitebulb.com/tests/urls/international/japanese-%E6%97%A5%E6%9C%AC%E8%AA%9E): A path whose final segment contains percent-encoded Japanese characters. - [International URL — Polish](https://crawler-test-site.uk.sitebulb.com/tests/urls/international/polish-za%C5%BC%C3%B3%C5%82%C4%87): A path whose final segment contains percent-encoded Polish characters. - [UTM tracking parameters](https://crawler-test-site.uk.sitebulb.com/tests/urls/parameters/utm?utm_source=test&utm_medium=crawler): An endpoint that echoes utm_source and utm_medium so tracking-parameter URLs are identifiable. ## utility-endpoints - [Headers mirror](https://crawler-test-site.uk.sitebulb.com/headers-mirror): Returns the request headers as JSON, with sensitive headers redacted. - [IP mirror](https://crawler-test-site.uk.sitebulb.com/ip-mirror): Returns the requester IP information visible to the app, including forwarded headers. - [llms.txt](https://crawler-test-site.uk.sitebulb.com/llms.txt): The primary AI-crawler guidance file, generated from the registry. - [robots.txt](https://crawler-test-site.uk.sitebulb.com/robots.txt): The primary robots policy, generated from registry contributions. - [security.txt](https://crawler-test-site.uk.sitebulb.com/.well-known/security.txt): Stable RFC 9116 security contact content for crawler discovery tests. - [Timing](https://crawler-test-site.uk.sitebulb.com/timing): Returns server timestamps and a request duration marker, never cached. - [User agent mirror](https://crawler-test-site.uk.sitebulb.com/user-agent-mirror): Returns the requesting user agent as JSON, or plain text when requested. ## web-vitals - [Heavy font asset](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/assets/vitals-asset-font-heavy.ttf): Committed 1,048,576-byte TrueType font (uncompressed container, so on-disk size is wire size). - [Heavy image asset](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/assets/vitals-asset-image-heavy.png): Deterministic 1448x1448 PNG (~2MiB, stored-deflate so transferred bytes match resource bytes) generated by the shared PNG helper. - [Heavy media asset](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/assets/vitals-asset-media-heavy.mp4): Committed 2,097,152-byte MP4: the sample video plus a deterministic top-level free box pad. - [Heavy script asset](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/assets/vitals-asset-script-heavy.js): Committed 1,048,576-byte valid JavaScript: one large string constant plus a function that sets the budget-script rendered marker. - [Heavy stylesheet asset](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/assets/vitals-asset-stylesheet-heavy.css): Committed 1,048,576-byte valid CSS: numbered padding rules plus the one rule the embedding page uses. - [Heavy third-party script asset](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/assets/vitals-asset-third-party-heavy.js): The heavy script content served by the host-subdomain profile so the embedding page crosses an origin. - [Web vitals calibration baseline](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/baseline-fast): Minimal page with inline critical CSS only, no external resources, and a trivial inline script setting the rendered marker. - [Performance budget — document bucket](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/budget/document): The page itself is the heavy resource: over 1MiB of visible repeated HTML text with no external resources. - [Performance budget — font bucket](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/budget/font): Small page whose font-face rule loads the 1MiB committed font, with visible text using that family so it downloads. - [Performance budget — image bucket](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/budget/image): Small page embedding the ~2MiB image via an img element with explicit width and height. - [Performance budget — media bucket](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/budget/media): Small page embedding the 2MiB MP4 via video preload="auto" muted, with no autoplay. - [Performance budget — script bucket](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/budget/script): Small page loading the 1MiB committed script via a plain script tag; the heavy script sets the rendered marker. - [Performance budget — stylesheet bucket](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/budget/stylesheet): Small page loading the 1MiB committed stylesheet via a link tag; one rule from the sheet is used by the page. - [Performance budget — third-party bucket](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/budget/third-party): Small page loading the heavy script from the host-subdomain profile origin via an absolute configuration-derived URL. - [Layout shift — late-injected banner](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/cls-late-banner): Renders immediately with 120vh of content; a fixed 2,000ms timer injects a 192px banner as the first body child. - [LCP hero image asset](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/assets/vitals-lcp-hero-image.png): Deterministic 1600x900 PNG generated by the shared PNG helper; fetched as the LCP element of vitals-lcp-late-hero. - [LCP — late-injected hero image](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/lcp-late-hero): Paints quickly with small text; a fixed 4,000ms timer injects the hero image into a pre-reserved container. - [TBT — three bounded long tasks](https://crawler-test-site.uk.sitebulb.com/tests/web-vitals/tbt-long-tasks): After a fixed 1,000ms, runs exactly three 300ms wall-clock busy loops separated by 100ms yields, once only.