Site Sweeper
A command-line tool to sweep a website for all internal links, take screenshots, generate sitemap data, and check for broken links and canonical tag issues.
Uses Playwright (headless Chromium) to render pages, extract links, verify canonical tags, and capture screenshots.
Features
- Crawl & traverse — recursively follows all internal links from a starting URL
- Broken link detection — identifies internal pages returning 4xx/5xx status codes
- Canonical tag validation — checks for missing, mismatched, or malformed
<link rel="canonical">tags - Non-canonical link detection — flags internal links that point to non-canonical URLs (e.g. linking to
/pagewhen the canonical is/page/) - External link checking — optionally verifies that external links are reachable
- Screenshots — captures page screenshots at configurable viewport sizes (mobile, tablet, desktop, desktop-lg)
- Canonical links file — writes a list of canonicalised internal paths for sitemap generation
Installation
Requires Python 3.13+ and uv (or pip).
# Clone the repository
git clone https://github.com/tcorbettclark/site-sweeper.git
cd site-sweeper
# Install dependencies
uv sync
# Install the Playwright browser
uv run playwright install chromium
Or with pip:
pip install -e .
playwright install chromium
Usage
site-sweeper <URL>
Examples
Sweep a local site:
site-sweeper http://localhost:8000
Sweep a production site, treating localhost as an alias for the canonical origin:
site-sweeper http://localhost:8000 --canonical-origin https://example.com
Check only a single page (don't follow links):
site-sweeper http://localhost:8000 --single-page
Take screenshots at mobile and desktop sizes:
site-sweeper http://localhost:8000 --size mobile --size desktop
Skip screenshots and only check links:
site-sweeper http://localhost:8000 --no-screenshots
Check external links for broken URLs:
site-sweeper http://localhost:8000 --external
Options
| Option | Default | Description |
|---|---|---|
--delay |
100 |
Delay between page visits in milliseconds |
--screenshots / --no-screenshots |
--screenshots |
Whether to take screenshots |
--screenshots-dir |
./screenshots |
Directory to save screenshots |
--size |
desktop |
Viewport size(s): mobile, tablet, desktop, desktop-lg. Can be specified multiple times |
--links / --no-links |
--links |
Whether to write the canonical links file |
--links-path |
canonical_links.txt |
Output path for the canonical links file |
--canonical / --no-canonical |
--canonical |
Whether to check canonical tags |
--external / --no-external |
--no-external |
Whether to check external links for broken URLs |
--traverse / --single-page |
--traverse |
Traverse all linked pages, or check only the given URL |
--canonical-origin |
(auto) | The production origin for canonical checks (defaults to the crawled URL's origin) |
Environment variables
| Variable | Description |
|---|---|
SITE_SWEEPER_SVG |
When set to a file path, saves the terminal output as an SVG file |
Output
The tool prints a summary to the terminal showing:
- Pages that failed to load or returned error status codes
- Canonical tag issues (missing, mismatched, malformed)
- Non-canonical internal links and what the correct canonical URL should be
- Broken internal and external links
It also writes:
- Screenshots to
./screenshots/(or the configured directory), named<hostname>_<path>_<size>.png - Canonical links to
canonical_links.txt(or the configured path), containing one normalised path per line — suitable for sitemap generation
Demo
A small static site is included in demo/site/ that exercises all of site-sweeper's checks — broken links, missing canonicals, canonical mismatches, and non-canonical links.
To run the demo:
bash demo/demo.sh
This starts a local server, records a terminal demo, and generates demo/demo.cast and demo/demo.gif. It also saves screenshots and canonical links to demo/.
What the demo checks
| Page | Issue |
|---|---|
/ |
Proper canonical; links to everything including a broken page and an external link |
/about/ |
Proper canonical |
/contact/ |
Missing canonical tag |
/blog/post-one/ |
Canonical mismatch (points to /blog/post-two/) |
/blog/post-two/ |
Home links to /blog/post-two (no trailing slash) — non-canonical link |
/broken-page/ |
404 — broken link |
Recording a demo video
bash demo/demo.sh handles recording automatically. It requires asciinema (installed via uv sync) and agg (brew install agg).
License
Metadata
Release files for site-sweeper-cli 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| site_sweeper_cli-0.1.2.tar.gz | 231.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| site_sweeper_cli-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 244.2 kB
Release files / site_sweeper_cli-0.1.2.tar.gz
| Download URL | site_sweeper_cli-0.1.2.tar.gz |
|---|---|
| Size | 231.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
70aafb42b236b5b2b5a6c6153d298b32a2c9bf06799b3f8e036c83378a0d221d
|
|
BLAKE2b-256 checksum How to use checksums |
43177bc59d9d3c5ff51e54f509c7aa69f9e0adaada8817d483ab38a7be00489a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / site_sweeper_cli-0.1.2-py3-none-any.whl
| Download URL | site_sweeper_cli-0.1.2-py3-none-any.whl |
|---|---|
| Size | 12.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9c73bcf4a7515d51e929c046644556c3d7177c383d3355f483ff2a71476a668b
|
|
BLAKE2b-256 checksum How to use checksums |
3182c729d4ee0a3b945ddc98208c847c28e8d016bfb67ec2b83f14daf5f26dcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for site-sweeper-cli 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.