Skip to content

Repository files navigation

RaptorProto

Autonomous SEO audit engine with AI-driven analysis.

RaptorProto is a proof of concept for a fully autonomous SEO pipeline: crawl any website, render JavaScript-heavy pages via Cloudflare Browser Rendering, and feed structured audit data directly to Claude for intelligent analysis, recommendations, and ongoing monitoring -- all orchestrated through a REST API and MCP (Model Context Protocol) integration.

Built by Nick Mangubat, founder of Ravana Solutions, a Norfolk, Virginia web design and SEO studio. This prototype grew into Raptor, the audit toolkit behind every Ravana engagement — read the full story in the Raptor case study.

  ┌─────────────────────────────────────────────────────────────────┐
  │                                                                 │
  │   Website  ──►  Raptor Crawler  ──►  Structured SEO Data       │
  │                      │                       │                  │
  │              Cloudflare Browser               │                  │
  │              Rendering (JS/SPA)               ▼                  │
  │                                        Claude API / MCP         │
  │                                          │         │            │
  │                                   REST API    MCP Server        │
  │                                   (direct)    (agentic)         │
  │                                          │         │            │
  │                                    Prioritized     Autonomous   │
  │                                    Fix Plans       Monitoring   │
  │                                                                 │
  └─────────────────────────────────────────────────────────────────┘

Table of Contents


What This Proves

  1. A Rust-native crawler can produce structured, machine-readable SEO audit data at scale. 114+ analyzers, health scoring, and multi-format reports -- all in seconds, not minutes.

  2. Cloudflare Browser Rendering closes the SPA gap. JS-heavy sites that return empty shells to traditional crawlers are fully rendered before analysis. Screenshots, entity extraction, and static-vs-rendered comparisons come free.

  3. The output is purpose-built for AI consumption. Raptor's structured JSON is designed to be fed directly into Claude via REST API for on-demand analysis, or exposed as an MCP server for agentic workflows where Claude autonomously crawls, analyzes, and acts.


The Crawler

The core engine is written in Rust using async I/O (tokio) for high-throughput concurrent crawling.

How It Works

Seed URL
   │
   ▼
┌──────────────────────────────────────────────────┐
│  Crawl Queue (BFS, depth-bounded)                │
│  ┌──────────┐  ┌───────────┐  ┌───────────────┐ │
│  │ Fetcher  │  │  Parser   │  │  URL Resolver │ │
│  │ (reqwest │──│ (scraper  │──│ (normalize,   │ │
│  │  async)  │  │  HTML)    │  │  dedup, scope)│ │
│  └──────────┘  └───────────┘  └───────────────┘ │
└──────────────────────────────────────────────────┘
   │
   ▼
┌──────────────────────────────────────────────────┐
│  Analysis Pipeline (114+ checks)                 │
│                                                  │
│  Technical    On-Page       Structured Data      │
│  ─────────   ────────      ───────────────       │
│  Canonicals   Titles        JSON-LD              │
│  Directives   Meta desc     Microdata            │
│  Status codes Headings      Open Graph           │
│  Security     Content                            │
│  URL issues   Images        Links & Hreflang     │
│  Sitemaps     Readability   Internal/External    │
└──────────────────────────────────────────────────┘
   │
   ▼
┌──────────────────────────────────────────────────┐
│  Scoring Engine                                  │
│  100-point scale, per-issue deductions with caps │
│  Grades: A (90+), B (80+), C (70+), D (60+), F  │
└──────────────────────────────────────────────────┘
   │
   ▼
┌──────────────────────────────────────────────────┐
│  Report Generation                               │
│                                                  │
│  JSON ─── machine-readable, Claude-ready         │
│  HTML ─── self-contained, offline-capable        │
│  CSV  ─── spreadsheet export                     │
│  SVG  ─── site structure visualization           │
└──────────────────────────────────────────────────┘

Key Capabilities

Feature Detail
Async concurrent crawling Configurable concurrency (default 3), semaphore-bounded
robots.txt compliance Honors rules, crawl-delay, disallow patterns
Sitemap discovery Parses sitemap.xml/sitemap index for URL seeding
Depth + page limits Configurable max depth (10) and max pages (500)
114+ SEO analyzers Titles, meta, headings, images, links, structured data, security headers, canonicals, hreflang, content quality
Health scoring 0-100 scale with per-issue weighted deductions and category caps
Self-contained HTML reports Single file, zero external dependencies, works offline
Event-driven architecture CrawlEvent channel decouples engine from UI -- reusable as a library

Example

raptor crawl https://example.com --max-pages 100 --concurrency 5

# Output:
#   JSON  crawl-example.com-2026-04-09.json    (structured audit data)
#   HTML  crawl-example.com-2026-04-09.html    (visual report)

Cloudflare Browser Rendering

Modern SPAs (React, Vue, Angular, Next.js) return skeleton HTML to crawlers. The real content only exists after JavaScript executes. Raptor integrates Cloudflare Browser Rendering to close this gap -- entirely optional, zero local dependencies.

Capabilities

Command What It Does
raptor crawl --backend cloudflare Full JS-rendered crawl -- pages loaded in headless Chromium on Cloudflare's edge, then analyzed by all 114+ checks
raptor screenshot <url> Pixel-perfect full-page captures at any viewport size
raptor inspect <url> --compare Side-by-side static vs. JS-rendered audit -- reveals content invisible to traditional crawlers
raptor extract <url> --preset seo AI-powered entity extraction (business name, phone, address, services, hours) using Workers AI

How the Hybrid Crawl Works

                    ┌──────────────────────────────┐
                    │  Raptor submits seed URL to   │
                    │  CF /crawl endpoint           │
                    └──────────────┬───────────────┘
                                   │
                    ┌──────────────▼───────────────┐
                    │  Cloudflare renders pages in  │
                    │  headless Chromium (JS runs)  │
                    │  Discovers + follows links    │
                    └──────────────┬───────────────┘
                                   │
                    ┌──────────────▼───────────────┐
                    │  Raptor retrieves rendered    │
                    │  HTML via cursor pagination   │
                    └──────────────┬───────────────┘
                                   │
                    ┌──────────────▼───────────────┐
                    │  Parallel security header     │
                    │  fetch (HSTS, CSP, XFO)       │
                    └──────────────┬───────────────┘
                                   │
                    ┌──────────────▼───────────────┐
                    │  Same 114+ analyzers run on   │
                    │  rendered HTML. Same reports.  │
                    └──────────────────────────────┘

Static vs. Rendered Comparison

The inspect --compare command demonstrates why this matters:

  ┌────────────────────┬──────────────┬──────────────┐
  │ Check              │ Static       │ Rendered     │
  ├────────────────────┼──────────────┼──────────────┤
  │ Title              │ (empty)      │ My SPA App   │
  │ Meta description   │ (empty)      │ Welcome to…  │
  │ H1 count           │ 0            │ 1            │
  │ Word count         │ 12           │ 847          │
  └────────────────────┴──────────────┴──────────────┘

A traditional crawler sees 12 words. Cloudflare rendering reveals 847. That gap is exactly what search engines penalize, and exactly what Raptor surfaces.

Free Tier

Cloudflare's free plan includes 10 minutes of browser time per day -- enough for 100-200 pages per crawl session. No credit card required.


Claude Integration: REST API + MCP

This is where Raptor becomes more than a crawler. The structured JSON output is designed to be consumed directly by Claude for AI-driven SEO analysis.

Approach 1: REST API (Direct Analysis)

Raptor's JSON output feeds directly into the Claude API (Anthropic REST) for on-demand, intelligent analysis that goes far beyond rule-based checks.

┌─────────────┐       ┌──────────────────┐       ┌──────────────┐
│  raptor      │       │  Orchestrator    │       │  Claude API  │
│  crawl       │──────►│  (service layer) │──────►│  (Anthropic) │
│  --json      │ JSON  │                  │ REST  │              │
└─────────────┘       │  Sends crawl     │       │  Returns:    │
                       │  data + prompt   │       │  - Analysis  │
                       │  template        │◄──────│  - Fix plan  │
                       └──────────────────┘       │  - Priority  │
                                                  └──────────────┘

What Claude adds on top of Raptor's raw audit:

Raptor Produces Claude Interprets
"47 images missing alt text" "The product gallery on /shop uses decorative images that don't need alt text, but 12 hero images on landing pages are missing descriptive alt -- those are the priority."
"Health score: 72 (C)" "The score is dragged down by 3 redirect chains on your highest-traffic pages. Fixing those alone would push you to B+."
"Missing meta descriptions on 23 pages" "These 23 pages share a /blog/draft URL pattern -- they may be unpublished drafts indexed by mistake. Verify they should be public before writing descriptions."
"Duplicate title tags on 8 pages" "All 8 are paginated category pages (/shoes?page=2, /shoes?page=3). Append the page number to each title to differentiate them."

Implementation pattern:

// Raptor outputs structured JSON
let crawl_result: CrawlResult = raptor_core::crawler::crawl(config, tx).await?;
let json = serde_json::to_string(&crawl_result)?;

// Feed into Claude API with a domain-specific prompt
let response = anthropic_client
    .messages()
    .create(MessageRequest {
        model: "claude-sonnet-4-20250514",
        messages: vec![Message {
            role: "user",
            content: format!(
                "Analyze this SEO audit and produce a prioritized action plan. \
                 Focus on fixes with the highest traffic impact first.\n\n{}",
                json
            ),
        }],
        max_tokens: 4096,
    })
    .await?;

Approach 2: MCP Server (Agentic Workflows)

The more powerful pattern: expose Raptor as an MCP (Model Context Protocol) server, giving Claude direct access to crawl, inspect, and extract as tools it can invoke autonomously.

┌───────────────────────────────────────────────────────┐
│  Claude (MCP Client)                                  │
│                                                       │
│  "Audit example.com, then check if the top 3 issues  │
│   are also present on their staging site."            │
│                                                       │
│  Tool calls:                                          │
│  ┌─────────────────────────────────────────────────┐  │
│  │ 1. raptor_crawl(url: "example.com")             │  │
│  │ 2. raptor_inspect(url: "staging.example.com",   │  │
│  │       compare: true)                            │  │
│  │ 3. raptor_extract(url: "example.com/contact",   │  │
│  │       preset: "seo")                            │  │
│  └─────────────────────────────────────────────────┘  │
│                                                       │
│  Claude reasons over the combined results and         │
│  produces a unified analysis without human prompting. │
└───────────────────────────────────────────────────────┘
         │              │              │
         ▼              ▼              ▼
┌─────────────────────────────────────────────────────┐
│  Raptor MCP Server                                  │
│                                                     │
│  Tools exposed:                                     │
│  ─────────────                                      │
│  raptor_crawl      Full site crawl → JSON           │
│  raptor_inspect    Single-page audit (3 modes)      │
│  raptor_screenshot Full-page capture → image        │
│  raptor_extract    Entity extraction → JSON         │
│  raptor_compare    Diff two crawl snapshots         │
│                                                     │
│  Resources exposed:                                 │
│  ─────────────────                                  │
│  Recent crawl results (read-only)                   │
│  Issue category definitions                         │
│  Scoring algorithm reference                        │
│                                                     │
│  Transport: stdio or SSE                            │
└─────────────────────────────────────────────────────┘

MCP unlocks agentic workflows like:

Workflow What Happens
Competitive audit "Compare our site against 3 competitors" -- Claude crawls all 4, cross-references scores, identifies gaps
Regression monitoring "Crawl weekly and alert if score drops" -- Claude diffs snapshots, flags regressions, explains root cause
SPA pre-launch check "Verify the React app is crawlable" -- Claude runs inspect --compare, checks for content gaps between static and rendered
Local SEO extraction "Pull business data from these 50 competitor pages" -- Claude calls extract in a loop, normalizes results into a spreadsheet
Fix verification "Re-crawl after deploy and confirm issues are resolved" -- Claude compares before/after, confirms fixes, flags new issues

MCP server definition (planned):

{
  "mcpServers": {
    "raptor": {
      "command": "raptor",
      "args": ["mcp-server"],
      "env": {
        "CLOUDFLARE_ACCOUNT_ID": "...",
        "CLOUDFLARE_API_TOKEN": "..."
      }
    }
  }
}

Architecture

RaptorProto/
├── raptor-core/                 Core Rust library (zero CLI coupling)
│   └── src/
│       ├── crawler/             Async fetcher, parser, queue, robots.txt, sitemaps
│       ├── analysis/            114+ SEO analyzers + scoring engine
│       ├── cloudflare/          CF Browser Rendering client (crawl, screenshot, inspect, extract)
│       ├── report/              JSON, HTML, CSV, SVG report generators
│       ├── models/              CrawlConfig, CrawlResult, PageData, CrawlEvent
│       └── utils/               Readability scoring, text analysis
│
├── raptor-cli/                  CLI binary (clap-based, dispatches to core)
│   └── src/main.rs              Dashboard, subcommands, progress bars
│
├── templates/                   Minijinja HTML templates (compiled into binary)
│   ├── crawl-report.html        Full report with sidebar, tabs, charts
│   ├── components/              Overview, Issues, Pages, Structure tabs
│   ├── styles/                  Light theme CSS
│   └── mascot.svg               Raptor mascot (mood changes with score)
│
├── python/                      Companion analysis tools
│   ├── raptor-entity/           NER + Semantic Density Index (spaCy)
│   ├── raptor-link/             Internal link graph visualization
│   ├── raptor-fossil/           Historical SERP tracking (Wayback Machine)
│   └── raptor-common/           Shared console styling
│
└── docs/
    └── cloudflare.md            Cloudflare integration setup guide

Design Principles

  • Library-first. raptor-core is a standalone Rust library with no CLI coupling. It communicates via CrawlEvent channels, making it embeddable in any service -- including an MCP server.
  • Structured output. Every crawl produces machine-readable JSON following a consistent schema. This is what makes the Claude integration viable without any data transformation layer.
  • Cloudflare is optional. The core crawler, all 114 analyzers, scoring, and reporting work without it. CF integration is behind a Cargo feature flag (cloudflare, enabled by default).
  • Self-contained reports. HTML reports are single files with all CSS, JS, and SVG inlined. No CDN. Works offline.
  • Responsible crawling. Honors robots.txt, polite delays, exponential backoff, rate limiting by default.

Current Status

Component Status
Rust crawler engine Production-ready (v0.2.0)
114+ SEO analyzers Complete
Health scoring + grading Complete
HTML/JSON/CSV/SVG reports Complete
Cloudflare Browser Rendering Complete (crawl, screenshot, inspect, extract)
Python NER/link/fossil tools Complete
Claude REST API integration Designed, ready to implement
MCP server Designed, ready to implement

Getting Started

Prerequisites

  • Rust 1.70+ (for building from source)
  • Python 3.10+ (for entity, link, and fossil analysis tools)
  • Cloudflare account (free tier, optional -- only for JS rendering features)

Build

git clone <repo-url> RaptorProto
cd RaptorProto
cargo build --release

Run

# Crawl a site
./target/release/raptor crawl https://example.com

# JS-rendered crawl (requires Cloudflare credentials)
export CLOUDFLARE_ACCOUNT_ID="your-id"
export CLOUDFLARE_API_TOKEN="your-token"
./target/release/raptor crawl https://example.com --backend cloudflare

# Single-page audit: static vs rendered comparison
./target/release/raptor inspect https://example.com --compare

# Screenshot
./target/release/raptor screenshot https://example.com

# Entity extraction
./target/release/raptor extract https://example.com --preset seo

License

MIT

About

Autonomous SEO audit engine with AI-driven analysis — Rust crawler, Cloudflare Browser Rendering, Claude REST API + MCP integration

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages