/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
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"
}
}
}