Skip to main content

Siteprobe

Siteprobe is a command-line tool, written in Rust, that fetches every URL from a sitemap.xml or a plain list of URLs, checks that each one exists, and reports how long it took to respond. It prints statistics to the terminal, can write CSV, JSON, and HTML reports, and its exit code reflects the result, so it can gate a CI pipeline.

Screenshot of Siteprobe statistics

Website: https://barttc.github.io/siteprobe/

Installation

# Homebrew (macOS/Linux)
brew install bartTC/siteprobe/siteprobe

# pip / pipx
pipx install siteprobe
pip install siteprobe

# Cargo
cargo install siteprobe

To run it once without installing:

uvx siteprobe https://example.com/sitemap.xml
pipx run siteprobe https://example.com/sitemap.xml

Prebuilt binaries for macOS, Linux, and Windows are attached to every GitHub release. Building from source requires Rust 1.86 or newer:

git clone https://github.com/bartTC/siteprobe.git
cd siteprobe
cargo build --release

Usage

siteprobe [SOURCE] [--url <URL>]... [OPTIONS]

SOURCE is where the URLs come from: a sitemap.xml, a sitemap index, or a plain-text list with one URL per line. It can be an http(s) URL, a local file path, or - to read from stdin. The format is detected automatically. SOURCE is optional when --url is used.

URL sources

# A sitemap or sitemap index. Nested sitemap indexes are followed recursively.
siteprobe https://example.com/sitemap.xml

# Gzip-compressed sitemaps are detected by their .gz suffix or their content.
siteprobe https://example.com/sitemap.xml.gz

# A plain-text URL list, remote or local. Blank lines and lines starting with #
# are ignored; lines that are not http(s) URLs are skipped with a warning.
siteprobe https://example.com/urls.txt
siteprobe ./urls.txt

# A list or a sitemap from stdin
cat urls.txt | siteprobe -
curl -s https://example.com/sitemap.xml | siteprobe -

# URLs given directly. -u can be repeated and combined with a SOURCE;
# all URLs are merged and deduplicated.
siteprobe -u https://example.com/ -u https://example.com/about
siteprobe https://example.com/sitemap.xml -u https://example.com/new-page

Examples

# Ten concurrent requests with a five second timeout
siteprobe https://example.com/sitemap.xml --concurrency-limit 10 --request-timeout 5

# List every page slower than one second, and exit with code 3 if there are any
siteprobe https://example.com/sitemap.xml --slow-threshold 1

# Stay under 300 requests per five minutes
siteprobe https://example.com/sitemap.xml --rate-limit 300/5m

# Write a CSV report and keep a copy of every downloaded page
siteprobe https://example.com/sitemap.xml --report-path ./results/report.csv --output-dir ./example.com

# Bypass caches by appending a random timestamp to each URL
siteprobe https://example.com/sitemap.xml --append-timestamp

# Check a few pages without a sitemap
siteprobe -u https://example.com/ -u https://example.com/pricing --slow-threshold 1

Options

Usage: siteprobe [OPTIONS] <SOURCE|--url <URL>>

Arguments:
  [SOURCE]  Where to load the URLs from: a sitemap.xml or a plain-text list with
            one URL per line, given as an http(s) URL, a local file path, or '-'
            to read from stdin. Optional if --url is used.

Options:
  -u, --url <URL>
          A URL to probe directly, without loading a sitemap or list. Can be
          specified multiple times and combined with SOURCE.
      --basic-auth <BASIC_AUTH>
          Basic authentication credentials in the format `username:password`
  -H, --header <HEADERS>
          Custom header to include in each request (format: 'Name: Value'). Can
          be specified multiple times.
  -c, --concurrency-limit <CONCURRENCY_LIMIT>
          Maximum number of concurrent requests allowed [default: 4]
  -l, --rate-limit <RATE_LIMIT>
          The rate limit for all requests in the format 'requests/time[unit]',
          where unit can be seconds (`s`), minutes (`m`), or hours (`h`). E.g.
          '-l 300/5m' for 300 requests per 5 minutes, or '-l 100/1h' for 100
          requests per hour.
  -o, --output-dir <OUTPUT_DIR>
          Directory where all downloaded documents will be saved
  -a, --append-timestamp
          Append a random timestamp to each URL to bypass caching mechanisms
  -r, --report-path <REPORT_PATH>
          File path for storing the generated `report.csv`
  -j, --report-path-json <REPORT_PATH_JSON>
          File path for storing the generated `report.json`
      --report-path-html <REPORT_PATH_HTML>
          File path for storing the generated `report.html`
  -t, --request-timeout <REQUEST_TIMEOUT>
          Default timeout (in seconds) for each request [default: 10]
      --user-agent <USER_AGENT>
          Custom User-Agent header to be used in requests [default: "Mozilla/5.0
          (compatible; Siteprobe/1.5.1)"]
      --slow-num <SLOW_NUM>
          Limit the number of slow documents displayed in the report. [default:
          100]
  -s, --slow-threshold <SLOW_THRESHOLD>
          Show slow responses. The value is the threshold (in seconds) for
          considering a document as 'slow'. E.g. '-s 3' for 3 seconds or '-s
          0.05' for 50ms.
  -f, --follow-redirects
          Controls automatic redirects. When enabled, the client will follow
          HTTP redirects (up to 10 by default). Note that for security, Basic
          Authentication credentials are intentionally not forwarded during
          redirects to prevent unintended credential exposure.
      --retries <RETRIES>
          Number of retries for failed requests (network errors or 5xx
          responses) [default: 0]
      --exit-zero
          Always exit with status code 0 after a completed run, even if URLs
          failed or exceeded the slow threshold. Fatal errors, such as an
          unreadable source, still exit non-zero.
      --json
          Output the JSON report to stdout instead of the normal table output.
          Suppresses all other console output for clean piping.
      --config <CONFIG>
          Path to a TOML config file. Defaults to `.siteprobe.toml` in the
          current directory.
  -h, --help
          Print help
  -V, --version
          Print version

Exit Codes:
  0  All URLs returned 2xx (success)
  1  One or more URLs returned 4xx/5xx or failed, or a fatal error occurred
  2  Invalid command line arguments
  3  One or more URLs exceeded the slow threshold (--slow-threshold)

Use --exit-zero to always exit 0 after a completed run.

Authentication and custom headers

# Basic Authentication
siteprobe https://example.com/sitemap.xml --basic-auth user:password

# Bearer token (via custom header)
siteprobe https://example.com/sitemap.xml -H "Authorization: Bearer <token>"

# Session cookie
siteprobe https://example.com/sitemap.xml -H "Cookie: sessionid=abc123def456"

# Several headers at once
siteprobe https://example.com/sitemap.xml \
  -H "Authorization: Bearer <token>" \
  -H "Cookie: sessionid=abc123" \
  -H "X-Custom-Header: value"

If both --basic-auth and -H "Authorization: ..." are given, the -H value takes precedence. When redirects are followed (--follow-redirects), Basic Authentication credentials are not forwarded to the redirect target.

Configuration file

Options can be stored in a TOML file so they do not have to be repeated on every run. Siteprobe reads .siteprobe.toml from the current directory if it exists, or the file given with --config. Command-line flags take precedence over the file, and the file takes precedence over the built-in defaults.

Every key is optional and corresponds to a command-line option. The file below lists all of them: the active lines are the defaults, the commented lines show options that have no default.

# .siteprobe.toml

# Requests
concurrency_limit = 4          # concurrent requests
request_timeout = 10           # seconds per request
retries = 0                    # retries for network errors and 5xx responses
follow_redirects = false       # follow up to 10 redirects
append_timestamp = false       # append a random timestamp to each URL to bypass caches
# rate_limit = "300/5m"        # requests per time span; units: s, m, h
# user_agent = "Mozilla/5.0 (compatible; Siteprobe/1.5.1)"   # the default carries the version

# Authentication
# basic_auth = "user:password"
# headers = ["Authorization: Bearer <token>", "Cookie: sessionid=abc123"]

# Slow responses
slow_num = 100                 # number of slow responses shown in the report
# slow_threshold = 1.0         # seconds; responses above it are reported and exit with code 3

# Reports (none are written unless a path is set)
# report_path = "report.csv"
# report_path_json = "report.json"
# report_path_html = "report.html"

# Exit code
exit_zero = false              # exit 0 even if URLs failed or were slow

Reports

Every run prints statistics to the terminal: success, error, and redirect rates; response time percentiles; throughput and response sizes; and the responses above --slow-threshold, limited to --slow-num entries.

  • --report-path <FILE> writes a CSV file with one row per URL: URL, response time in milliseconds, response size, and status code.

  • --report-path-json <FILE> writes a JSON file with the run configuration (sitemapUrl, concurrencyLimit, elapsedTime, bypassCaching), the statistics, and every response with its url, responseTime, responseSize, and statusCode.

  • --report-path-html <FILE> writes a self-contained HTML file with summary statistics, a response time histogram, a status code chart, and a sortable table of all responses.

  • --json prints the JSON report to stdout and suppresses all other output:

    siteprobe https://example.com/sitemap.xml --json | jq '.responses[] | select(.statusCode != 200)'
    

Exit codes

Code Meaning
0 All URLs returned 2xx.
1 One or more URLs returned 4xx/5xx or failed, or a fatal error occurred (e.g. the source could not be loaded).
2 Invalid command line arguments.
3 One or more URLs exceeded the --slow-threshold.

A run with both failing and slow URLs exits with 1.

Pass --exit-zero (or set exit_zero = true in .siteprobe.toml) to always exit with 0 after a completed run, for example when only the report matters and failing URLs should not fail the job. Fatal errors and invalid arguments still exit non-zero.

siteprobe https://example.com/sitemap.xml --report-path-html report.html --exit-zero

Development

Requires Rust 1.86 or newer and just. The Justfile lists all recipes (just --list); the most useful ones:

just check        # cargo fmt --check, cargo clippy -D warnings, cargo test
just test         # run the tests; add --cov for an HTML coverage report (needs cargo-tarpaulin)
just serve-site   # build the website into _site/ and serve it at http://localhost:8000/

The website consists of the landing page docs/index.html, the shared stylesheet docs/site.css, and this README and the CHANGELOG rendered with microdocs through the template docs/template.html. It is deployed to GitHub Pages on every push to main.

To release a new version, set it in Cargo.toml, describe the changes under [Unreleased] in CHANGELOG.md, and run just release. This runs the tests, turns the unreleased section into a dated release entry, commits, tags vX.Y.Z, and pushes. The release workflow on GitHub then builds the binaries and publishes to GitHub Releases, Homebrew, and PyPI.

License

MIT, see LICENSE.

Metadata

Release files for siteprobe 1.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for siteprobe 1.5.1
File Actions
siteprobe-1.5.1-py3-none-manylinux_2_38_x86_64.whl Python 3 none Linux glibc 2.38+ x86-64 Details for siteprobe-1.5.1-py3-none-manylinux_2_38_x86_64.whl
siteprobe-1.5.1-py3-none-manylinux_2_34_aarch64.whl Python 3 none Linux glibc 2.34+ ARM64 Details for siteprobe-1.5.1-py3-none-manylinux_2_34_aarch64.whl
siteprobe-1.5.1-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details for siteprobe-1.5.1-py3-none-macosx_11_0_arm64.whl
siteprobe-1.5.1-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details for siteprobe-1.5.1-py3-none-macosx_10_12_x86_64.whl

Total release size: 13.4 MB

Release files / siteprobe-1.5.1-py3-none-manylinux_2_38_x86_64.whl

Download URL siteprobe-1.5.1-py3-none-manylinux_2_38_x86_64.whl
Size 3.5 MB
Tags Linux glibc 2.38+ x86-64 Python 3
SHA-256 checksum
How to use checksums
ccc23d78eac3915b5bb301fad27005e8b2ed17d580bdf729bd32fdf54aa39233
BLAKE2b-256 checksum
How to use checksums
8cb3c7dc7d9151c5fc78daf62d2ee9d778b6a7a2f8ef15b6f864b309320c9f26
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release files / siteprobe-1.5.1-py3-none-manylinux_2_34_aarch64.whl

Download URL siteprobe-1.5.1-py3-none-manylinux_2_34_aarch64.whl
Size 3.4 MB
Tags Linux glibc 2.34+ ARM64 Python 3
SHA-256 checksum
How to use checksums
b90bd565d11c2da101ae28bef743c5d72e42dcf97785fec17b1e472f96f11875
BLAKE2b-256 checksum
How to use checksums
418ca5a0069ae9567d6a57737a2b3a6aec70793d07a3ba5c8b8a1de0141b7572
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release files / siteprobe-1.5.1-py3-none-macosx_11_0_arm64.whl

Download URL siteprobe-1.5.1-py3-none-macosx_11_0_arm64.whl
Size 3.2 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f2205fd6c688076f2ec07a00591194af6e8727dbed93de48af4b8681478a59bc
BLAKE2b-256 checksum
How to use checksums
9305f2fc21ed4857a8f6e7438cf83b2225a013fca3a4a5ce6666753e939a40bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release files / siteprobe-1.5.1-py3-none-macosx_10_12_x86_64.whl

Download URL siteprobe-1.5.1-py3-none-macosx_10_12_x86_64.whl
Size 3.3 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
cb520aa28ef651b707343c7506c34f644e4f041d3cad8c7ab5bbb0bf81b7c0dd
BLAKE2b-256 checksum
How to use checksums
36cd23167e8d23b6676e9c05c73628a4976289729f6c9a94401febef6ef9aa92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Security for siteprobe 1.5.1

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.

Full provenance

All 4 files in this release have been uploaded with provenance metadata.

Select from 4 files

Attestation for siteprobe-1.5.1-py3-none-manylinux_2_38_x86_64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page