A powerful, developer-friendly Python tool to analyze TLS/SSL certificates for any domain.
- ✨ Check TLS Certificate ✨
- Comprehensive Analysis: Fetches leaf & intermediate certificates using Authority Information Access (AIA).
- Chain Validation: Validates the certificate chain against the system's default trust store.
- Profile Detection: Detects certificate profiles like TLS Server, Code Signing, S/MIME, etc., based on Key Usage and Extended Key Usage extensions.
- Revocation Checks:
- OCSP: Performs Online Certificate Status Protocol (OCSP) checks.
- CRL: Checks Certificate Revocation Lists (CRL).
- DNS CAA Check: Displays DNS Certification Authority Authorization (CAA) records for the domain.
- Certificate Transparency: Queries
crt.sh
for Certificate Transparency logs. - Flexible Output: Human-readable (color-coded), JSON, or CSV formats.
- Web UI: Interactive browser-based analysis via a built-in Flask server.
- REST API: Programmatic access for seamless integration into other tools.
- Dockerized: Ready to use with zero local setup via Docker Hub or GHCR.
pipx
installs CLI tools in isolated environments, which is the safest way to install Python applications.
pipx install check-tls
pip install check-tls
Pull the latest image from Docker Hub or GHCR:
# From Docker Hub
docker pull obeoneorg/check-tls:latest
# Or from GHCR.io
docker pull ghcr.io/obeone/check-tls:latest
Running the Container
You can run the tool in either CLI mode or as a web server.
1. CLI Mode
To analyze a domain, pass it as a command to the container:
docker run --rm obeoneorg/check-tls:latest example.com
To output to a file on your host machine, mount a volume:
# Create a reports directory first: mkdir -p reports
docker run --rm -v "$(pwd)/reports:/app/reports" \
obeoneorg/check-tls:latest example.com -j /app/reports/report.json
2. Web Server Mode
To run the interactive web UI, use the --server
flag and map the port:
docker run --rm -p 8000:8000 obeoneorg/check-tls:latest --server
The web interface will be available at http://localhost:8000.
Example: Command-line output for analyzing a domain (including OCSP status)
Analyze a single domain:
check-tls example.com
Analyze a domain with a specific port:
# The port in the URL overrides the default or --connect-port
check-tls https://example.net:9000
Analyze multiple domains and output to a JSON file:
check-tls google.com https://github.com:443 -j report.json
The CLI provides human-readable output by default. Use -j
for JSON and -c
for CSV. When analyzing multiple domains, a progress indicator will be displayed.
Key Options:
-j, --json FILE
: Output JSON to a file (use "-" for stdout).-c, --csv FILE
: Output CSV to a file (use "-" for stdout).-P, --connect-port PORT
: Port for TLS analysis (default: 443). Overridden by port in domain/URL.-m, --mode [simple|full]
: Analysis mode.simple
checks the leaf certificate only;full
fetches intermediates (default).-l, --loglevel LEVEL
: Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL).-k, --insecure
: Allow self-signed or invalid certificates.-s, --server
: Launch the web UI.-p, --port PORT
: Web server port for the UI (default: 8000).--no-transparency
: Skip certificate transparency check.--no-crl-check
: Skip CRL check.--no-ocsp-check
: Disable OCSP revocation check.--no-caa-check
: Disable DNS CAA check.
To launch the interactive web interface, use the --server
flag:
check-tls --server
Then, open http://localhost:8000 in your browser.
The tool provides a REST API for programmatic analysis. When launched with --server
, the API is available.
- Endpoint:
/api/analyze
- Method:
POST
- Content-Type:
application/json
Request Body:
domains
(array of strings, required): List of domains to analyze (e.g.,["example.com", "google.com:443"]
).connect_port
(integer, optional): Default port to connect to if not specified in the domain string. Defaults to 443.insecure
(boolean, optional): Allow insecure (self-signed) certificates.no_transparency
(boolean, optional): Skip certificate transparency check.no_crl_check
(boolean, optional): Disable CRL check.no_ocsp_check
(boolean,optional): Disable OCSP check.no_caa_check
(boolean, optional): Disable CAA check.
curl -X POST http://localhost:8000/api/analyze \
-H "Content-Type: application/json" \
-d '{"domains": ["example.com", "google.com"], "insecure": true, "no_transparency": true}'
[
{
"domain": "example.com:443",
"status": "completed",
"analysis_timestamp": "2025-04-26T08:30:00+00:00",
"connection_health": { ... },
"validation": { ... },
"certificates": [ ... ],
"crl_check": { ... },
"transparency": { ... },
"ocsp_check": { ... },
"caa_check": { ... }
}
]
The tool provides the following OCSP statuses for the leaf certificate:
good
: The certificate is valid according to its OCSP responder.revoked
: The certificate has been revoked.unknown
: The OCSP responder does not have status information for the certificate.error
: An error occurred during the OCSP check (e.g., network issue, responder unavailable).no_ocsp_url
: The certificate does not contain an OCSP URI.skipped
: The OCSP check was disabled or not applicable.
Example: HTML-based interactive certificate analysis (including OCSP status)
- User-friendly web UI for interactive analysis.
- Supports all CLI options via the browser.
- Great for demos, teams, and non-CLI users!
- Includes a light/dark theme toggle.
check-tls
supports shell completion for bash, zsh, and fish. To enable it, add the appropriate command to your shell's configuration file (~/.bashrc
, ~/.zshrc
, or ~/.config/fish/config.fish
).
Bash:
eval "$(check-tls --print-completion bash)"
Zsh:
eval "$(check-tls --print-completion zsh)"
Fish:
check-tls --print-completion fish | source
The project follows the standard src
layout for packaging.
check-tls/
├── src/
│ └── check_tls/
│ ├── __init__.py
│ ├── main.py # CLI entry point
│ ├── tls_checker.py # Core analysis logic
│ ├── web_server.py # Flask web server and API
│ ├── static/ # CSS/JS for web UI
│ ├── templates/ # HTML templates for web UI
│ └── utils/ # Utility modules
│ ├── __init__.py
│ ├── cert_utils.py
│ ├── crl_utils.py
│ ├── crtsh_utils.py
│ ├── dns_utils.py
│ └── ocsp_utils.py
├── pyproject.toml # Project metadata and dependencies
├── Dockerfile
├── LICENSE
└── README.md
Q: What's the difference between --port
and --connect-port
?
A: --port
(or -p
) specifies the port for the web server UI (--server
mode). --connect-port
(or -P
) specifies the default port for the TLS connection to the target domain.
Q: What does "No CDP" or "No OCSP URL" mean?
A: This means the certificate does not contain a URL for its Certificate Revocation List (CRL) or an OCSP responder. This is common and not necessarily an error, but it prevents the tool from performing that specific revocation check.
Q: How do I analyze a server that uses a self-signed certificate?
A: Use the -k
or --insecure
flag. This tells the tool to connect without validating the certificate against a trusted authority, which is necessary for self-signed certs.
Q: Can I use this tool without Python installed?
A: Yes! The Docker image provides a self-contained environment with all dependencies. See the "With Docker" section for instructions.
Q: How do I get JSON or CSV output?
A: Use -j file.json
or -c file.csv
. Use -
as the filename to print to standard output.
Problem: ssl.SSLCertVerificationError
- Cause: The certificate chain could not be validated against your system's trust store. This is expected for self-signed certificates or if an intermediate certificate is missing.
- Solution: If you trust the server, use the
-k
or--insecure
flag to bypass validation. For production systems, this error indicates a misconfiguration that should be fixed.
Problem: Connection Errors (Connection refused
, timed out
, gaierror
)
- Cause: These are network-level issues.
Connection refused
: The server is not listening on the specified port.timed out
: The server is unreachable, or a firewall is blocking the connection.gaierror
orName or service not known
: The domain name could not be resolved by DNS.
- Solution: Verify the domain name and port. Check for firewall rules and ensure the server is running and accessible from your location.
Problem: ModuleNotFoundError
or import errors.
- Solution: Ensure the package was installed correctly (e.g.,
pip install .
). When running from source, usepython -m check_tls.main ...
.
Problem: Shell completion isn't working.
- Solution: Ensure you have sourced the completion script in your shell's configuration file (
.bashrc
,.zshrc
, etc.) and have restarted your shell. For Fish, the completion file must be placed in the correct directory.
Problem: Docker container exits immediately.
- Cause: You need to provide a command to the container.
- Solution: Specify a domain to analyze or a flag like
--server
. For example:docker run --rm obeoneorg/check-tls:latest example.com
.
- All source code is located in
src/check_tls/
. - Imports should be relative to the package, e.g.,
from check_tls.utils import ...
. - For development, use an editable install:
pip install -e .
. This allows you to test changes without reinstalling. - To run the application from source, use
python -m check_tls.main [OPTIONS]
. - Run tests and linting before submitting a pull request.
Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.
MIT License © Grégoire Compagnon (obeone)
To publish a new version to PyPI, create a new release on GitHub. The GitHub Actions workflow will build and publish the package automatically if the release tag matches the version in pyproject.toml
.
See .github/workflows/publish-to-pypi.yaml
for details.