SSL Certificate Inspector
Inspect TLS certificate metadata via Certificate Transparency and edge probes - cert expiry, issuer, and chain details
Inspect TLS certificate metadata for a domain. Uses Certificate Transparency logs (crt.sh) for issuer, subject, validity, SAN list, and days-until-expiry, plus an HTTPS HEAD probe for reachability.
Features
- GET /inspect?domain= - Certificate metadata + reachability
- CT-based cert data - Issuer, subject, validity window, SANs
- HTTPS probe - Confirms the domain is reachable over TLS
- Honest limitations - Documents that full live cert chain inspection is limited in Workers
API Reference
GET /inspect
Inspect certificate metadata for a hostname.
Prop
Type
Example Request
curl "https://your-worker.workers.dev/inspect?domain=cloudflare.com"Success Response
{
"domain": "cloudflare.com",
"reachable": true,
"tlsVersion": "TLSv1.3",
"certificate": {
"issuer": "CN=WE1,O=Google Trust Services,C=US",
"subject": "CN=cloudflare.com",
"notBefore": "2025-01-01T00:00:00",
"notAfter": "2026-01-01T00:00:00",
"daysUntilExpiry": 180,
"san": ["cloudflare.com", "*.cloudflare.com"],
"serialNumber": "03:AB:CD..."
},
"source": "certificate-transparency",
"note": "Certificate metadata comes from Certificate Transparency logs (crt.sh)..."
}Error Codes
400- Invalid domain (INVALID_DOMAIN)502- Lookup or probe failed (INSPECT_ERROR)
Workers cannot perform arbitrary live TLS certificate handshakes for any domain. This experiment uses CT logs for certificate fields and a HEAD request for reachability. For production cert monitoring, consider dedicated TLS inspection tooling.
Use Cases
- Check certificate expiry and SAN coverage from the edge
- Learn CT log lookup patterns for domain security audits
- Prototype cert monitoring alerts before integrating a full scanner
Limitations
- Certificate data comes from CT logs, not a live handshake
- crt.sh availability and freshness affect results
tlsVersionon the Worker request reflects the Worker's outbound fetch, not the target's full chain
Use in your project
Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/ssl-certificate-inspector.
import type { CertificateInfo } from "../types/env";import { daysUntil, uniqueSans } from "./domain";type CrtShEntry = { issuer_name?: string; common_name?: string; name_value?: string; not_before?: string; not_after?: string; serial_number?: string;};export async function fetchCertificateFromCt(domain: string): Promise<CertificateInfo | null> { const url = `https://crt.sh/?q=${encodeURIComponent(domain)}&output=json`; const response = await fetch(url, { headers: { "User-Agent": "cloudflare-experiments/ssl-certificate-inspector" }, }); if (!response.ok) { throw new Error(`Certificate lookup failed with status ${response.status}`); } const entries = (await response.json()) as CrtShEntry[]; if (!entries.length) return null; const latest = entries .filter((entry) => entry.not_after) .sort((a, b) => Date.parse(b.not_after ?? "") - Date.parse(a.not_after ?? ""))[0]; if (!latest?.not_after || !latest.not_before) return null; const san = uniqueSans( entries .flatMap((entry) => (entry.name_value ?? "").split("\n")) .filter((name) => name.includes(domain) || name.startsWith("*.")) ); return { issuer: latest.issuer_name ?? "unknown", subject: latest.common_name ?? domain, notBefore: latest.not_before, notAfter: latest.not_after, daysUntilExpiry: daysUntil(latest.not_after), san: san.length ? san.slice(0, 50) : [domain], serialNumber: latest.serial_number, };}export async function probeHttps( domain: string): Promise<{ reachable: boolean; tlsVersion?: string }> { try { const response = await fetch(`https://${domain}`, { method: "HEAD", redirect: "follow", }); const tlsVersion = (response as unknown as { cf?: { tlsVersion?: string } }).cf?.tlsVersion; return { reachable: response.ok || response.status < 500, tlsVersion }; } catch { return { reachable: false }; }}Deployment
Test your deployment
curl "https://your-worker.workers.dev/inspect?domain=cloudflare.com"Local Development
cd apps/experiments/ssl-certificate-inspector
npm install
npm run devcurl "http://localhost:8787/inspect?domain=example.com"Cloudflare Features Used
- Workers - Edge compute and outbound fetch
- Fetch API - HTTPS reachability probe