Technical SEO audit across 9 categories: crawlability, indexability, security, URL structure, mobile, Core Web Vitals, structured data, JavaScript rendering, and IndexNow protocol.
Library skill — the default version is maintained in GitHub; edits you make live in your own clone.
"${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run sitemap_discovery.py <url> --json; require a
valid entry in found, and report stale or unsafe robots.txt declarations
separately from working fallback locations/crawling/ipranges/ and googlebot.json was renamed common-crawlers.json.As of 2025-2026, AI companies actively crawl the web to train models and power AI search. Managing these crawlers via robots.txt is a critical technical SEO consideration.
Known AI crawlers:
| Crawler | Company | robots.txt token | Purpose |
|---|---|---|---|
| GPTBot | OpenAI | GPTBot |
Model training (NOT ChatGPT Search) |
| OAI-SearchBot | OpenAI | OAI-SearchBot |
ChatGPT Search citability |
| ChatGPT-User | OpenAI | ChatGPT-User |
Real-time browsing (user-triggered) |
| ClaudeBot | Anthropic | ClaudeBot |
Model training (NOT Claude search citability) |
| Claude-SearchBot | Anthropic | Claude-SearchBot |
Claude search-result citability |
| PerplexityBot | Perplexity | PerplexityBot |
Search index + training |
| Bytespider | ByteDance | Bytespider |
Model training |
| Google-Extended | Google-Extended |
Gemini training (NOT search) | |
| Applebot-Extended | Apple | Applebot-Extended |
Apple Intelligence training opt-out (NOT Siri/Spotlight/Safari) |
| CCBot | Common Crawl | CCBot |
Open dataset |
Key distinctions:
- Blocking Google-Extended prevents Gemini training use but does NOT affect Google Search indexing or AI Overviews (those use Googlebot)
- Blocking GPTBot prevents OpenAI training but does NOT affect ChatGPT Search
citability, which is governed by OAI-SearchBot, nor user-triggered browsing
(ChatGPT-User). Check OAI-SearchBot for any citability claim; GPTBot
status is evidence about training use only
- Blocking ClaudeBot prevents Anthropic model training but does NOT affect
citability in Claude's own search features, which is governed by
Claude-SearchBot (per Anthropic's crawler support article). Check
Claude-SearchBot for any Claude-search citability claim; ClaudeBot status
is evidence about training use only
- Blocking Applebot-Extended opts out of Apple Intelligence / generative-model
training use but does NOT affect discoverability via Siri, Spotlight, or Safari,
which follows Applebot (per Apple's support article); Applebot-Extended does
not itself crawl
- ~3-5% of websites now use AI-specific robots.txt rules
Example, selective AI crawler blocking:
# Allow search indexing, block AI training crawlers
User-agent: GPTBot
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: Bytespider
Disallow: /
# Allow all other crawlers (including Googlebot for search)
User-agent: *
Allow: /
Recommendation: Consider your AI visibility strategy before blocking. Being cited by AI systems drives brand awareness and referral traffic. Cross-reference the seo-geo skill for the full AI crawler/fetcher taxonomy.
User-triggered fetchers ignore robots.txt by design. Google now documents Google-Agent (Project Mariner, agentic browsing) plus Google-NotebookLM and Google Messages as user-triggered fetchers that cannot be blocked via robots.txt. Use server-side access controls instead. By contrast,
Google-ExtendedandGoogle-CloudVertexBotobey robots.txt. Emerging: Web Bot Auth (RFC 9421) lets bots authenticate cryptographically via aSignature-Agentheader + key directory atagent.bot.goog(used by Google-Agent); reverse-DNS verification remains the fallback.
history.pushState/replaceState (including scripts injected by third-party ad/library platforms). Added to Google's spam policies 2026-04-13; enforcement live since 2026-06-15 (manual actions + automated demotions): treat as Critical.Page experience is guidance, not a single ranking system. Only Core Web Vitals feeds ranking directly; HTTPS is a confirmed but lightweight signal (affects <~1% of queries). Relevance can still win even when page experience is sub-par, so don't over-weight security headers. Note: the standalone Page Experience report was removed from Search Console (monitor via the Core Web Vitals + HTTPS reports).
Recommended rendering strategy:
| Strategy | Use Case |
|---|---|
| SSR | Public SEO content, dynamic pages |
| SSG | Static content, blogs, docs |
| CSR | Authenticated / behind-login content only |
Preferred frameworks: Next.js, Astro, React Router v7 (Remix), SvelteKit
Google updated its JavaScript SEO documentation in December 2025 with critical clarifications:
<meta name="robots" content="noindex"> but JavaScript removes it, Google MAY still honor the noindex from raw HTML. Serve correct robots directives in the initial HTML response.Best practice: Serve critical SEO elements (canonical, meta robots, structured data, title, meta description) in the initial server-rendered HTML rather than relying on JavaScript injection.
AI agents (not just AI summarizers) increasingly read sites through three
channels: vision models on screenshots, raw HTML/DOM, and the accessibility
tree (the cleanest signal). Audit criteria: semantic HTML (real <button>
and <a>, not <div onclick>), label associations, interactive target sizing,
layout stability across templates, cursor: pointer correctness, live in
references/agent-friendly-pages.md.
Google now ships a Lighthouse Agentic Browsing category (default-on since
Lighthouse 13.3.0, Chrome 150+; buckets: agent-centric accessibility, CLS +
llms.txt, three WebMCP audits). It reports a fractional pass-ratio (X of N),
not a 0-100 score, keep that distinct from this skill's own Agent-UX 0-100
heuristic below. Lighthouse 13.4.1 re-enabled the category through the PSI API.
It is also available through Lighthouse CLI with
--only-categories=agentic-browsing, DevTools, and the PSI web UI. See
references/agent-friendly-pages.md.
# Render with Playwright + capture accessibility tree, then score
"${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run agent_ux_check.py https://example.com --json
The scanner outputs an Agent-UX score (0-100) plus itemized issues:
- HTML findings: real buttons / anchors, <div onclick> widgets, semantic
landmarks, inputs without <label for>, inputs without ARIA labels
- Accessibility tree findings: total nodes, interactive nodes, unnamed
interactive elements, role="generic" ratio
The accessibility-tree snapshot uses Chromium's
Accessibility.getFullAXTree CDP command through Playwright. To capture the
tree without scoring, use
"${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run render_page.py <url> --a11y-tree --json.
Surface findings as opportunities, not failures; don't gate audits on a sub-100 Agent-UX score. WebMCP origin-trial/sign-up status needs verification, and absence of WebMCP support is still an opportunity, not a defect.
| Category | Status | Score |
|---|---|---|
| Crawlability | pass/warn/fail | XX/100 |
| Indexability | pass/warn/fail | XX/100 |
| Security | pass/warn/fail | XX/100 |
| URL Structure | pass/warn/fail | XX/100 |
| Mobile | pass/warn/fail | XX/100 |
| Core Web Vitals | pass/warn/fail | XX/100 |
| Structured Data | pass/warn/fail | XX/100 |
| JS Rendering | pass/warn/fail | XX/100 |
| IndexNow | pass/warn/fail | XX/100 |
If DataForSEO MCP tools are available, use on_page_instant_pages for real page analysis (status codes, page timing, broken links, on-page checks), on_page_lighthouse for Lighthouse audits (performance, accessibility, SEO scores), and domain_analytics_technologies_domain_technologies for technology stack detection.
If Google API credentials are configured, use "${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run pagespeed_check.py <url> --json for real PSI + CrUX field data (replaces lab-only CWV estimates), "${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run crux_history.py <url> --json for 25-week CWV trends, and "${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run gsc_inspect.py <url> --json for real indexation status per URL.
url_safety refuses loopback and private addresses by default, so http://localhost:3000 and a staging host on Tailscale fail with "Blocked hostname" or "Blocked IP literal". That default is deliberate: these scripts follow URLs found on the pages they crawl.
To audit a pre-deployment host, the operator names it in CLAUDE_SEO_LOCAL_TARGETS, a comma-separated list of host or host:port entries:
CLAUDE_SEO_LOCAL_TARGETS="localhost:3000,127.0.0.1:8080,100.101.102.103" \
"${CLAUDE_PLUGIN_ROOT}/scripts/claude-seo" run fetch_page.py http://localhost:3000/
What it does and does not cover:
| Behaviour | Allowlisted host |
|---|---|
| First, top-level URL over raw HTTP | Allowed |
| Redirect target reached from that URL | Refused |
| Subresource fetched by a rendered page | Refused |
Playwright renders (--render, screenshots) |
Refused; use the raw-HTTP path |
| A host not named in the variable | Refused |
| Cloud metadata endpoints, even when listed | Refused |
host:port matches that port only; a bare host matches any port. With the variable unset the policy is unchanged. Never suggest setting it for a host the user does not control. See SECURITY.md.
| Scenario | Action |
|---|---|
| URL unreachable | Report connection error with status code. Suggest verifying URL, checking DNS resolution, and confirming the site is publicly accessible. |
| robots.txt not found | Note that no robots.txt was detected at the root domain. Recommend creating one with appropriate directives. Continue audit on remaining categories. |
| HTTPS not configured | Flag as a critical issue. Report whether HTTP is served without redirect, mixed content exists, or SSL certificate is missing/expired. |
| Core Web Vitals data unavailable | Note that CrUX data is not available (common for low-traffic sites). Suggest using Lighthouse lab data as a proxy and recommend increasing traffic before re-testing. |