AI-native SEO audits from your terminal or any MCP client. Crawlmind crawls a website, finds technical SEO problems, and goes further than other crawlers: it suggests the internal links you should add, measures page speed per template instead of per page, and shows what changed between two crawls.
- Internal link suggestions. Local multilingual embeddings find pages that are about the same thing but not linked, and point to the paragraph where a link fits and the words that could become its anchor. They also detect keyword cannibalization.
- Speed by template. Every crawled page gets TTFB and download timings. Pages are grouped into templates, and Lighthouse (via the PageSpeed Insights API) runs only on one or two representatives of each, so one fix covers thousands of pages.
- Crawl diffs. Compare two crawls of the same site: new 404s, pages that lost inlinks, TTFB regressions, changed titles and canonicals.
Requires Node.js 22 or newer.
Claude Code:
claude mcp add crawlmind -- npx -y crawlmind-mcpClaude Desktop, Cursor and other clients (JSON config):
{
"mcpServers": {
"crawlmind": {
"command": "npx",
"args": ["-y", "crawlmind-mcp"]
}
}
}crawlmind-mcp is a shortcut for crawlmind mcp; both start the same server over stdio.
For internal link suggestions, add the embeddings add-on (see
below).
Then ask your AI client:
- "Audit https://example.com and give me the top 10 fixes."
- "Which internal links should I add to my blog?"
- "Which templates on my shop are slow on mobile?"
- "Crawl the site again and tell me what broke since last week."
- "Export an HTML report of the last crawl to ~/Desktop/audit.html."
npx crawlmind --help
# or
npm install -g crawlmindcrawlmind crawl https://example.com # crawl with live progress, then a summary
crawlmind crawl https://example.com -n 2000 # up to 2,000 pages
crawlmind summary # key numbers and top issues of the latest crawl
crawlmind issues --severity critical # issues with examples
crawlmind issues --check links.broken_internal # every affected URL of one check
crawlmind page /pricing # everything about one URL
crawlmind links /pricing --content-only # who links here, from the main content
crawlmind top --by underlinked # important pages that need more links
crawlmind suggest # internal links to add (needs the embeddings add-on)
crawlmind suggest --target /pricing # links that should point to one page
crawlmind cannibalization # pages competing for the same topic
crawlmind templates # page templates with TTFB per template
crawlmind speed # PageSpeed Insights on template representatives
crawlmind diff # what changed between the two latest crawls
crawlmind report -o audit.html # self-contained HTML report (or -f md)
crawlmind sql "SELECT url, ttfb_ms FROM pages ORDER BY ttfb_ms DESC LIMIT 10"
crawlmind crawls # past crawlsEvery command takes --json for machine-readable output (progress goes to stderr). In CI,
crawlmind crawl <url> --fail-on critical exits with code 1 when critical issues are found.
The CLI and the MCP server share one local database, so you can crawl from the terminal and then ask your AI client about the result.
| Package | What it is |
|---|---|
crawlmind |
Engine, CLI (crawlmind) and MCP server |
crawlmind-mcp |
Shortcut binary that runs crawlmind mcp |
| Tool | What it does |
|---|---|
start_crawl |
Start a background crawl and return its crawl_id |
get_crawl_status |
Progress of a crawl; wait_seconds waits and streams progress |
cancel_crawl |
Stop a running crawl, keeping the pages fetched so far |
list_crawls |
Past and running crawls, filterable by site |
get_summary |
Key numbers and top issues by severity, with examples and recommendations |
get_issues |
Issues filtered by severity; with check_id, every affected URL (paginated) |
get_page |
Everything about one URL: status, redirects, metadata, timings, link metrics |
get_links |
Inlinks or outlinks of a URL with anchors, rel and placement |
get_top_pages |
Pages by PageRank, inlinks, depth, TTFB, or underlinked important pages |
get_templates |
Templates with page counts, TTFB median/p90 and PageSpeed results |
measure_templates |
Lighthouse (PageSpeed Insights) on 1–2 representatives per template |
suggest_links |
Internal links to add: source page, paragraph and anchor candidates |
find_cannibalization |
Page pairs that compete for the same topic |
compare_crawls |
Diff two crawls: new and fixed errors, lost inlinks, TTFB regressions |
export_report |
Write a self-contained HTML or Markdown report to a file |
query_data |
Read-only SQL SELECT on the crawl database, row-limited |
ping |
Health check |
Prompts: seo_audit runs the full audit workflow and ends with a prioritized fix list;
internal_linking_plan turns link suggestions into a table of links to add.
Resources: crawlmind://checks/{id} documents each check (why it matters, how to fix), and
crawlmind://crawls/{id}/summary gives the summary of a crawl.
Every issue has the same shape: id, severity (critical, warning, info), title, count,
up to five examples and a recommendation.
| Area | Checks |
|---|---|
| Status | 4xx and 5xx pages, unreachable pages |
| Links | broken internal and external links, links to redirects, internal nofollow, generic and empty anchors |
| Redirects | chains longer than one hop, loops |
| Sitemap | orphan pages, noindex pages listed, non-200 URLs listed |
| Canonical | canonical to an error page, to a redirect, to a different page |
| Content | missing or duplicate titles, meta descriptions and H1, thin content (default < 200 words) |
| Structure | pages more than 3 clicks deep |
| Speed | TTFB over 800 ms, HTML over 1 MB, mixed content |
Generic anchors ("click here", "read more", "подробнее", "mehr erfahren", …) are listed per
language in generic-anchors.ts.
Inlinks and outlinks are counted per page and by placement (nav, header, footer, main, other),
with links through redirects credited to the final page. Click depth is a breadth-first search
from the start URL. Internal PageRank uses damping 0.85, spreads the rank of pages without
outlinks evenly, ignores nofollow, and iterates until the total change is below 1e-6;
scores are shown 0–100 relative to the strongest page.
Crawlmind embeds every indexable page (title, H1 and the start of the main content) with a local model and looks for pages that are about the same topic as a target but do not link to it yet. For each pair it returns:
- the paragraph of the source page that fits the target best (paragraphs of the main content are embedded separately),
- anchor candidates: phrases from that paragraph that share key words with the target's
title and H1, matched by word prefixes so inflected forms count (
беговые кроссовкиfor "Лучшие беговые кроссовки"), - the similarity and the target's content inlinks and PageRank.
Without a target, the most link-worthy pages come first: rank =
similarity × (1 + importance / (1 + content inlinks)), where importance is the larger of the
page's relative PageRank and its sitemap priority. Crawlmind never writes the final sentence;
your AI client does, from this context. No API keys are involved.
Cannibalization: pairs of indexable pages whose embeddings are at least 0.92 similar and whose title/H1 key words overlap by at least 50%.
The model runs locally with transformers.js. Its ONNX runtime is several hundred megabytes, so it is an optional peer dependency and everything else works without it. To enable link suggestions:
npm install -g crawlmind @huggingface/transformers
# or, without installing:
npx -p crawlmind -p @huggingface/transformers crawlmind suggestFor MCP clients:
claude mcp add crawlmind -- npx -y -p crawlmind-mcp -p @huggingface/transformers crawlmind-mcpThe model is downloaded once (about 120 MB) into ~/.crawlmind/models. Page vectors are stored
per crawl; paragraph vectors are computed only for pages that appear in suggestions.
Model choice. Xenova/multilingual-e5-small
(8-bit quantized, 384 dimensions) covers about 100 languages, which matters for sites that are
not in English, and is strong at retrieval for its size: it is the smallest of the e5 family
that clearly beats older multilingual MiniLM models on retrieval benchmarks, while still
embedding hundreds of pages per minute on a laptop CPU. Its cosine similarities cluster high,
so the default thresholds (0.82 for suggestions, 0.92 for cannibalization) are tuned for it.
Every crawled page gets its time to first byte and download time. Pages are then grouped into templates, and Lighthouse runs only on one or two representatives per template, so a site with thousands of product pages needs a handful of PageSpeed Insights calls instead of thousands:
3,400 pages use template
/product/*with mobile LCP 4.2 s (real-user, poor), score 38. Fixing this one template improves all of them.
How pages are grouped:
- URL pattern. Path segments are compared level by level. Numbers, dates, UUIDs, hex ids
and long slugs become
*; siblings that differ only in digits (post-1,post-2) become*; below the first level, four or more distinct sibling values become*. First-level sections (/blog,/shop) are never merged by count alone. - DOM structure. Each page's skeleton (the set of tag paths below
<body>, six levels deep, ignoring text and attributes) is reduced to a 32-value MinHash signature. Within one URL pattern, pages whose estimated Jaccard similarity is at least 0.8 form one template, so/p/*pages with two different layouts become two templates. - Representatives are the pages whose TTFB is closest to the template median: typical, not the best or worst case.
PageSpeed Insights runs on demand (measure_templates / crawlmind speed), mobile by default,
with a 60 s timeout and retries with backoff. Results (performance score, LCP, CLS, TBT, FCP,
page weight and CrUX field data when Google has it) are stored per crawl and reused. Without
PSI_API_KEY Crawlmind uses Google's shared keyless quota one request at a time, which is
often exhausted; a free API key
raises it.
Crawls are kept, so any two crawls of a site can be compared (compare_crawls,
crawlmind diff): new and fixed 4xx/5xx pages, new and fixed broken links, pages added and
removed, the pages that gained or lost the most inlinks, TTFB regressions (at least 200 ms and
50% slower), title and canonical changes, and how each issue count moved. A warning is added
when the crawls differ much in size, since "removed" pages may just not have been reached.
Reports (export_report, crawlmind report) contain the summary, every issue with up to ten
examples and its fix, under-linked important pages, speed by template, and the strongest and
slowest pages. The HTML version is a single file with inline CSS, no scripts, light and dark
themes, and works on phones. A report never replaces an existing file unless asked to, and
never writes through a symbolic link. MCP clients write only inside ~/.crawlmind/reports
unless the server runs with CRAWLMIND_ALLOW_REPORT_PATHS=1, so instructions hidden in a
crawled page cannot make the AI client overwrite your files.
| Variable | Purpose |
|---|---|
CRAWLMIND_HOME |
Data directory (default ~/.crawlmind) |
PSI_API_KEY |
PageSpeed Insights API key |
CRAWLMIND_ALLOW_PRIVATE_NETWORKS |
1 lets MCP clients crawl private and local addresses |
CRAWLMIND_LOG_LEVEL |
debug, info, warn (default), error or silent; logs go to stderr |
CRAWLMIND_ALLOW_REPORT_PATHS |
1 lets MCP clients write reports outside ~/.crawlmind/reports |
- Identifies itself as
CrawlmindBot/<version> (+https://github.com/Everhard/crawlmind). - Follows robots.txt, including
Crawl-delay(capped at 10 s), unless told not to. - Defaults: 500 pages (hard cap 10,000), depth 10, 4 parallel requests, 250 ms between requests to the same host, 15 s timeout, 5 MB per page.
- Only
text/htmlis parsed. Sitemaps (from robots.txt and/sitemap.xml, indexes and gzip included) add URLs that links do not reach. - Refuses private, loopback and link-local addresses, checked on every connection and redirect
hop (DNS rebinding included). For intranet or local sites use
--allow-privatein the CLI. MCP clients may only setallowPrivateNetworkswhen the server runs withCRAWLMIND_ALLOW_PRIVATE_NETWORKS=1, so a prompt injection on a crawled page cannot turn the AI client into a local network scanner.
- No JavaScript rendering: pages are analyzed as the server sends them. Sites that build their content in the browser show up nearly empty.
- One site per crawl (optionally with subdomains), up to 10,000 pages.
- Crawlmind only reads. No tool changes the audited site.
Everything stays on your machine, in ~/.crawlmind (override with CRAWLMIND_HOME). Crawlmind
contacts only the site you crawl, the PageSpeed Insights API when you measure templates, and
Hugging Face once to download the embedding model when you first use link suggestions. No
telemetry.
npm install
npm run build
npm run lint && npm run typecheck && npm testTry the MCP server in the official inspector:
npx @modelcontextprotocol/inspector node packages/crawlmind/dist/cli.js mcpLayout: packages/crawlmind/src/core is the engine (crawler, storage, analysis, speed,
embeddings, report, diff) and never imports the MCP SDK or CLI libraries; src/mcp and
src/cli are thin layers over it.
See CONTRIBUTING.md.
MIT © 2026 Andrew Dorokhov