Full TLS handshake and certificate chain analysis. Connects to the target, inspects the certificate chain, checks DANE/TLSA and CAA records, validates OCSP stapling and CT SCTs, tests HSTS, and runs 15 graded quality checks.
See also: interactive API reference (auto-generated OpenAPI)
Endpoints
GET /api/inspect?host=
Inspect a host's TLS configuration. Returns a synchronous JSON response.
curl -s 'https://tls.netray.info/api/inspect?host=example.com' | jq .
POST /api/inspect
Same inspection via POST body.
curl -s -X POST https://tls.netray.info/api/inspect \
-H 'Content-Type: application/json' \
-d '{"host": "example.com"}' | jq .
Custom Port
Append a port number to inspect non-standard TLS ports:
curl -s 'https://tls.netray.info/api/inspect?host=example.com:8443' | jq .
Multi-Port Inspection
Inspect multiple ports in a single request:
curl -s 'https://tls.netray.info/api/inspect?host=example.com:443,8443' | jq .
Response Structure
The response contains several top-level sections:
{
"summary": {
"host": "example.com",
"verdict": "Pass",
"grade": "A",
...
},
"ports": [
{
"port": 443,
"ips": [
{
"ip": "93.184.215.14",
"tls_version": "TLSv1.3",
"cipher_suite": "TLS_AES_256_GCM_SHA384",
"certificate": {
"subject": "CN=example.com",
"issuer": "CN=DigiCert TLS RSA SHA256 2020 CA1",
"not_before": "2024-01-15T00:00:00Z",
"not_after": "2025-02-14T23:59:59Z",
"serial": "0A:1B:2C:...",
"sans": ["example.com", "www.example.com"],
"signature_algorithm": "SHA256withRSA",
"key_type": "RSA 2048"
},
"chain": [
{"subject": "CN=example.com", "issuer": "CN=DigiCert TLS RSA SHA256 2020 CA1"},
{"subject": "CN=DigiCert TLS RSA SHA256 2020 CA1", "issuer": "CN=DigiCert Global Root G2"}
],
"ocsp": {
"stapled": true,
"status": "good"
},
"scts": [
{"log": "Google Argon", "timestamp": "2024-01-15T12:00:00Z"}
],
"enrichment": {
"asn": 64496,
"isp": "Example Networks",
"country": "US"
}
}
]
}
],
"dns": {
"caa": [
{"flag": 0, "tag": "issue", "value": "digicert.com"}
],
"tlsa": [],
"dane_valid": false
},
"quality": {
"verdict": "Pass",
"grade": "A",
"checks": [
{"name": "certificate_validity", "status": "pass", "detail": "Certificate valid for 396 days"},
{"name": "chain_completeness", "status": "pass", "detail": "Full chain provided"},
{"name": "san_quality", "status": "pass", "detail": "SAN covers primary domain"},
{"name": "aia_reachability", "status": "pass", "detail": "AIA OCSP responder reachable"},
...
]
},
"hsts": {
"enabled": true,
"max_age": 31536000,
"include_subdomains": true,
"preloaded": false
}
}
Quality Checks
The quality.checks array contains up to 15 graded checks.
Each check has a status of pass, warn,
or fail:
| Check | What It Tests |
|---|---|
certificate_validity | Certificate is not expired and not expiring soon |
chain_completeness | Full chain is served (no missing intermediates) |
chain_order | Certificates are in correct order |
signature_algorithm | Strong signature algorithm (no SHA-1) |
key_strength | Adequate key size (RSA >= 2048, ECDSA >= 256) |
tls_version | TLS 1.2 or 1.3 (no SSLv3, TLS 1.0/1.1) |
san_quality | SAN list covers the queried hostname |
aia_reachability | AIA OCSP and CA Issuers URLs are reachable |
ocsp_stapling | OCSP stapling is present and valid |
ct_scts | Certificate Transparency SCTs are present |
dane_compliance | TLSA record matches certificate (if TLSA exists) |
caa_compliance | Issuer is authorized by CAA records |
hsts | HSTS header is present with adequate max-age |
redirect | HTTP redirects to HTTPS |
certificate_transparency | Certificate appears in CT logs |
Useful One-Liners
# Get the overall grade
curl -s 'https://tls.netray.info/api/inspect?host=example.com' | jq '.quality.grade'
# Check certificate expiry date
curl -s 'https://tls.netray.info/api/inspect?host=example.com' \
| jq '.ports[0].ips[0].certificate.not_after'
# List all SANs
curl -s 'https://tls.netray.info/api/inspect?host=example.com' \
| jq '.ports[0].ips[0].certificate.sans[]'
# Check for failing quality checks
curl -s 'https://tls.netray.info/api/inspect?host=example.com' \
| jq '[.quality.checks[] | select(.status == "fail")]'
# Verify DANE/TLSA compliance
curl -s 'https://tls.netray.info/api/inspect?host=example.com' \
| jq '.dns.dane_valid'
# CI gate: fail if grade is below A
curl -sf 'https://tls.netray.info/api/inspect?host=example.com' \
| jq -e '.quality.verdict == "Pass"'
Multi-IP Fan-Out
When a domain resolves to multiple IPs, tlsight inspects each one
independently. The ports[].ips[] array contains per-IP results.
If an IP is unreachable, it is included with an error rather than silently
dropped (cap-and-warn graceful degradation).
Rate Limits
Per-IP and per-target GCRA rate limiting. The cost of a request is:
cost = number_of_ports * number_of_inspected_ips
Inspecting example.com:443,8443 where the domain resolves to
3 IPs costs 6 (2 ports x 3 IPs).
When rate-limited, you receive a 429 response with a
Retry-After header.
Errors
{
"error": {
"code": "bad_request",
"message": "Missing required parameter: host"
}
}
Common error codes:
| Code | Meaning |
|---|---|
bad_request | Missing or invalid host parameter |
rate_limited | Too many requests; check Retry-After |
connection_failed | Could not establish TLS connection to target |
internal_error | Server error; include X-Request-Id in reports |