Skip to content

CAA Record: syntax, examples, and troubleshooting

A CAA record declares which certificate authorities are permitted to issue TLS certificates for a domain. CAs are required to check it at issuance time and must refuse if they are not listed. It constrains future issuance only — it has no effect on certificates that already exist.

Example CAA record

google.com.		9310	IN	CAA	0 issue "pki.goog"
cloudflare.com.		300	IN	CAA	0 issue "letsencrypt.org"
cloudflare.com.		300	IN	CAA	0 issuewild "digicert.com; cansignhttpexchanges=yes"
cloudflare.com.		300	IN	CAA	0 iodef "mailto:[email protected]"
A real CAA record as a resolver returns it
Look one up
CAA Record Lookup

What does a CAA record do?

CAA is record type 257, defined in RFC 8659 (which obsoleted RFC 6844). It exists to close a structural weakness in the web PKI: any of the hundreds of trusted CAs can issue a certificate for any domain. CAA lets the domain owner publish a machine-readable allowlist, and the CA/Browser Forum Baseline Requirements make checking it mandatory before issuance. Unlike a TXT record, CAA has a real structured wire format — flags, tag, and value are separate fields, not a string you parse.

The enforcement point is the CA, not the browser. A browser does not look at CAA when validating a connection — by then the certificate exists and CAA is irrelevant. CAA is a control on the *issuance* process, which is exactly why it is useful: it stops an attacker who has compromised a domain-validation flow at some unrelated CA from getting a working certificate for your name.

CAA Record Lookup
Which certificate authorities may issue for a domain

CAA syntax and fields

FieldExampleMeaning
Name (owner)google.com.The domain the policy applies to. CAA is inherited by subdomains via tree climbing.
TTL9310Cache lifetime.
Class / TypeIN CAARecord type 257.
Flags08-bit field. Only bit 0 — the critical flag, value 128 — is defined. 0 is the normal value.
TagissueProperty name: issue, issuewild, or iodef. Case-insensitive.
Value"pki.goog"Quoted string. A CA domain for issue/issuewild, a URL for iodef. Optional key=value parameters follow a semicolon.

The three tags

  • `issue` — authorizes a CA to issue certificates for this domain. 0 issue "letsencrypt.org" permits Let's Encrypt. The special value 0 issue ";" authorizes no CA, which is how you say "never issue certificates for this name".
  • `issuewild` — authorizes a CA specifically for wildcard certificates. If any issuewild record is present, it governs wildcards entirely and issue records are ignored for wildcard requests. If no issuewild exists, issue covers both. This asymmetry is the subtlest part of CAA.
  • `iodef` — where the CA should report a policy violation, as mailto: or an https:// endpoint. Reporting is best-effort and CAs vary in whether they send anything, so treat it as a bonus rather than a monitoring channel.

The value string is the CA's own CAA identifier — a specific domain string the CA publishes, not a guess. letsencrypt.org, pki.goog, digicert.com, sectigo.com, comodoca.com, ssl.com, amazon.com, and amazontrust.com are common ones, but the authoritative source is always the CA's current documentation. Getting the string wrong is functionally identical to not authorizing them.

A CA may accept several identifier strings, and some organizations issue under multiple brands. If you use a reseller or a cloud provider's managed certificates, ask which CAA identifier their issuance uses before you lock the domain down.

The critical flag

The flags byte has one defined bit: bit 0, the issuer critical flag, written as the value 128. It means "if you do not understand this property tag, you must refuse to issue" — a fail-closed instruction for future tags a CA might not recognize.

For the three standard tags you should use 0. Setting 128 issue "letsencrypt.org" is legal and behaves the same way in practice for a CA that understands issue, but it adds no security and risks unexpected refusals. Real zones almost universally publish 0, as both examples above do. Reserve the critical flag for a case where you genuinely need unknown-tag handling to fail closed.

How CAs check: tree climbing

A CA asked to issue for shop.eu.example.com does not just query that exact name. It climbs:

  1. Query shop.eu.example.com for CAA. If a record set exists, that set is the policy — the search stops, and parent records are not consulted.
  2. If empty, query eu.example.com. Same rule.
  3. Continue up to example.com, and stop at the registrable domain boundary.
  4. If no CAA record is found anywhere on the path, issuance is unrestricted.

Two consequences follow that catch people out. First, a CAA set at a subdomain completely overrides the parent — it does not merge. If example.com permits Let's Encrypt and api.example.com publishes 0 issue "digicert.com", then Let's Encrypt cannot issue for api.example.com. Second, CNAMEs are followed before the climb: if the name is an alias, the CA follows the CNAME and evaluates CAA at the target, which means a vendor's CAA policy can govern your subdomain.

Also note that CAA lookups happen against the live DNS at issuance time, and a SERVFAIL is not the same as an empty answer — under RFC 8659 a CA must treat a lookup failure as a reason not to issue (with narrow retry allowances). A broken DNSSEC signature on your zone can therefore block certificate renewal while the site itself still loads for non-validating resolvers. Check with the DNSSEC checker if renewals start failing for no visible reason.

A realistic policy

; Only Let's Encrypt may issue, including wildcards
example.com.  3600  IN  CAA  0 issue "letsencrypt.org"
example.com.  3600  IN  CAA  0 issuewild "letsencrypt.org"
example.com.  3600  IN  CAA  0 iodef "mailto:[email protected]"

; A subdomain that uses a different CA — this OVERRIDES the parent entirely
api.example.com.  3600  IN  CAA  0 issue "digicert.com"

; A name that should never have a certificate
internal.example.com.  3600  IN  CAA  0 issue ";"
Publishing both issue and issuewild is the clearest way to express intent, since issuewild alone governs wildcards when present.

Before you publish, enumerate every certificate you actually have — including ones a CDN, load balancer, or platform issues on your behalf — and make sure each issuing CA is listed. A CAA record that omits the CA your renewals depend on breaks nothing today and breaks everything in ninety days.

TTL guidance

3600 is a sensible default. CAA records are queried only at issuance, so query volume is negligible and there is no performance argument for either extreme. Do drop the TTL to 300 for the hour or two around a CA change — CAs may hold a cached answer, and you want a newly added authorization visible before you trigger the issuance. Raise it again afterwards.

Common CAA mistakes

  • Locking out the CA you actually use. Publishing 0 issue "letsencrypt.org" while your CDN silently renews through a different CA means renewals begin failing at the next cycle, not immediately. Inventory first.
  • Forgetting `issuewild`. If you publish any issuewild record, it alone governs wildcard requests. A policy of 0 issuewild "digicert.com" with 0 issue "letsencrypt.org" means Let's Encrypt cannot issue your wildcard.
  • Using the wrong identifier string. letsencrypt.com, sectigo.net, or a marketing brand name instead of the published CAA identifier. Check the CA's current docs.
  • Including a scheme or path. The value is a bare domain — "https://letsencrypt.org" is wrong.
  • Expecting CAA to revoke existing certificates. It does not. Adding CAA today has no effect on a certificate issued yesterday; that one remains valid until it expires or is revoked.
  • Assuming it stops all mis-issuance. CAA binds compliant CAs. A CA that ignores it, or a compromised one, is not stopped by a DNS record. It raises the bar, it does not close the door.
  • Setting the critical flag without reason. 128 on a standard tag adds risk and no benefit.
  • A subdomain CAA that unintentionally overrides the parent. Remember the set at the closest name wins outright; there is no merging.

Check it with dig

# CAA policy for a domain
dig +short google.com CAA

# Full record set with TTLs
dig +noall +answer cloudflare.com CAA

# Walk the tree the way a CA does — the first non-empty set wins
dig +short shop.eu.example.com CAA
dig +short eu.example.com CAA
dig +short example.com CAA

# Straight from the authoritative server
dig +noall +answer @ns1.google.com google.com CAA

# What certificate is actually deployed, and who issued it?
openssl s_client -connect google.com:443 -servername google.com </dev/null 2>/dev/null \
  | openssl x509 -noout -issuer -subject -dates
Run the openssl line before publishing CAA — the issuer it reports must be authorized by the policy you are about to write.

Cross-check the deployed certificate and chain with the SSL certificate checker, and read expiry dates from the command line using Check SSL expiry with OpenSSL. If a renewal has already failed and the certificate has lapsed, Fix ERR_CERT_DATE_INVALID covers the browser-side symptoms; an unrelated-looking browser error may instead be an incomplete chain.

Frequently asked questions

Does a CAA record stop an existing certificate from working?
No. CAA is checked only at issuance. Certificates already issued remain valid until they expire or are revoked, regardless of what your CAA record says. Adding a restrictive CAA record affects your next renewal, not the certificate currently being served.
What happens if I have no CAA record?
Any publicly trusted CA may issue for your domain, subject to its own domain-validation checks. That is the default for most domains and it is not an error — CAA is optional. Publishing one narrows the set of CAs that can be tricked into issuing for you.
Do I need both issue and issuewild?
Only if you want different policies for wildcards. If no issuewild record exists, issue covers wildcard requests too. But the moment you publish any issuewild record, it governs wildcards exclusively and issue is ignored for them — so publishing both explicitly is the least surprising configuration.
Which CAA identifier string should I use for my CA?
The exact string the CA publishes in its own documentation — letsencrypt.org, pki.goog, digicert.com, and so on. It is not derived from the CA's website or brand name, and a wrong string simply means that CA is not authorized. Check the CA's current docs rather than copying from a blog post.
How do I forbid all certificate issuance for a hostname?
Publish 0 issue ";" at that name. The semicolon value authorizes no CA, and because a CAA set at a subdomain overrides the parent, this works even when the parent domain permits issuance. It is a useful control for internal-only names that should never appear in a public certificate.
Can CAA break my certificate renewals?
Yes, in two ways. Omitting the CA that actually performs your renewals means the next renewal is refused. And because a CA must treat a failed CAA lookup as a reason not to issue, a DNS outage or a broken DNSSEC signature at renewal time can block issuance even though your CAA policy is correct.