CI/CD SDK
The SEO Crawler SDK is a standalone CLI binary that runs SEO/GEO checks in your CI/CD pipeline. Catch SEO regressions before they reach production.
Installation
Build from source
git clone https://github.com/booltools/booltools-seo-crawler.git
cd booltools-seo-crawler
make build-sdk
# Binary: bin/seo-crawler
Download release binary
Linux / macOS
# Linux (amd64)
curl -sL https://github.com/booltools/booltools-seo-crawler/releases/latest/download/seo-crawler-linux-amd64 -o seo-crawler
chmod +x seo-crawler
# macOS (Apple Silicon)
curl -sL https://github.com/booltools/booltools-seo-crawler/releases/latest/download/seo-crawler-darwin-arm64 -o seo-crawler
chmod +x seo-crawler
# macOS (Intel)
curl -sL https://github.com/booltools/booltools-seo-crawler/releases/latest/download/seo-crawler-darwin-amd64 -o seo-crawler
chmod +x seo-crawler
Windows
# PowerShell
Invoke-WebRequest -Uri "https://github.com/booltools/booltools-seo-crawler/releases/latest/download/seo-crawler-windows-amd64.exe" -OutFile "seo-crawler.exe"
# Or with curl (available in Windows 10+)
curl -sL https://github.com/booltools/booltools-seo-crawler/releases/latest/download/seo-crawler-windows-amd64.exe -o seo-crawler.exe
On Windows, use seo-crawler.exe instead of
./seo-crawler in all commands below.
Scan Modes
Full mode (live crawl)
Crawls a running server, following links and checking all pages.
seo-crawler --mode=full --url=http://localhost:3000
Static mode (local HTML files)
Analyzes built HTML files directly — no server needed.
seo-crawler --mode=static --dir=./dist
Auto-starting a Dev Server
The SDK can start your dev/preview server before crawling and stop it after:
seo-crawler \
--mode=full \
--start-cmd="npm run dev" \
--wait-for=http://localhost:3000 \
--url=http://localhost:3000
Multiple Servers
When your app depends on both a frontend and a backend (or other services), pass multiple commands and URLs:
# Via CLI flags (comma-separated)
seo-crawler \
--mode=full \
--start-cmd="go run ./cmd/server,npm run dev" \
--wait-for="http://localhost:8080/api/health,http://localhost:3000" \
--url=http://localhost:3000
Or as an array in the YAML config:
mode: full
url: http://localhost:3000
start_cmd:
- "go run ./cmd/server"
- "cd web && npm run dev"
wait_for:
- http://localhost:8080/api/health
- http://localhost:3000
wait_timeout: 90s
fail_on: high
All commands are started in parallel. The crawler waits for every URL
in wait_for before starting. All processes are stopped
when the scan finishes.
Both fields accept a single string or an array in YAML. On the CLI, use comma-separated values.
Configuration File
Create .seo-crawler.yml in your project root:
mode: full
url: http://localhost:3000
start_cmd: "npm run dev"
wait_for: http://localhost:3000
wait_timeout: 60s
fail_on: high
format: text
ignore:
- uses_https
- hsts_header
CLI flags override config file values.
Avoiding port conflicts
If port 3000 is already in use on your machine, use
--port to inject a PORT environment variable
into the --start-cmd process. Make sure
--url and --wait-for match the chosen port:
mode: full
url: http://localhost:3000
start_cmd: "npm run dev"
wait_for: http://localhost:3000
port: 3000
CLI Flags
| Flag | Description | Default |
|---|---|---|
--mode |
static or full |
— |
--dir |
Directory with HTML files (static mode) | — |
--url |
Server URL to crawl (full mode) | — |
--fail-on |
Severity threshold for exit code 1 | high |
--ignore |
Comma-separated rule keys to skip | — |
--only |
Comma-separated rule keys to run exclusively | — |
--start-cmd |
Commands to start servers (comma-separated for multiple) | — |
--wait-for |
URLs to poll until ready (comma-separated for multiple) | — |
--wait-timeout |
Max wait time per URL (e.g. 30s, 1m)
|
30s |
--format |
text or json |
text |
--output |
Write JSON report to file path | — |
--max-pages |
Max pages to crawl (0 = unlimited) | 0 |
--port |
Port to set as PORT env var for
--start-cmd processes
|
— |
--exclude-urls |
Comma-separated URL patterns to exclude (supports
* wildcard)
|
— |
--only-urls |
Comma-separated URL patterns to analyze exclusively (supports
* wildcard)
|
— |
--exclude-noindex |
Skip SEO rules on noindex pages | false |
--config |
Path to config file | .seo-crawler.yml |
URL Filtering
Use --only-urls to analyze only specific pages, or
--exclude-urls to skip pages. Both support
* wildcard patterns.
Only analyze specific pages
# Only analyze marketplace pages
seo-crawler --mode=full --url=http://localhost:3000 --only-urls="/marketplace/*"
# Only analyze blog and product pages
seo-crawler --mode=full --url=http://localhost:3000 --only-urls="/blog/*,/products/*"
# Analyze a specific route
seo-crawler --mode=full --url=http://localhost:3000 --only-urls="/pricing"
Exclude pages from analysis
# Skip admin and API pages
seo-crawler --mode=full --url=http://localhost:3000 --exclude-urls="/admin/*,/api/*"
# Skip legal pages
seo-crawler --mode=full --url=http://localhost:3000 --exclude-urls="/privacy,/terms"
YAML config
mode: full
url: http://localhost:3000
only_urls:
- /marketplace/*
- /blog/*
# Or exclude specific paths:
# exclude_urls:
# - /admin/*
# - /api/*
Exit Codes
| Code | Meaning |
|---|---|
0 |
All checks pass (no issues at or above threshold) |
1 |
Issues found at or above --fail-on severity |
2 |
Configuration error |
GitHub Action
The SDK is available as a GitHub Action. Add it directly to your workflow:
name: SEO Audit
on: [pull_request]
jobs:
seo:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"
- run: npm ci
- name: SEO Audit
uses: booltools/booltools-seo-crawler@v0
with:
mode: full
start-cmd: "npm run dev"
wait-for: http://localhost:3000
url: http://localhost:3000
fail-on: high
Static mode (no server needed)
- run: npm run build
- name: SEO Audit
uses: booltools/booltools-seo-crawler@v0
with:
mode: static
dir: ./dist
fail-on: high
Action Inputs
| Input | Description | Default |
|---|---|---|
mode |
static or full (required) |
— |
url |
URL to crawl (full mode) | — |
dir |
HTML directory (static mode) | — |
fail-on |
Severity threshold | high |
ignore |
Comma-separated rule keys to skip | — |
only |
Comma-separated rule keys to run | — |
start-cmd |
Commands to start servers | — |
wait-for |
URLs to poll until ready | — |
wait-timeout |
Max wait time | 30s |
max-pages |
Max pages to crawl (0 = unlimited) | 0 |
port |
Port for --start-cmd processes |
— |
version |
SDK version to use | latest |
Action Outputs
| Output | Description |
|---|---|
passed |
Number of rules that passed |
issues |
Number of issues found |
exit-code |
0 = pass, 1 = fail, 2 = config error |
Manual Setup (without the Action)
If you prefer to download the binary directly:
name: SEO Audit
on: [push, pull_request]
jobs:
seo-audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"
- run: npm ci
- name: Download SEO Crawler SDK
run: |
curl -sL https://github.com/booltools/booltools-seo-crawler/releases/latest/download/seo-crawler-linux-amd64 -o seo-crawler
chmod +x seo-crawler
- name: Run SEO audit
run: |
./seo-crawler \
--mode=full \
--start-cmd="npm run dev" \
--wait-for=http://localhost:3000 \
--url=http://localhost:3000 \
--fail-on=high
Ignoring Rules for Localhost
When testing localhost, some rules will always fail (e.g. HTTPS, HSTS). Ignore them in your config:
ignore:
- uses_https
- hsts_header
- mixed_content