CSR.plus API Reference
Automate the whole SSL/TLS certificate lifecycle with a single open REST API — CSR generation, decoding, A–F grading, certificate transparency, CAA, revocation and TLS tracing. Free, unauthenticated, no API keys.
Try the API liveOverview
The CSR.plus API is a collection of read-only and generation endpoints that power our web tools. Every endpoint returns JSON, supports CORS for browser clients, and is rate-limited per IP address. Keys and CSRs are generated in memory and never stored.
Base URL & authentication
https://csr.plusAll endpoints are served over HTTPS. No authentication is required — the API is open and unauthenticated by design. There are no API keys, tokens or billing. Requests are identified by IP address for rate limiting only.
All responses include CORS headers (Access-Control-Allow-Origin: *), so you can call the API directly from browsers and client-side scripts.
Rate limits
| Endpoint | Limit | Window |
|---|---|---|
| /api/generate | 10 requests | per minute per IP |
| /api/ssl-check, /api/ct, /api/caa | 30 requests | per minute per IP |
| /api/revocation, /api/ssl-tracer | 20 requests | per minute per IP |
| /api/decode, /api/openssl-trace | Not limited | — |
Exceeding a limit returns HTTP 429 with a Retry-After header indicating how many seconds to wait.
/api/generateGenerate a certificate signing request and a private key. Rate limit: 10 requests per minute per IP.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
| common_name | string | Yes | Primary domain (e.g. example.com) |
| sans | array | No | Additional subject alternative names, e.g. ["www.example.com"] |
| organization | string | No | Organization name (O) |
| org_unit | string | No | Organizational unit (OU) |
| country | string | No | Two-letter country code (C), e.g. "US" |
| state | string | No | State or province (ST) |
| locality | string | No | Locality / city (L) |
| string | No | Contact email address | |
| key_type | string | No | "rsa" (default) or "ecdsa" |
| key_size | string|int | No | RSA: 2048 (default) / 3072 / 4096 · ECDSA: "P-256" (default) / "P-384" |
| passphrase | string | No | Encrypts the private key as encrypted PKCS#8 PEM (max 200 chars) |
Response fields
| Field | Description |
|---|---|
| csr | Certificate signing request in PEM format (PKCS#10, SHA-256 signature) |
| private_key | Private key in PEM format (PKCS#8; encrypted PKCS#8 when a passphrase is supplied) |
| algorithm | Algorithm used, e.g. "RSA-2048" or "ECDSA-P-256" |
| created_at | ISO 8601 timestamp of generation |
curl -X POST https://csr.plus/api/generate \
-H "Content-Type: application/json" \
-d '{
"common_name": "example.com",
"sans": ["www.example.com", "api.example.com"],
"organization": "Example Inc",
"country": "US",
"key_type": "rsa",
"key_size": 2048
}'{
"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIICzDCCAbQCAQAwgYwxCzAJBgNVBAYTAVVT...\n-----END CERTIFICATE REQUEST-----",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC...\n-----END PRIVATE KEY-----",
"algorithm": "RSA-2048",
"created_at": "2026-08-14T10:30:00.000Z"
}openssl req -verify -noout -in example.com.csr
openssl req -in example.com.csr -text -noout | head -20/api/decodeParse any PKCS#10 CSR and return its subject, subject alternative names, public key, signature verification and extensions.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
| csr | string | Yes | The CSR in PEM format (-----BEGIN CERTIFICATE REQUEST-----) |
curl -X POST https://csr.plus/api/decode \
-H "Content-Type: application/json" \
-d '{"csr": "-----BEGIN CERTIFICATE REQUEST-----\n..."}'{
"success": true,
"subject": {
"commonName": "example.com",
"organization": "Example Inc",
"organizationalUnit": null,
"country": "US",
"state": "California",
"locality": "San Francisco",
"email": null
},
"publicKey": { "type": "RSA", "size": 2048 },
"signature": { "algorithm": "sha256WithRSAEncryption", "verified": true },
"sanList": ["example.com", "www.example.com", "api.example.com"],
"extensions": [],
"size": 640,
"version": 0,
"timestamp": "2026-08-14T10:30:00.000Z"
}Note: dcvInfo contains domain control validation hints (HTTP token files and a CNAME record) useful when completing CA validation steps.
/api/ssl-check?domain={domain}Full SSL/TLS check with an SSL Labs-style A–F grade: certificate validity, hostname match, chain trust, TLS version probes and HSTS inspection.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | Yes | Hostname to check (port 443 is assumed) |
curl "https://csr.plus/api/ssl-check?domain=example.com"{
"success": true,
"domain": "example.com",
"grade": {
"letter": "A+",
"score": 100,
"label": "Excellent configuration with HSTS",
"checks": [
{ "name": "Hostname match", "status": "pass", "detail": "Certificate covers the requested hostname" },
{ "name": "TLS 1.3", "status": "pass", "detail": "TLS 1.3 is supported" }
]
},
"cert": {
"subject": "CN=example.com",
"issuer": "CN=R10,O=Let's Encrypt,C=US",
"validFrom": "2026-05-14T00:00:00.000Z",
"validTo": "2026-08-12T00:00:00.000Z",
"daysRemaining": 30,
"san": ["example.com", "www.example.com"]
},
"tls": { "tls13": true, "tls12": true, "tls11": false, "tls10": false, "protocol": "TLSv1.3" },
"hsts": { "present": true, "maxAge": 31536000, "includeSubDomains": true, "preload": false }
}/api/ct?domain={domain}Search public certificate transparency logs for every certificate ever issued to a domain. Falls back to Cert Spotter when crt.sh is unavailable.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | Yes | Domain to search in CT logs |
curl "https://csr.plus/api/ct?domain=example.com"{
"success": true,
"count": 12,
"source": "crt.sh",
"certs": [
{
"id": 123456,
"logged_at": "2026-08-01T12:00:00.000Z",
"not_before": "2026-07-15T00:00:00.000Z",
"not_after": "2026-10-13T00:00:00.000Z",
"common_name": "example.com",
"name_value": "example.com\nwww.example.com"
}
]
}The response includes source (crt.sh or certspotter) so you can tell which provider served the data.
/api/caa?domain={domain}Return the DNS CAA records for a domain together with A, AAAA, NS and MX records, showing which certificate authorities are authorized to issue certificates.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | Yes | Domain to query |
curl "https://csr.plus/api/caa?domain=example.com"{
"success": true,
"domain": "example.com",
"caa": [
{ "flags": 0, "tag": "issue", "value": "letsencrypt.org" },
{ "flags": 0, "tag": "iodef", "value": "mailto:[email protected]" }
],
"a": ["93.184.216.34"],
"aaaa": ["2606:2800:220:1:248:1893:25c8:1946"],
"ns": ["a.iana-servers.net"],
"mx": [],
"caaError": ""
}/api/revocation?domain={domain}Fetch the certificate currently served by a domain and report its CRL distribution points and OCSP responder endpoints.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | Yes | Domain whose serving certificate is inspected |
curl "https://csr.plus/api/revocation?domain=example.com"{
"success": true,
"domain": "example.com",
"serial": "03F2A1B3C4D5E6F7",
"crlUrls": ["http://crl.letsencrypt.org/r3.crl"],
"ocspUrls": ["http://r3.o.lencr.org"],
"status": "good"
}/api/ssl-tracer?domain={domain}&port={port}Perform a real TLS handshake against any host and port, recording DNS resolution, TCP connectivity, negotiated TLS version and cipher, and the full certificate chain.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | Yes | Hostname to connect to |
| port | int | No | TCP port (default 443) |
curl "https://csr.plus/api/ssl-tracer?domain=example.com&port=443"{
"success": true,
"host": "example.com",
"port": 443,
"dns": { "ips": ["93.184.216.34"], "ms": 12 },
"tcp": { "ok": true, "ms": 38 },
"tls": { "version": "TLSv1.3", "cipher": "TLS_AES_128_GCM_SHA256", "weak": false },
"certs": [
{
"subject": { "CN": "example.com" },
"issuer": { "CN": "R10", "O": "Let's Encrypt", "C": "US" },
"serialNumber": "03F2A1B3C4D5E6F7",
"notBefore": "2026-05-14T00:00:00.000Z",
"notAfter": "2026-08-12T00:00:00.000Z",
"daysRemaining": 30,
"expired": false,
"isCA": false,
"isSelfSigned": false,
"keyType": "RSA",
"keySize": 2048,
"sha256": "E8:2F:0A:..."
}
],
"chainComplete": true,
"chainNote": "Chain resolves to a trusted root",
"errors": []
}/api/openssl-trace?domain={domain}Run a raw openssl s_client handshake against a domain and return the complete verbose output — useful for debugging certificate chain and protocol issues.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain | string | Yes | Domain to trace (port 443 is assumed) |
curl "https://csr.plus/api/openssl-trace?domain=example.com"{
"success": true,
"output": "CONNECTED(00000005)\ndepth=2 C=US, O=Internet Security Research Group...\nverify return:1\n..."
}Error codes
Errors are returned as JSON with an error message and, where applicable, an errorId for programmatic handling.
| Status | errorId | Meaning |
|---|---|---|
| 400 | invalid_json | Request body is not valid JSON |
| 400 | invalid_common_name | common_name is missing or longer than 253 characters |
| 400 | invalid_key_type | key_type must be "rsa" or "ecdsa" |
| 400 | invalid_key_size | RSA sizes must be 2048/3072/4096; ECDSA curves must be "P-256"/"P-384" |
| 400 | invalid_passphrase | passphrase must be a non-empty string (max 200 characters) |
| 400 | invalid_json_format | Request body or fields are malformed |
| 405 | method_not_allowed | Only POST is accepted on /api/generate |
| 413 | payload_too_large | Request body too large (limit 10 KB) |
| 429 | rate_limit_exceeded | Rate limit exceeded — retry after the Retry-After header |
| 500 | generation_failed | Internal error during key/CSR generation |
Best practices
- Generate private keys locally with OpenSSL or node-forge for production workloads. The API is designed for development, testing and light automation.
- Set a passphrase when the key needs to be stored or transferred between systems.
- Use RSA 2048 or ECDSA P-256 unless compliance rules require stronger keys.
- Honor the Retry-After header instead of hammering the API after a 429.
- Validate domain parameters client-side (max 253 chars, alphanumeric, dots and dashes) before calling read-only endpoints.
- Never log the private_key field from API responses.
More examples
import requests
r = requests.post(
"https://csr.plus/api/generate",
json={"common_name": "example.com", "sans": ["www.example.com"]},
)
r.raise_for_status()
data = r.json()
open("example.com.csr", "w").write(data["csr"])
open("example.com.key", "w").write(data["private_key"])const res = await fetch("https://csr.plus/api/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ common_name: "example.com", key_type: "ecdsa", key_size: "P-256" }),
});
const { csr, private_key } = await res.json();
console.log(csr);Try the API live
Pick an endpoint, fill in the parameters and run a real request against the production API.
FAQ
What is the API rate limit?
CSR generation allows 10 requests per minute per IP address. SSL check, CT and CAA allow 30 per minute; revocation and TLS tracer allow 20 per minute. Exceeding a limit returns HTTP 429 with a Retry-After header.
What key types are supported?
RSA 2048/3072/4096 and ECDSA P-256/P-384. Pass the key_type and key_size parameters in the request body.
Can I encrypt the generated private key?
Yes. Add a passphrase field to the request and the private key is returned encrypted as an encrypted PKCS#8 PEM key.
Does the API store my private key?
No. Keys and CSRs are generated in memory and never persisted, logged or stored on disk. Use the API for development and testing.
What CAs accept CSRs generated by this API?
The API produces standard PKCS#10 CSRs with SHA-256 signatures that are accepted by all major certificate authorities, including Let’s Encrypt, DigiCert, Sectigo and Google Trust Services.