GitHub

Live usage

Numbers from the running server, refreshed every 5 seconds. Counters reset when the server restarts.

Connected clients-
Outbound bandwidth-
Certificates per second-
Data sent since restart-
Uptime-

Loading live numbers.

Connect to the CertStream WebSocket

Certificates arrive as JSON text frames in the same format as the self-hosted server.

EndpointStreamSize per certificate
wss://api.certstream.dev/Domain names only (default)~200 B
wss://api.certstream.dev/liteLite, without DER and chain~1 KB
Python
import asyncio, json, websockets

URL = "wss://api.certstream.dev/"

async def main():
    async with websockets.connect(URL) as ws:
        async for message in ws:
            event = json.loads(message)
            if event["message_type"] == "dns_entries":
                print(event["data"])

asyncio.run(main())
JavaScript
const ws = new WebSocket("wss://api.certstream.dev/");
ws.onmessage = (e) => {
  const event = JSON.parse(e.data);
  if (event.message_type === "dns_entries") console.log(event.data);
};
websocat
websocat wss://api.certstream.dev/

Use it with existing CertStream clients

Point a client that already speaks CertStream at the lite endpoint. Only the URL changes.

Pythoncertstream library
import certstream

def on_message(message, context):
    if message["message_type"] == "certificate_update":
        print(message["data"]["leaf_cert"]["all_domains"])

certstream.listen_for_events(on_message, url="wss://api.certstream.dev/lite")

Message format

domains-only/
{
  "message_type": "dns_entries",
  "data": ["example.com", "*.example.com"]
}
lite/lite, abbreviated
{
  "message_type": "certificate_update",
  "data": {
    "update_type": "PrecertLogEntry",
    "leaf_cert": {
      "issuer": { "CN": "Amazon RSA 2048 S09" },
      "not_before": 1792405638,
      "not_after": 1796297238,
      "all_domains": ["example.com"]
    },
    "seen": 1792409244.748,
    "source": { "name": "DigiCert Sphinx2026h2" }
  }
}

Every field is described in the API documentation.

What people use it for

Phishing and typosquat detection

Match new domains against lookalikes of a brand as certificates are issued.

Brand monitoring

Get notified when a certificate appears for a name that contains yours.

Subdomain discovery

Collect new hostnames under domains you track, before they show up anywhere else.

Threat intelligence

Feed newly registered and newly certified domains into your own pipeline.

Limits

ItemValue
Concurrent connections per IP2. A third connection is refused with HTTP 429.
Availability (SLA)99.9%

Frequently asked questions

Is the CertStream API really free?

Yes. The domains-only and lite streams are free and need no API key or sign-up.

Do I need an API key?

No. Open a WebSocket connection to the endpoint and certificates start arriving.

Can I use it with existing CertStream clients?

Yes. The lite stream uses the same message format as the original CertStream, so a client only needs its URL changed to wss://api.certstream.dev/lite. The Python certstream library works this way.

What is the difference between domains-only and lite?

Domains-only sends just the domain names of each certificate, about 200 bytes per message. Lite adds the issuer, validity dates, fingerprints and log source, about 1 KB per message.

Which Certificate Transparency logs does it read?

The Chrome- and Apple-trusted CT logs, both RFC 6962 and static-ct-api, with certificates that appear in more than one log delivered once.

Can I get the full stream with the DER certificate and chain?

Not on the public endpoint. You can run your own instance of certstream-server-rust, which serves it.

Want to run it yourself? See the quick start or the certstream-server-rust repository.