Command-line TLS certificate inspector
Project description
certinspect
Command-line TLS certificate inspector.
Given one or more domains (or a .pem/.der file), it reports:
- Validity and days to expiry
- Total validity period
- Subject and issuer
- Subject Alternative Names (SAN)
- Signature algorithm and key size
- SHA-256 fingerprint
- CA flag and self-signed flag
- Key usage and extended key usage
- Weak-crypto warnings
- Negotiated TLS version and cipher
- Hostname match against the certificate
Requirements
- Python >= 3.10
Installation
pip install certinspect
From source (development)
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Usage
# Inspect a host
certinspect example.com
# A full URL or host:port works too (scheme and path are ignored)
certinspect https://example.com/login
certinspect example.com:8443
# Multiple hosts at once (batch mode)
certinspect example.com github.com api.example.com
# Custom port
certinspect example.com --port 8443
# Custom connection timeout in seconds (default: 5)
certinspect example.com --timeout 10
# JSON output (always a list of objects)
certinspect example.com --json
# Inspect a local certificate
certinspect --file ./certificate.pem
# Custom expiry warning threshold (default: 30 days)
certinspect example.com --days 14
# Only print certificates that have a problem
certinspect example.com github.com --quiet
# Verify the certificate chain against the system trust store
certinspect example.com --verify
# Show the certificate chain presented by the server
certinspect example.com --chain
# Fail (exit 7) unless the fingerprint matches the expected pin
certinspect example.com --pin AA:BB:CC:...
# Read targets from a file (or '-' for stdin)
certinspect --input hosts.txt
cat hosts.txt | certinspect --input -
# Save the fetched certificate as PEM
certinspect example.com --export ./fetched.pem
# Inspect a certificate behind STARTTLS (smtp, imap, pop3, ftp)
# The protocol's standard port is used unless --port is given
certinspect mail.example.com --starttls smtp
certinspect mail.example.com --starttls imap --port 143
# Monitoring output: a Nagios/Icinga plugin line per target
# (exit code follows the plugin convention: 0=OK, 1=WARNING, 2=CRITICAL)
certinspect example.com --exporter nagios
# Monitoring output: Prometheus textfile-collector metrics
certinspect example.com github.com --exporter prometheus
# Print the version
certinspect --version
Example
$ certinspect pypi.org --verify
=== pypi.org ===
Subject: CN=pypi.org
Status: VALID
Issuer: CN=GlobalSign Atlas R3 DV TLS CA 2025 Q4,O=GlobalSign nv-sa,C=BE
Valid from: 2025-12-28 04:33:08+00:00
Valid until: 2027-01-29 04:33:07+00:00
Days to expiry: 217
Total validity: 396 days
Serial number: 1587345912129534630556007389588586994
Signature: sha256WithRSAEncryption
Key size: 2048 bit
Fingerprint: 15:58:1C:41:02:3F:07:89:85:31:4E:7D:4C:4F:8A:CA:BF:05:C7:F6:...
CA: False
Self-Signed: False
TLS version: TLSv1.3
Cipher: TLS_AES_128_GCM_SHA256
Key usage: digital_signature, key_encipherment
Ext. key usage: serverAuth, clientAuth
Hostname match: True
Chain trusted: True
Revocation: GOOD
SAN:
- pypi.org
- *.pypi.org
- www.pypi.org
- donate.pypi.org
With --verify, certinspect opens a fully verified TLS handshake (chain +
hostname against the Python/OpenSSL trust store) and, when the certificate
advertises an OCSP responder, queries it for the revocation status. OCSP is
soft-fail: an unreachable responder reports UNAVAILABLE and does not change
the exit code, while a REVOKED status fails with exit code 6. Revocation is
not checked via CRLs.
Options
| Option | Description |
|---|---|
target... |
One or more domains, URLs or host:port to inspect. Omit when using --file. |
--file PATH |
Inspect a local certificate (PEM or DER) instead of a host. |
--port N |
TCP port to connect to (default: 443). |
--timeout N |
Connection timeout in seconds (default: 5). |
--json |
Print the result as JSON instead of human-readable text. |
--quiet |
Only print certificates that have a problem. |
--verify |
Verify the chain + OCSP revocation, system trust store (hosts only). |
--chain |
Show the certificate chain presented by the server. |
--pin SHA256 |
Fail (exit 7) unless the SHA-256 fingerprint matches (colons/case ignored). |
--input PATH |
Read extra targets from a file, one per line ('-' for stdin). |
--days N |
Warn if the certificate expires within N days (default: 30). |
--export PATH |
Save the inspected certificate as a PEM file at PATH. |
--starttls {smtp,imap,pop3,ftp} |
Upgrade a plaintext connection to TLS before inspecting (standard port unless --port is given). |
--exporter {nagios,prometheus} |
Emit machine-readable monitoring output (ignores --quiet). |
--version |
Print the version and exit. |
Monitoring
Use --exporter to plug certinspect straight into a monitoring stack. Both
formats report every target, including hosts that could not be reached.
nagios emits one Nagios/Icinga plugin line per target with perfdata and exits
with the plugin convention (0 OK, 1 WARNING, 2 CRITICAL); an unreachable
host is CRITICAL:
$ certinspect example.com expired.example.com --exporter nagios
OK: example.com certificate VALID (217 days to expiry) | days=217;30;0
CRITICAL: expired.example.com certificate EXPIRED (-3 days to expiry) | days=-3;30;0
prometheus emits textfile-collector metrics (certinspect_up,
certinspect_cert_expiry_days, certinspect_cert_valid), keeping the normal
worst-status exit code:
$ certinspect example.com --exporter prometheus
# HELP certinspect_up Whether the target could be inspected (1) or not (0).
# TYPE certinspect_up gauge
certinspect_up{target="example.com"} 1
# HELP certinspect_cert_expiry_days Days until the certificate expires.
# TYPE certinspect_cert_expiry_days gauge
certinspect_cert_expiry_days{target="example.com"} 217
# HELP certinspect_cert_valid Whether the certificate is within its validity window (1) or not (0).
# TYPE certinspect_cert_valid gauge
certinspect_cert_valid{target="example.com"} 1
Exit codes
Designed for automation (cron, CI, monitoring scripts). In batch mode the worst code across all targets is returned.
| Code | Meaning |
|---|---|
| 0 | Valid certificate |
| 1 | Runtime error (network, file, parse) |
| 2 | Command-line usage error |
| 3 | Expiring within the --days threshold |
| 4 | Expired or with invalid dates |
| 5 | Hostname does not match the certificate |
| 6 | Chain not trusted or revoked (--verify) |
| 7 | Fingerprint does not match --pin |
Example in a script:
certinspect yoursite.com --days 21
case $? in
0) ;; # all good
3) echo "Expiring" | mail -s "Warning" you@mail.com ;;
4) echo "Expired" | mail -s "Urgent" you@mail.com ;;
5) echo "Bad host" | mail -s "Urgent" you@mail.com ;;
*) echo "Check failed" ;;
esac
Development
# Tests
pytest
# Lint and formatting (Ruff)
ruff check src tests
ruff format src tests
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file certinspect-0.6.0.tar.gz.
File metadata
- Download URL: certinspect-0.6.0.tar.gz
- Upload date:
- Size: 26.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b576e4850a9b009a0153f66230b7e0f7900433b8d21759136e12ad6864660772
|
|
| MD5 |
5105c82359924ce0613f1a7d0b4221a9
|
|
| BLAKE2b-256 |
0fdbcbfa7562aed9f59843bff5c49ff504073cd775d2dc7c60fe2a1a4e1f4e88
|
Provenance
The following attestation bundles were made for certinspect-0.6.0.tar.gz:
Publisher:
publish.yml on mangrisano/certinspect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
certinspect-0.6.0.tar.gz -
Subject digest:
b576e4850a9b009a0153f66230b7e0f7900433b8d21759136e12ad6864660772 - Sigstore transparency entry: 1964810030
- Sigstore integration time:
-
Permalink:
mangrisano/certinspect@d0ca1162a33e0fb18aec5e46f80610bdc9c7aeb8 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/mangrisano
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d0ca1162a33e0fb18aec5e46f80610bdc9c7aeb8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file certinspect-0.6.0-py3-none-any.whl.
File metadata
- Download URL: certinspect-0.6.0-py3-none-any.whl
- Upload date:
- Size: 18.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b56d83c6995e0303c2eaea358e66edfbb8fac23b161ab373783a058f4c650560
|
|
| MD5 |
7cf5eb89bd93075f76f57972201ed785
|
|
| BLAKE2b-256 |
125d5a767cbb2e2b60449cb108e3d815355653c4851e63b1e3988d5de609bff0
|
Provenance
The following attestation bundles were made for certinspect-0.6.0-py3-none-any.whl:
Publisher:
publish.yml on mangrisano/certinspect
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
certinspect-0.6.0-py3-none-any.whl -
Subject digest:
b56d83c6995e0303c2eaea358e66edfbb8fac23b161ab373783a058f4c650560 - Sigstore transparency entry: 1964810166
- Sigstore integration time:
-
Permalink:
mangrisano/certinspect@d0ca1162a33e0fb18aec5e46f80610bdc9c7aeb8 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/mangrisano
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d0ca1162a33e0fb18aec5e46f80610bdc9c7aeb8 -
Trigger Event:
push
-
Statement type: