Certificate Inspector over HTTP — Fast & lightweight HTTP gateway that serves X.509 certificate inspection as a JSON REST API.
Built in Go, it accepts a POST request with either a live TLS socket address or raw certificate bytes (PEM or DER), and returns the full parsed certificate chain as structured JSON. The binary embeds a static web UI and an OpenAPI specification, with zero runtime dependencies.
The embedded web UI (served at
/) provides an interactive form to inspect TLS certificates directly from a hostname or by pasting raw PEM data. It supports dark and light themes and is fully translated into 15 languages.
Provided binaries are fully functional natively on Linux (amd64 or arm64), Windows (amd64), macOS (amd64 or arm64), and also via Docker (amd64 or arm64), with no additional dependencies required. For download and installation, please refer to the Releases page.
This project is released as-is, for demonstration or reference purposes. It is not maintained: no bug fixes, dependency updates, or new features are planned. Issues and pull requests will not be addressed.
This project is licensed under the Apache License, Version 2.0 — see the LICENSE file for details.
Copyright (c) 2026 letstool.net
- Single static binary — no external runtime dependencies
- Embedded web UI and OpenAPI 3.1 specification (
/openapi.json) - Web UI available in dark and light mode, switchable at runtime via a toggle
- Web UI fully translated into 15 languages: Arabic, Bengali, Chinese, German, English, Spanish, French, Hindi, Indonesian, Japanese, Korean, Portuguese, Russian, Urdu, Vietnamese
- Inspect certificates from a live TLS connection (dial by hostname/IP) or from raw PEM/DER bytes
- Auto-detection of PEM vs DER format; supports single certificates and full chains
- Full X.509 v3 extension parsing: SAN, Key Usage, Extended Key Usage, Basic Constraints, AKI/SKI, AIA, CRL, Certificate Policies, Name Constraints, OCSP No-Check, SCT list
- Per-certificate fingerprints: SHA-1, SHA-256, SHA-512
- Public key details for RSA, EC, Ed25519, DSA, X25519/ECDH
- Expiry status and days-left computed at query time
- Self-signed and CA flag detection
- Configurable listen address and dial timeout
- Docker image built on
scratch— minimal attack surface
- Go 1.22+
bash scripts/linux_build.shThe binary is output to ./out/http2cert.
The script produces a fully static binary (no libc dependency):
go build \
-trimpath \
-ldflags="-extldflags -static -s -w" \
-tags netgo \
-o ./out/http2cert ./cmd/http2certscripts\windows_build.cmdbash scripts/docker_build.shThis runs a two-stage Docker build:
- Builder —
golang:1.24-alpinecompiles a static binary - Runtime —
scratchimage, containing only the binary
The resulting image is tagged letstool/http2cert:latest.
bash scripts/linux_run.shThis sets LISTEN_ADDR=0.0.0.0:8080 and runs the binary.
scripts\windows_run.cmdbash scripts/docker_run.shEquivalent to:
docker run -it --rm -p 8080:8080 -e LISTEN_ADDR=0.0.0.0:8080 letstool/http2cert:latestOnce running, the service is available at http://localhost:8080.
Each setting can be provided as a CLI flag or an environment variable. The CLI flag always takes priority. Resolution order: CLI flag -> environment variable -> default.
| CLI flag | Environment variable | Default | Description |
|---|---|---|---|
-addr |
LISTEN_ADDR |
127.0.0.1:8080 |
Address and port the HTTP server listens on. |
-timeout |
DIAL_TIMEOUT |
10s |
TLS dial+handshake timeout. Go duration format: 5s, 1m, 1m30s. Applied per request when no per-request timeout is provided. |
-json |
LOG_JSON |
false |
Emit structured JSON logs instead of plain text. Accepts true/false/1/0. |
Examples:
# Using CLI flags
./out/http2cert -addr 0.0.0.0:9090 -timeout 30s -json true
# Using environment variables
LISTEN_ADDR=0.0.0.0:9090 DIAL_TIMEOUT=30s LOG_JSON=true ./out/http2certInspects an X.509 certificate or certificate chain. Exactly one of socket or raw_cert_data must be provided.
Option A — live TLS socket:
{
"socket": "example.com:443",
"sni": "example.com",
"timeout": 10
}Option B — raw certificate data (PEM or DER):
{
"raw_cert_data": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
}| Field | Type | Required | Description |
|---|---|---|---|
socket |
string |
(A) | Address to dial: domain:port, IPv4:port, or [IPv6]:port. Example: example.com:443. |
sni |
string |
No | Server Name Indication override. Defaults to the host part of socket. |
timeout |
integer |
No | Per-request dial+handshake timeout in seconds (range: 1-120). Socket mode only. |
raw_cert_data |
string |
(B) | PEM or DER bytes. Auto-detected. Accepts single certificates and full PEM chains. |
socketandraw_cert_dataare mutually exclusive.timeoutcannot be used withraw_cert_data.
{
"result": "SUCCESS",
"source": {
"type": "SOCKET",
"address": "93.184.216.34:443",
"sni": "example.com",
"timeout": 10,
"cert_count": 2
},
"answers": [
{
"format": "PEM",
"version": 3,
"serial_number": "0a:1b:2c:...",
"signature_algorithm": "SHA256-RSA",
"subject": { "common_name": "example.com", "organization": ["Example Org"], ... },
"issuer": { "common_name": "DigiCert TLS RSA SHA256 2020 CA1", ... },
"validity": {
"not_before": "2024-01-01T00:00:00Z",
"not_after": "2025-01-01T00:00:00Z",
"is_expired": false,
"days_left": 183
},
"public_key_info": { "algorithm": "RSA", "key_size_bits": 2048, "exponent": 65537 },
"fingerprints": {
"sha1": "aa:bb:cc:...",
"sha256": "11:22:33:...",
"sha512": "ff:ee:dd:..."
},
"is_self_signed": false,
"is_ca": false,
"extensions": { ... }
}
]
}| Field | Type | Description |
|---|---|---|
type |
string |
SOCKET or RAW |
address |
string |
Resolved host:port dialed (SOCKET only) |
sni |
string |
SNI sent in the ClientHello (SOCKET only) |
timeout |
integer |
Effective timeout applied in seconds (SOCKET only) |
format |
string |
PEM or DER (RAW only) |
cert_count |
integer |
Number of certificates in answers |
| Field | Type | Description |
|---|---|---|
raw |
string |
PEM-encoded certificate |
format |
string |
Input format: PEM or DER |
version |
int |
X.509 version (1, 2, or 3) |
serial_number |
string |
Hex-encoded serial number (colon-separated) |
serial_number_dec |
string |
Decimal serial number |
signature_algorithm |
string |
e.g. SHA256-RSA, ECDSA-SHA384 |
issuer |
object |
Parsed issuer Distinguished Name |
subject |
object |
Parsed subject Distinguished Name |
validity |
object |
Validity window with expiry status and days remaining |
public_key_info |
object |
Algorithm, key size, curve (EC), exponent (RSA) |
extensions |
object |
Parsed X.509 v3 extensions (omitted if none) |
signature |
object |
Signature algorithm and raw hex value |
fingerprints |
object |
SHA-1, SHA-256, SHA-512 digests of the DER certificate |
is_self_signed |
bool |
true if subject == issuer and signature self-validates |
is_ca |
bool |
true if Basic Constraints marks this as a CA |
| Value | HTTP status | Meaning |
|---|---|---|
SUCCESS |
200 | At least one certificate was parsed and returned |
INVALID_INPUT |
400 | Malformed request (bad JSON, missing/conflicting fields, bad timeout) |
NOTFOUND |
502 | Host unreachable (DNS failure, connection refused, timeout) |
TLS_ERROR |
502 | TCP connected but TLS handshake failed |
NO_CERTIFICATES |
200 | Connection or parse succeeded but the server returned no certificates |
ERROR |
500/502 | Internal or unexpected error |
curl -s -X POST http://localhost:8080/api/v1/certinfo \
-H "Content-Type: application/json" \
-d '{"socket": "example.com:443"}' | jq .{
"result": "SUCCESS",
"source": {
"type": "SOCKET",
"address": "93.184.216.34:443",
"sni": "example.com",
"timeout": 10,
"cert_count": 2
},
"answers": [
{
"format": "PEM",
"version": 3,
"serial_number": "0a:1b:2c:3d:...",
"signature_algorithm": "SHA256-RSA",
"subject": { "common_name": "example.com" },
"issuer": { "common_name": "DigiCert TLS RSA SHA256 2020 CA1" },
"validity": {
"not_before": "2024-01-15T00:00:00Z",
"not_after": "2025-01-15T23:59:59Z",
"is_expired": false,
"days_left": 183
},
"fingerprints": {
"sha256": "11:22:33:44:55:66:77:88:..."
},
"is_self_signed": false,
"is_ca": false
}
]
}curl -s -X POST http://localhost:8080/api/v1/certinfo \
-H "Content-Type: application/json" \
-d "{\"raw_cert_data\": \"$(cat cert.pem)\"}" | jq .Returns the embedded interactive web UI.
Returns the full OpenAPI 3.1 specification of the API.
Returns the application icon.
Dependencies are managed with Go modules. After cloning:
go mod download
go build ./...The test suite and initialization scripts are located in scripts/:
scripts/000_init.sh # Environment setup (go mod tidy)
scripts/999_test.sh # Integration test (curl against a running server)
Run unit tests:
go test ./...This project was developed with the assistance of Claude Sonnet 4.6 by Anthropic.
| Project | GitHub | Docker Hub | Description |
|---|---|---|---|
http2dns |
letstool/http2dns | letstool/http2dns | Fast & lightweight HTTP gateway that serves DNS queries as a JSON REST API |
http2whois |
letstool/http2whois | letstool/http2whois | Fast & lightweight HTTP gateway that serves WHOIS queries as a JSON REST API |
http2rdap |
letstool/http2rdap | letstool/http2rdap | Fast & lightweight HTTP gateway that serves RDAP queries as a JSON REST API |
http2geoip |
letstool/http2geoip | letstool/http2geoip | Fast & lightweight HTTP gateway that serves IP geolocation database as a JSON REST API |
http2cert |
letstool/http2cert | letstool/http2cert | Fast & lightweight HTTP gateway that serves X.509 certificate inspection as a JSON REST API |
http2tor |
letstool/http2tor | letstool/http2tor | Fast & lightweight HTTP gateway that serves Tor IP database as a JSON REST API |
http2sun |
letstool/http2sun | letstool/http2sun | Fast & lightweight HTTP gateway that serves solar position algorithm as a JSON REST API |
http2mac |
letstool/http2mac | letstool/http2mac | Fast & lightweight HTTP gateway that serves MAC address OUI database as a JSON REST API |
http2country |
letstool/http2country | letstool/http2country | Fast & lightweight HTTP gateway that serves country database as a JSON REST API |
http2prefix |
letstool/http2prefix | letstool/http2prefix | Fast & lightweight HTTP gateway that serves Internet BGP routing database as a JSON REST API |
