Automated SEO Audits with Claude Skills: Full Guide
TL;DR: A Claude Skill packages a repeatable task, instructions plus scripts, so Claude can run it consistently without you re-explaining the process every time. Applied to SEO, a skill can crawl a sitemap, check every page for missing meta descriptions, broken internal links, duplicate titles, and slow-loading assets, then produce a plain-language report. Build it once as a SKILL.md file with a clear trigger description, back it with a small script that does the actual checking, and schedule it to run weekly so regressions get caught before they've been live for a month. The audit should check the same things a human reviewer would: title and meta tag presence and length, broken links, sitemap and llms.txt consistency, and duplicate content, then flag only what changed since the last run so the report stays short enough to actually read.
What Is a Claude Skill, and Why Use One for SEO Audits?
A Claude Skill is a folder with a SKILL.md file describing when to use it and how, plus any supporting scripts or reference files the task needs. Claude loads the skill's instructions when the trigger matches, runs the steps, and uses the bundled scripts rather than reinventing the logic from scratch each time.
SEO audits are a good fit for this because they're repetitive by nature: the same twenty checks, run against the same set of pages, week after week. Without a skill, that means re-describing the checklist every time you want an audit done, and getting slightly different results depending on how the request was phrased. With a skill, the checklist is fixed, the script that runs it is fixed, and the only thing that changes between runs is the state of the site.
What Should an Automated SEO Audit Actually Check?
Keep the list focused on things that move rankings or click-through rate, not everything that's theoretically measurable:
- Title tags: present on every page, under roughly 60 characters, and not duplicated across pages.
- Meta descriptions: present, in the 150-160 character range, and not duplicated.
- Broken internal links: any link to a path that returns a 404.
- Heading structure: one H1 per page, no skipped levels.
- Sitemap accuracy: every URL in the sitemap actually resolves, and every published page is actually in the sitemap.
- llms.txt consistency: new sections match what's in the sitemap, so AI crawlers and search engines see the same picture of the site.
- Image alt text: present on content images.
- Page load signals: response time and payload size, as a rough proxy for the things a full Lighthouse run would catch in more depth.
That's a list a script can check mechanically. Anything requiring judgment, like whether the content itself is actually good, stays a human task; the skill's job is to catch the mechanical regressions before they pile up.
How Do You Structure a Claude Skill for Site Audits?
A skill is a directory with a required SKILL.md and whatever else the task needs:
seo-audit-skill/
├── SKILL.md
├── scripts/
│ └── audit.py
└── reference/
└── checklist.md
SKILL.md needs YAML frontmatter with a name and description Claude uses to decide when to trigger it, followed by instructions:
name: seo-audit
description: Run a technical SEO audit across the site, checking meta tags, broken links, sitemap accuracy, and llms.txt consistency. Trigger on request for an SEO audit, site health check, or before a scheduled content push.
# SEO Audit Skill
1. Run `scripts/audit.py` against the site's sitemap URL.
2. Read the JSON output and summarise findings by severity: broken (fix now), warning (fix this week), info (worth knowing).
3. Only report items that are new since the last run, tracked in `reference/last_run.json`.
4. Write the summary as a short report, not a raw dump of every check.
The pattern here matches the plugin structure covered in claude-plugin-from-scratch: a skill is a smaller, focused version of the same idea, packaging one repeatable capability instead of a full set of tools and commands.
How Do You Check for Broken Internal Links Automatically?
The script behind the skill does the actual crawling. A minimal version in Python:
import requests
from urllib.parse import urljoin
import xml.etree.ElementTree as ET
SITE = "https://example.com"
def get_sitemap_urls(sitemap_url):
resp = requests.get(sitemap_url)
root = ET.fromstring(resp.content)
ns = {"ns": "http://www.sitemaps.org/schemas/sitemap/0.9"}
return [loc.text for loc in root.findall(".//ns:loc", ns)]
def check_links(urls):
broken = []
for url in urls:
try:
resp = requests.get(url, timeout=10)
if resp.status_code >= 400:
broken.append((url, resp.status_code))
except requests.RequestException as e:
broken.append((url, str(e)))
return broken
urls = get_sitemap_urls(f"{SITE}/sitemap.xml")
broken = check_links(urls)
for url, status in broken:
print(f"BROKEN: {url} -> {status}")
This checks that every URL in the sitemap resolves. A second pass, crawling each page for its own outgoing links, catches internal links to pages that were removed or renamed but never updated at the source.
How Do You Audit Meta Titles and Descriptions at Scale?
Extend the same script to pull the <title> and meta description from each page and flag anything missing, too long, or duplicated:
from bs4 import BeautifulSoup
def check_meta(url):
resp = requests.get(url, timeout=10)
soup = BeautifulSoup(resp.text, "html.parser")
title = soup.title.string if soup.title else None
desc_tag = soup.find("meta", attrs={"name": "description"})
desc = desc_tag["content"] if desc_tag else None
issues = []
if not title:
issues.append("missing title")
elif len(title) > 60:
issues.append(f"title too long ({len(title)} chars)")
if not desc:
issues.append("missing meta description")
elif not (150 <= len(desc) <= 160):
issues.append(f"meta description length {len(desc)}")
return issues
Run this across every URL from the sitemap, collect duplicates by comparing titles and descriptions across the full set, and the audit now covers the two tags that matter most for click-through rate in search results.
How Do You Verify Your Sitemap and llms.txt Stay in Sync?
A sitemap and an llms.txt file describe the same site to two different audiences: search engine crawlers and AI systems respectively. When a new page ships and only one of them gets updated, the two start disagreeing about what the site actually contains.
The automation pattern for keeping the sitemap current on every deploy is covered in indexnow-sitemap-automation. Extend the audit skill to diff the URLs listed in llms.txt against the sitemap's URL list, and flag anything present in one but not the other. This catches the specific and common failure mode where a new section of the site launches, gets added to the sitemap by the build process automatically, but nobody remembers to also add a line to llms.txt.
How Do You Schedule Recurring Audits?
An audit that only runs when someone remembers to ask for it will drift for months between runs. Schedule it instead, using the recurring task pattern in schedule-recurring-claude-tasks, so it runs weekly without anyone triggering it manually.
A weekly cadence is usually the right balance: frequent enough to catch a broken link before it's been live for a month, infrequent enough that the report stays short and worth reading rather than becoming background noise you learn to ignore.
How Do You Turn Audit Results into a Report You'll Actually Read?
The biggest failure mode for automated audits isn't missing checks, it's reports nobody reads because they're the same forty lines every week. Two changes fix most of that:
Diff against the last run. Store the previous run's results (a JSON file is enough) and only report what's new. A stable site with no new issues should produce a one-line report: "No new issues since last week."
Group by severity, not by check type. A report that lists "3 broken links, 1 missing meta description, 12 pages need alt text" in order of what actually needs fixing first is more useful than the same information organised by which script produced it.
How Does This Fit with GitHub-Based Workflows?
If the site's content and code live in a GitHub repository, as covered in github-integration-claude, the audit skill can open an issue automatically when it finds something broken, rather than only producing a report that has to be read and acted on separately. A broken link becomes a GitHub issue with the URL and status code attached, which puts it in the same queue as every other piece of work rather than a report sitting in a chat log.
For teams running a broader automated content pipeline, the same audit skill slots into a larger agent workflow; see 21-agent-product-pipeline for how a chain of specialised agents can cover SEO alongside content production, design, and launch tasks.
Frequently Asked Questions
Do I need to write the audit script myself, or does Claude generate it?
You can ask Claude to write the initial script, but it's worth keeping it in the repository under version control rather than regenerating it fresh each time. The skill's value comes from consistency: the same checks, the same thresholds, run the same way every week. A script Claude regenerates from scratch on each run risks subtly different logic between runs, which makes it harder to trust a report that says "no new issues."
How is this different from just running a Lighthouse or PageSpeed audit?
Lighthouse and PageSpeed focus on performance and some accessibility signals for a single page at a time. An SEO-focused audit skill checks things across the whole site: sitemap accuracy, duplicate meta tags, broken internal links, and consistency between the sitemap and llms.txt. They're complementary; a thorough setup runs both, and the deployment guidance in deploy-react-app-vercel covers where page-speed checks fit into a Vercel-hosted build.
What should trigger an urgent fix versus a routine one?
Broken links on high-traffic pages and missing title tags are worth fixing immediately, since they directly affect indexing and click-through rate. Minor issues, like a meta description that's five characters over the ideal length, can wait for the next content pass. The severity grouping in the audit report should reflect this, so the first line of the report is always the thing worth acting on today.
Can the same skill audit multiple sites in a portfolio?
Yes, if you parameterise the sitemap URL rather than hardcoding it. Store a small config file listing each site's domain and sitemap path, loop the audit script over that list, and produce one report per site or a combined summary. This is the same pattern worth using for DNS checks across a portfolio, and the two audits pair well on the same weekly schedule.