API reference

Check a server's TLS certificate

Connect to a host and check the certificate chain it presents: trust, host name, expiry, protocol.

GET POST /api/tls/check MCP tool tls_check

Connects to host:port with OpenSSL 3, using SNI, and verifies the presented chain against the Mozilla root store, including host name verification (RFC 6125). It reports OpenSSL's verdict and every verify error with its chain depth, plus the negotiated protocol, cipher and key-exchange group. The chain is then decoded exactly as cert_decode would, with ordering, signature and expiry notes. Only direct TLS is supported (no STARTTLS). Revocation (OCSP/CRL) is not checked.

Browser version (runs locally): TLS Checker.

Try it

Credentials
Remember these credentials

Not saved: you will paste them again next time.

No credentials yet? Get a client ID and secret. They are sent only to this site, in an Authorization: Basic header.

POST /api/tls/check with a JSON body

Parameters

Parameter Type Default Description
host required string (≤ 253 chars) — Public DNS name or IP address. Private, loopback, link-local, CGNAT and documentation addresses are refused, both as given and after DNS resolution.
port 443 | 8443 | 465 | 636 | 853 | 993 | 995 | 5061 443 TCP port. Only ports that speak TLS directly are allowed.
servername string (≤ 253 chars) — SNI and verification name, if different from host (for example when host is an IP address).

Also accepted on every endpoint: format (json | text). Parameters may come from the query string, a JSON object body, an urlencoded or multipart form, or (for input) a text/plain body.

Global parameters
Parameter Type Default Description
format json | text json json returns the documented object. text returns only the primary value as text/plain (see "Text output").

Response 200 application/json

Field Type Description
host string Host as requested.
port integer Port connected to.
address string IP address actually connected to (DNS is resolved once, then pinned).
servername string | null SNI and verification name used.
trusted boolean True when OpenSSL verified the chain to a Mozilla root and the host name matched.
verification object
verification.ok boolean Same as trusted.
verification.code integer | null OpenSSL verify return code (0 = ok; 10 expired; 18/19 self-signed; 20 unknown issuer; 62 host name mismatch).
verification.message string | null OpenSSL's description of that code.
verification.errors array of object Every verification error OpenSSL reported.
verification.errors[].code integer OpenSSL verify error number.
verification.errors[].message string Description.
verification.errors[].depth integer | null Chain position: 0 is the leaf.
protocol string | null Negotiated protocol, e.g. TLSv1.3.
cipher string | null Negotiated cipher suite.
key_exchange_group string | null Key exchange group, e.g. X25519MLKEM768 (post-quantum hybrid) or X25519.
peer_signature_type string | null Signature scheme the server used in the handshake.
handshake_ms integer Connection and handshake time from the checker.
certificates array of object The chain as presented, leaf first, decoded.
certificates[].subject string Subject distinguished name (RFC 4514 string).
certificates[].issuer string Issuer distinguished name.
certificates[].serialNumber string Serial number as colon-separated uppercase hex.
certificates[].signatureAlgorithm string Signature algorithm, e.g. RSA PKCS#1 v1.5 with SHA-256.
certificates[].validity object
certificates[].validity.notBefore string ISO 8601 UTC.
certificates[].validity.notAfter string ISO 8601 UTC.
certificates[].validity.status "valid" | "expired" | "not-yet-valid" Relative to at (default: now).
certificates[].validity.daysRemaining integer Whole days until notAfter; negative once expired.
certificates[].publicKey object
certificates[].publicKey.algorithm string RSA, EC, Ed25519, X25519, or the algorithm OID name.
certificates[].publicKey.bits integer | null Key size in bits (RSA modulus, EC field size).
certificates[].publicKey.curve string | null Named curve for EC keys (P-256, …).
certificates[].publicKey.spkiSha256 string RFC 7469 pin: Base64(SHA-256(SubjectPublicKeyInfo)).
certificates[].subjectAltNames array of object Subject alternative names.
certificates[].subjectAltNames[].type string dns, ip, email, url, dn, …
certificates[].subjectAltNames[].value string The name.
certificates[].keyUsage array of string Key usage extension bits.
certificates[].extendedKeyUsage array of string Extended key usage purposes.
certificates[].basicConstraints object | null
certificates[].basicConstraints.ca boolean Whether this is a CA certificate.
certificates[].basicConstraints.pathLength integer | null Max intermediate CAs below this one.
certificates[].subjectKeyId string | null Subject key identifier, hex.
certificates[].authorityKeyId string | null Authority key identifier, hex.
certificates[].ocsp array of string OCSP responder URLs (AIA).
certificates[].caIssuers array of string Issuer certificate URLs (AIA).
certificates[].crlDistributionPoints array of string CRL URLs.
certificates[].policies array of string Certificate policies (DV/OV/EV are named).
certificates[].embeddedScts boolean True when Certificate Transparency SCTs are embedded.
certificates[].selfSigned boolean True when subject equals issuer and the signature verifies with its own key.
certificates[].fingerprints object
certificates[].fingerprints.sha1 string SHA-1 of the DER, colon hex.
certificates[].fingerprints.sha256 string SHA-256 of the DER, colon hex.
certificates[].pem string The certificate re-encoded as PEM.
notes array of string Chain observations from the decoder (order, gaps, expiry, host-name coverage).
checked_at string When the check ran.

Errors

Errors are JSON: {"error": "<message>", "code": "<code>", "param": "<name>"?}.

Status Code When
400 invalid_parameter The host is not a DNS name or IP address, or the port is not allowed.
422 unprocessable_input The host does not resolve, resolves to a non-public address, refuses the connection, or does not speak TLS.
502 upstream_error The TLS checker failed or timed out (10 s).
503 service_unavailable The TLS checker is not configured on this deployment.
400 missing_parameter A required parameter is absent.
400 unknown_parameter A parameter name is not in the table above (typos are rejected, not ignored).
413 payload_too_large The request body exceeds 1 MiB.
405 method_not_allowed A method other than GET, POST or OPTIONS.

Behaviour

  • Not idempotent: the result can differ between calls (time, randomness, or a live network check).
  • Requires a client ID and secret (authentication). Each call is recorded as one metadata row against your client ID; inputs and outputs are never stored or logged. Responses carry cache-control: no-store.
  • Contacts the network: this operation asks the TLS checker run by this service to connect to the host you name.
  • CORS: any origin may call this endpoint from a browser, using your credentials.

Examples

Responses below were produced by running each request through this code at build time. Long strings are shortened.

Check example.com

curl 'https://util.caruana.me/api/tls/check?host=example.com'

Response 0

Same call as an MCP tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "tls_check",
    "arguments": {
      "host": "example.com"
    }
  }
}