Skip to main content

Local-first desktop SEO crawler

Project description

xseo

CI License: MIT Python 3.12+

A local-first desktop SEO crawler. Audit your site on your own machine — no cloud, no accounts, no data leaves your computer.

xseo is a desktop application that crawls a website, extracts on-page SEO signals, detects common issues and content duplication, and renders the results in a clean UI. Everything runs locally and persists to a single SQLite file under ~/.xseo/.

xseo crawling a site live

xseo issues view

Features

  • Live crawling with a real-time progress view and a threaded background worker that keeps the UI responsive.
  • Polite by default — respects robots.txt and applies a configurable per-request delay so you don't hammer the sites you audit.
  • On-page extraction of titles, meta descriptions, headings, canonicals, robots directives, internal/external links, and more via selectolax.
  • Issue detection for missing/duplicate titles and descriptions, thin content, heading problems, broken links, and other common SEO defects.
  • Duplicate content detection through content hashing and grouped read models.
  • Sortable result tables for pages, issues, and duplicate groups, with a double-click page detail dialog.
  • Headless CLI (xseo crawl <url>) that runs the same engine without the GUI — JSON/CSV reports and a --fail-on exit code, so you can gate CI on SEO regressions.
  • CSV export for every result view, so you can pipe findings into spreadsheets or other tools.
  • Local persistence in SQLite at ~/.xseo/xseo.sqlite3. The last crawl is restored automatically on launch.
  • Clean architecture — domain, application, and adapter layers are strictly separated, with ports/adapters for HTTP, persistence, export, and the UI.

Screenshots

Configure a crawl, then watch progress stream in live:

Control Progress
Control panel Live progress

Review crawled pages, detected issues, and duplicate content groups:

Pages Duplicates
Pages table Duplicate groups

Double-click any page for full detail — headings, links, redirects, and per-page issues:

Page detail dialog

Tech stack

  • Python 3.12+
  • PySide6 for the desktop UI
  • httpx for HTTP fetching
  • selectolax for fast HTML parsing
  • SQLite for local storage
  • pytest, hypothesis, and pytest-qt for unit, property-based, and UI tests

Install

Download a ready-to-run build (no Python needed)

Download the build for your OS, unzip it, and run the xseo executable inside:

OS Download
macOS (Apple Silicon) xseo-macos-arm64.zip
Windows (x64) xseo-windows-x64.zip
Linux (x64) xseo-linux-x64.zip

These links always point to the most recent release. You can also browse every build on the Releases page.

The builds are not code-signed yet, so the OS may warn you the first time:

  • macOS: right-click the app → OpenOpen (or System Settings → Privacy & Security → Open Anyway).
  • Windows: on the SmartScreen prompt, click More info → Run anyway.

Install from PyPI (for Python users)

pipx install xseo   # isolated, recommended
# or
pip install xseo

Then launch with xseo-ui. Requires Python 3.12 or newer.

From source

python3 -m pip install -e '.[test]'

Run

Launch the desktop UI:

xseo-ui

Or from the source tree:

python3 -m xseo.ui.app

Enter a URL, click Start Crawl, and watch the progress tab fill in. When the crawl finishes, browse pages, issues, and duplicate groups in their respective tabs. Double-click any page row for full detail, or export any view to CSV.

Command line

xseo also runs headless — no GUI, scriptable, and CI-friendly. It uses the same crawl engine and the same SQLite store as the desktop app, so you can audit from the terminal and still open the results in the UI later.

xseo crawl https://example.com/
Crawling https://example.com/ …

Crawled 142 pages, found 38 issues

  HIGH       3  broken_internal_link
  MEDIUM    12  meta_description_missing
  LOW       22  thin_content

Write a machine-readable report, or pipe JSON straight to another tool:

xseo crawl https://example.com/ --out report.json      # full JSON report
xseo crawl https://example.com/ --out - | jq '.summary' # JSON to stdout
xseo crawl https://example.com/ --format csv --out issues.csv

Use it as a build gate — --fail-on makes the command exit non-zero when an issue at or above the given severity is found, so a regression breaks CI:

xseo crawl https://example.com/ --fail-on high

Other flags: --limit, --delay, --timeout, --no-robots, --all-hosts, --db. Run xseo crawl --help for the full list.

Verify

python3 -m compileall src tests
python3 -m pytest -q

The current suite has 165 tests covering domain logic, adapters, integration, property-based invariants, CLI behavior, and UI smoke tests.

Project layout

src/xseo/
├── domain/         # entities, value objects, ports, validation, events
│   ├── crawler/    # frontier + crawl engine
│   ├── extraction/ # HTML extraction
│   ├── analysis/   # SEO issue detection
│   └── duplicates/ # content duplicate detection
├── application/    # services, commands, queries, read models
├── adapters/       # HTTP, persistence, export, background worker, event bridge
└── ui/             # PySide6 app, widgets, controller

Contributing

Contributions are welcome — see CONTRIBUTING.md for dev setup, how to run the checks (ruff + pytest), and the project conventions.

About

I built xseo because I needed it. I was starting a new project and wanted a fast way to scan it for SEO issues without uploading URLs to a third-party tool, paying for another subscription, or fighting a heavy web dashboard. I wanted something that ran on my desktop, was honest about what it found, and stored results in a file I owned — so I wrote it, and I'm sharing it in case it's useful to anyone else who wants a small, local, hackable SEO crawler.

This is an early prototype. It works end-to-end and I use it on my own projects, but expect rough edges. Issues and PRs are welcome.

Built by Yuri Silva — @yurisilvapi on X/Twitter.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xseo-0.4.0.tar.gz (52.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

xseo-0.4.0-py3-none-any.whl (73.0 kB view details)

Uploaded Python 3

File details

Details for the file xseo-0.4.0.tar.gz.

File metadata

  • Download URL: xseo-0.4.0.tar.gz
  • Upload date:
  • Size: 52.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for xseo-0.4.0.tar.gz
Algorithm Hash digest
SHA256 02e288fd184748d0ea8e01b78345f831bd409d4373986d08b6c6d717df05c1aa
MD5 70a4ae6c90bc5aab069f6bda9b07b88a
BLAKE2b-256 1f2a2004a90e4ae3a2772d53bac86b4915857b177762b10751f21225a1acbb96

See more details on using hashes here.

Provenance

The following attestation bundles were made for xseo-0.4.0.tar.gz:

Publisher: release-please.yml on yuripinto/xseo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xseo-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: xseo-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 73.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for xseo-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 da6a7fff1629d36ca825bb5c7533b6a5033bd597e80749a0cd3c12fc4754fbde
MD5 b4947e64b3f0118c207421f3454b22e6
BLAKE2b-256 10eb2e2f589b667e0e96ced74bbe8082d549fa50c9708da8026c55860f8df2ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for xseo-0.4.0-py3-none-any.whl:

Publisher: release-please.yml on yuripinto/xseo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page