API
Free, no key needed. Limit: 120 HTTP requests per minute per IP. All responses are JSON with CORS enabled.
Real-time WebSocket streams
CertStream-compatible endpoints: point existing CertStream clients (certstream-python, certstream-go, etc.) at wss://treehead.dev.
wss://treehead.dev/ | CertStream certificate_update messages, one per log entry |
wss://treehead.dev/full-stream | Same as above (the leaf DER is available from cert_link) |
wss://treehead.dev/domains-only | CertStream dns_entries messages |
wss://treehead.dev/v1/stream | Native: one JSON frame per second {"type":"certs","seq":…,"certs":[…]}; much cheaper to consume |
Optional query parameters on any stream:
domain=example.com | Only certificates with a name equal to or under this domain |
contains=paypal | Only certificates with a name containing this substring |
issuer=let's encrypt | Issuer DN substring |
dedupe=1 | Drop repeats of a certificate already seen in another log or as a precertificate |
precerts=0 | Final certificates only |
since=<seq> | /v1/stream only: replay up to 30 s of frames after reconnecting |
websocat 'wss://treehead.dev/v1/stream?domain=example.com'
import certstream # pip install certstream
certstream.listen_for_events(lambda m, c: print(m["data"]["leaf_cert"]["all_domains"]),
url="wss://treehead.dev/")
Search
GET /api/v1/search?q=example.com: every certificate for the registered domain example.com and its subdomains, newest first. With a subdomain (q=api.example.com) results are limited to that name and its subdomains.
exact=1 | Only the exact name (and its wildcard) |
expired=1 | Include expired certificates (excluded by default) |
issuer=… | Issuer organisation substring |
precerts=0 | Hide certificates seen only as precertificates |
limit, cursor | Pagination: pass next from the previous response as cursor |
Each result is one certificate (precertificate and final certificate merged; copies across logs merged), with the log entries it appears in.
curl 'https://treehead.dev/api/v1/search?q=example.com&limit=2'
Certificates and log entries
GET /api/v1/entry/{log}/{index} | Parsed entry fetched live from the log, with PEM, leaf hash and (RFC 6962 logs) an inclusion proof against the tree head Treehead verified |
GET /api/v1/entry/{log}/{index}.pem / .der | Raw certificate |
GET /api/v1/cert/{id} | Look up by Treehead ID (SHA-256 of the TBS certificate without CT extensions, so a precertificate and its final certificate share an ID) |
Logs and health
GET /api/v1/logs | Every log from Chrome's and Apple's lists: tree size, Treehead's position, last verified root, errors and verification incidents |
GET /api/v1/stats | Ingest rate and totals |
How verification works
For each log Treehead fetches the signed checkpoint (Static CT API) or STH (RFC 6962) and checks its signature against the key in the log list. It seeds a compact Merkle range from the log's hash tiles or an audit path, hashes every entry it reads into that range, and only marks a tree size verified when the recomputed root equals the signed root. Mismatches, shrinking trees and split views are recorded as incidents on the log page.