# SSL Certificate Checker

Connect to a host and port over TLS and inspect the certificate chain the server presents (no data is sent after the handshake). Returns a verdict (valid, expiring, expired, not-yet-valid, self-signed, untrusted, hostname-mismatch, outdated-tls), days to expiry, issuer, the chain with SANs, key type and size, signature algorithm, negotiated protocol and cipher, and issues with fixes: missing intermediates, expired certificates, name mismatch, weak keys or signatures. A server that refuses TLS 1.2 and 1.3 and only speaks TLS 1.0 or 1.1 gets the verdict outdated-tls with the fix (enable TLS 1.2 and 1.3); its chain is read but not checked for trust. Ports 443, 465, 587 (STARTTLS), 636, 853, 993, 995 and 8443; only public hosts.

**Not for:** Scanning supported cipher suites or protocol versions, or HTTP headers (use http_headers).

- Tool id: `ssl-checker`
- Category: security
- Execution: network
- MCP tool `ssl_check` at https://lookupowl.com/mcp
- REST `GET https://lookupowl.com/api/v1/tools/ssl-checker` (or POST a JSON body)
- OpenAPI: https://lookupowl.com/api/openapi.json

## Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `host` | string | yes |  | Domain name or public IP address to connect to, e.g. example.com. A URL or host:port is reduced to its host (and port). Private, loopback and internal addresses are refused. max length 2048 |
| `port` | integer | no | `443` | TCP port. Allowed: 443, 465, 587, 636, 853, 993, 995, 8443 (587 is SMTP with STARTTLS). A port written in the host overrides this. min 1, max 65535 |

## Output

Results are wrapped in an envelope: `tool`, `version`, `requestId`, `data`, `summary`, `meta` (cache status, timing), `permalink`. `data` has these fields:

| Field | Type | Description |
|---|---|---|
| `host` | string |  |
| `port` | integer | min -9007199254740991, max 9007199254740991 |
| `ip` | string | Address that was connected to. |
| `verdict` | "valid" \| "expiring" \| "expired" \| "not-yet-valid" \| "self-signed" \| "untrusted" \| "hostname-mismatch" \| "outdated-tls" | valid = trusted, matches the host and not close to expiry; expiring = valid but 30 days or less remain; outdated-tls = the server refused TLS 1.2 and 1.3 and only speaks TLS 1.0 or 1.1, which browsers block (its certificate is read but its chain is not checked for trust). |
| `valid` | boolean | A browser would accept this certificate for this host right now. |
| `expiresAt` | string |  |
| `daysToExpiry` | integer | Whole days left; negative when expired. min -9007199254740991, max 9007199254740991 |
| `issuedAt` | string |  |
| `lifetimeDays` | integer | Total validity period of the leaf certificate. min -9007199254740991, max 9007199254740991 |
| `subject` | string | Common name (or organization) of the leaf certificate. |
| `issuer` | string | Common name (or organization) of the issuing CA. |
| `protocol` | string | Negotiated TLS version, e.g. TLSv1.3. TLSv1 or TLSv1.1 means the server refused TLS 1.2 and 1.3 (verdict outdated-tls). |
| `cipher` | string |  |
| `alpn` | string |  |
| `authorized` | boolean | The certificate chain verified against the Mozilla root list that ships with LookupOwl's Node.js runtime, not an operating system store (Node's verdict, including dates and host name). Always false when the server only speaks TLS 1.0 or 1.1: its chain is read but not checked. |
| `authorizationError` | string | Why verification failed (an OpenSSL code such as CERT_HAS_EXPIRED). LEGACY_TLS_NOT_VERIFIED means the chain was read over TLS 1.0 or 1.1 and not checked. |
| `hostnameMatch` | boolean |  |
| `ocspStapled` | boolean |  |
| `chain` | object[] | The certificate chain, leaf first. The server sent every entry except possibly a final root marked trustAnchor, which our trust store may have supplied. |
| `issues` | object[] |  |
| `checkedAt` | string |  |
| `ms` | number |  |

## Examples

### Certificate of example.com

```json
{"host":"example.com","port":443}
```

```bash
curl 'https://lookupowl.com/api/v1/tools/ssl-checker?host=example.com&port=443'
```

Web page: https://lookupowl.com/ssl-checker?q=example.com

### Certificate of github.com

```json
{"host":"github.com","port":443}
```

```bash
curl 'https://lookupowl.com/api/v1/tools/ssl-checker?host=github.com&port=443'
```

Web page: https://lookupowl.com/ssl-checker?q=github.com

### An expired certificate (badssl.com)

```json
{"host":"expired.badssl.com","port":443}
```

```bash
curl 'https://lookupowl.com/api/v1/tools/ssl-checker?host=expired.badssl.com&port=443'
```

Web page: https://lookupowl.com/ssl-checker?q=expired.badssl.com

### STARTTLS on a mail submission port

```json
{"host":"smtp.gmail.com","port":587}
```

```bash
curl 'https://lookupowl.com/api/v1/tools/ssl-checker?host=smtp.gmail.com&port=587'
```

Web page: https://lookupowl.com/ssl-checker?q=smtp.gmail.com&port=587

## Web pages

- https://lookupowl.com/ssl-checker
- https://lookupowl.com/ssl-certificate-expiry-checker

## Limits and caching

- Cost: 5 units for a live lookup, 1 unit for a cached one. Budgets are per network and published in the `RateLimit` response headers.
- Cache: results are kept for 600 s. Add `fresh=true` (MCP argument or query parameter) to look again; it costs 3 units per unit and is limited to 10 per hour.
- Timeout: 12 s.

## Related tools

- [Security Headers Checker](https://lookupowl.com/tools/security-headers.md): Grade a site's HTTP security headers from A+ to F, with what each one does and the exact header to add.
- [HTTP Headers Checker](https://lookupowl.com/tools/http-headers.md): Fetch a URL, follow its redirects and see every response header, with a security-header grade and caching summary.
- [Domain Report: Registration, DNS, Web, Hosting and Email](https://lookupowl.com/tools/domain-report.md): One scored report on a domain: registration, DNS, certificate and security headers, hosting, SPF, DMARC, DKIM and blocklists.
- [DNS Lookup](https://lookupowl.com/tools/dns-lookup.md): Look up A, AAAA, MX, NS, TXT, CNAME, SOA, CAA, DS and DNSKEY records from a public resolver or the authoritative nameserver.
- [WHOIS Lookup](https://lookupowl.com/tools/whois-lookup.md): Registrar, creation and expiry dates, status codes, nameservers and DNSSEC for any domain, from RDAP with WHOIS fallback.
- [Domain Availability Checker](https://lookupowl.com/tools/domain-availability.md): Is a domain name taken? Checks one name under up to ten extensions, each answered by its registry, with honest caveats.

## Guide: SSL certificate checker

Check that a site's certificate is valid, trusted by browsers and nowhere near its expiry date.

### What the SSL checker reports

When a browser opens an HTTPS site, the server presents a certificate to prove its identity. The checker connects to the server the same way and completes the TLS handshake, then reports what came back: who the certificate was issued to, which names it covers, who issued it, when it is valid, the chain up to the root, and the TLS version and cipher in use. It sends nothing after the handshake, so no page is requested.

| Field | What it tells you |
|---|---|
| Subject and SANs | The subject alternative names: the names the certificate is valid for. The hostname you visit must be on the list (a wildcard such as `*.example.com` covers one level). |
| Issuer | The certificate authority (CA) that signed it. |
| Valid from / until | The window in which it is valid, plus the days left. |
| Chain | The leaf certificate and the intermediates the server sends. Browsers need them to link the leaf to a trusted root. |
| Key and signature | The key type and size (RSA 2048, ECDSA P-256) and the signing algorithm. |
| Protocol and cipher | The TLS version negotiated (TLS 1.2 or 1.3) and the cipher suite. A server stuck on TLS 1.0 or 1.1 is flagged as outdated. |
| ALPN | The application protocol the server picked, where `h2` means HTTP/2. LookupOwl asks for it on ports 443, 8443 and 853. |
| OCSP stapling | OCSP is how a CA reports whether a certificate has been revoked. Stapling means the server attaches a recent answer to the handshake. |
| Trust and name match | Whether the chain verifies against trusted roots, and whether the certificate covers the name you entered. |

### How to use it

1. **Enter the host**: Type `example.com`, paste a URL, or add a port, as in `mail.example.com:993`. The default is 443, and 8443 works for a web server on an alternate port. Public IP addresses work as well, and the last question below lists the mail, LDAP and DNS-over-TLS ports.
2. **Read the verdict**: The headline reads Valid and trusted, Expires in N days (30 or fewer left), Expired N days ago, Not valid yet, Self-signed certificate, Browsers won't trust this, Certificate is for a different name, or Only supports outdated TLS. A list of problems follows, most with a suggested fix.
3. **Open the details**: If something fails, the Chain tab lists each certificate with its issuer and expiry date, so you can see where a link is missing or has expired. The other tabs show the certificate itself, the connection and the names it covers.

> **In Claude, ChatGPT or Cursor** Connect the LookupOwl MCP server and ask “Is the certificate on shop.example.com about to expire, and is the chain complete?” The assistant calls `ssl_check`, reads the structured answer and gives you a link to the result.

### Common certificate errors, decoded

| Problem | What it means | Fix |
|---|---|---|
| Expired | The valid-until date is in the past (Chrome shows `NET::ERR_CERT_DATE_INVALID`). | Renew and install the new certificate, then check your automation. See the [expiry checker](https://lookupowl.com/ssl-certificate-expiry-checker). |
| Name mismatch | The hostname is not in the certificate's SAN list (Chrome shows `ERR_CERT_COMMON_NAME_INVALID`). | Reissue with the right names, or point the name at the right server. |
| Incomplete chain | The server did not send an intermediate certificate that links yours to a trusted root. | Install the full chain: your certificate plus the intermediates, usually the `fullchain.pem` file. |
| Untrusted or self-signed | The root is not in the client's trust store. | Use a public CA for public sites, or install your private root on clients. |
| Wrong certificate on some IPs | Different servers behind one name present different certificates. | Make every server or load balancer use the same certificate. |
| Only outdated TLS | The server refuses TLS 1.2 and 1.3 and only speaks TLS 1.0 or 1.1. Every current browser needs TLS 1.2 or newer (RFC 8996). | Enable TLS 1.2 and 1.3 on the server, load balancer or CDN and turn off the old versions. If the software is too old for TLS 1.2, update it or put a CDN or proxy in front. |
| Weak key or signature | An RSA key under 2048 bits, or a SHA-1 signature. | Reissue with an RSA 2048 or ECDSA P-256 key and a SHA-256 signature. |
| Lifetime above the limit | The certificate is trusted but valid for longer than the CA/Browser Forum allows: over 398 days, or over 200 days if issued since 15 March 2026. | Unusual from a public CA, so check where it came from. The limit falls to 100 days on 15 March 2027 and 47 days on 15 March 2029, as the [expiry checker](https://lookupowl.com/ssl-certificate-expiry-checker) page explains. |

- **Works in my browser, fails in curl or an API client.** Suspect an incomplete chain first, since browsers can fetch a missing intermediate and many libraries cannot.
- **SNI matters.** Servers hosting many sites choose a certificate from the name the client sends (SNI). The checker sends the name you entered, as browsers do. For an IP address it sends no name, so the server shows its default certificate.
- **Old TLS versions.** LookupOwl connects with TLS 1.2 or 1.3 first. If a server refuses both, it makes one more attempt that can only use TLS 1.0 or 1.1, just to learn which version the server speaks and read its certificate. You then see “Only supports outdated TLS”, with the dates and names from that certificate. The chain is not checked for trust over that connection, and the result is never a pass. Enable TLS 1.2 and 1.3 on the server, then check again. If even the older attempt fails, you get a short message saying the server refused every version we can speak, instead.
- **Revocation is not the same as expiry.** A revoked certificate can still look valid by date. The checker reports whether the server stapled an OCSP response, but it does not ask the CA about revocation. Some CAs, such as Let's Encrypt, have stopped running OCSP, so “No” under OCSP stapling is normal for their certificates.
- **Trust follows one root list.** The verdict uses the public root certificates bundled with LookupOwl's software (the Mozilla list). Chrome, Apple and Microsoft keep their own lists, so a rare certificate can be trusted by one and not another.

### Installation problems to look for

- **The certificate is on the web server but not on the CDN or load balancer.** The public name ends its TLS at whichever layer answers first.
- **Renewed but still serving the old certificate.** The service needs a reload or restart, or there are several nodes and one was missed.
- **Only the bare domain is covered.** A certificate for `example.com` does not automatically cover `www.example.com`. List both names in the SANs.
- **Wildcard expectations.** `*.example.com` covers `shop.example.com`, but not `example.com` or `a.b.example.com`.
- **Forgotten services.** Mail servers (SMTPS 465, IMAPS 993), LDAPS and DNS-over-TLS endpoints have certificates too, and they expire just as quietly.
- **Internal names.** The checker only reaches public hosts. Private, loopback and internal names, and single-word names like `intranet`, are refused.

### How the check works

LookupOwl looks up the host, checks that every address is public, connects to one of them on the port you chose and completes a TLS handshake. It sends the server the name you entered (SNI) and, on ports 443 and 8443, offers HTTP/2 and HTTP/1.1 (ALPN). On port 587 it first asks the mail server to switch to TLS with STARTTLS. It records the certificate chain, the protocol, the cipher and whether a stapled OCSP response arrived, then hangs up. If the server refuses TLS 1.2 and 1.3, one more attempt that can only use TLS 1.0 or 1.1 reads the certificate and the version, and that result is marked unverified. The trust and name checks are done by the TLS library itself, against its bundled roots. A handshake gets about nine seconds, fresh checks of any one host are limited to 20 a minute across all callers, and results are cached for up to ten minutes. Check again fetches a fresh one.

```bash
# The same thing with OpenSSL
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null

# Just the dates
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates -issuer -subject
```

### Standards

- **RFC 5280**: the X.509 certificate and path validation profile. **RFC 9525**: service identity checks (replaces RFC 6125).
- **RFC 8446 and RFC 5246**: TLS 1.3 and 1.2. **RFC 8996**: deprecation of TLS 1.0 and 1.1.
- **RFC 6066**: Server Name Indication, and the certificate status request behind OCSP stapling. **RFC 7301**: ALPN. **RFC 3207**: STARTTLS for SMTP.
- **RFC 6960**: the Online Certificate Status Protocol (OCSP).
- **CA/Browser Forum Baseline Requirements**: the rules public CAs follow, including certificate lifetimes.

### Frequently asked questions

**How do I check an SSL certificate?**

Enter the hostname above. The checker connects the way a browser does, then shows the certificate, its dates, the chain and any problems found, with a suggested fix for most. Add a port, as in `mail.example.com:993`, to check a mail server or another TLS service.

**What is an incomplete certificate chain?**

It means the server sent its own certificate but not the intermediate certificates that connect it to a trusted root. Some browsers recover by fetching the missing link, but many apps, libraries and mail servers do not, so the site works for you and fails for others.

**Why does it say the name does not match?**

Because the hostname you entered is not in the certificate's subject alternative names. Either the certificate was issued for different names, or the DNS record points to the wrong server. Check the Names tab to see which names the certificate does cover.

**Why does my browser show a warning when the checker says the certificate is valid?**

The cause is probably on your side or on another server. Check your device's clock, security software that inspects HTTPS, and any cached warning in the browser. Large sites also use many servers, so yours may be answering with a different certificate than the one LookupOwl reached. The Connection tab shows which address was checked.

**Is a certificate from Let's Encrypt as good as a paid one?**

For encryption and browser trust, yes. A free Let's Encrypt certificate protects traffic as strongly as a paid one. Paid certificates differ in support, warranty and validation type, not in the strength of the encryption. Let's Encrypt certificates are short-lived, so automatic renewal matters more.

**Does this check TLS versions and ciphers?**

It reports the version and cipher negotiated in this one connection, and it tells you when a server refuses TLS 1.2 and 1.3 and only speaks TLS 1.0 or 1.1. That is not a full configuration audit, because it does not list every protocol and cipher suite the server supports. For that you need a dedicated TLS scanner, which tries each version and cipher in turn.

**Can I check a non-HTTPS service?**

Yes, on the supported ports. Services that use TLS from the first byte work on 465 (SMTPS), 993 (IMAPS), 995 (POP3S), 636 (LDAPS) and 853 (DNS-over-TLS). On 587 (SMTP submission) the checker asks for STARTTLS before the handshake. Other STARTTLS services, such as IMAP on 143, are not supported.

**Is anything stored about the sites I check?**

Not in our routine server logs, which do not record the names you look up. Results are held in memory for up to ten minutes so repeat checks are quick. On the website, Google Analytics does see what you look up. The [privacy policy](https://lookupowl.com/privacy) lists exactly what is collected.
