DKIM public keys are published at <selector>._domainkey.<domain> as TXT records. There is no way to list them — DNS has no directory operation, so you cannot ask "what selectors exist for example.com". You have to know the name, or guess it. Three methods, in order of reliability.
Method 1 — Read the s= tag from a real message
This is definitive. Every DKIM-signed message carries a DKIM-Signature header, and the s= tag in it names the selector that signed it. Find any message the domain sent, view the original source, and look at the top of the header block.
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=selector1;
h=from:to:subject:date:message-id;
bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
b=Xk9pQ2mR7vN4tY8wL3cE5aB1dF6gH0jK2lM4nO7pQ9rS...Two tags matter together. d=example.com is the signing domain and s=selector1 is the selector. The key lives at selector1._domainkey.example.com. If d= is a vendor domain rather than yours, the message is signed by the vendor and will not align for DMARC on your domain — see DMARC policy not enabled for why that matters.
Where to find the raw source in common clients: Gmail uses the three-dot menu then "Show original"; Outlook on the web uses "View message source"; Apple Mail uses View → Message → Raw Source. Then confirm the key resolves:
dig +short TXT selector1._domainkey.example.com
# A live example — Stripe signs with the selector "google":
dig +short TXT google._domainkey.stripe.com
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4T1PE2vh5..."A valid answer starts with v=DKIM1 (or begins straight at k=rsa — the version tag is recommended but not mandatory) and contains a p= tag with the base64 public key. If p= is present but empty, the key has been revoked, which is a deliberate signal and not the same as a missing record. If you would rather have the header parsed for you, paste the whole message source into the email header analyzer.
s=/d= pair, not just the first.Method 2 — Try your provider’s default selector
Most providers use fixed or predictable selector names. If you know who sends your mail, try theirs first. These are the defaults at the time of writing; providers do change them and some let you set a custom selector, so treat this as a starting point rather than gospel and check your provider’s current documentation if none of them resolve.
| Provider | Typical selector(s) | Record type at your zone |
|---|---|---|
| Google Workspace | google (default; configurable when generating the key) | TXT |
| Microsoft 365 | selector1, selector2 | CNAME → selector1-<domain-key>._domainkey.<tenant>.onmicrosoft.com |
| SendGrid | s1, s2 | CNAME → s1.domainkey.uNNNNNN.wlNNN.sendgrid.net |
| Mailchimp / Mandrill | k1, k2, k3 | CNAME → dkim.mcsv.net |
| Zoho Mail | zoho (default; user-chosen on newer setups) | TXT |
| Proton Mail | protonmail, protonmail2, protonmail3 | CNAME → <selector>.domainkey.<hash>.domains.proton.ch |
| Amazon SES | Three rotating token selectors, or a custom BYODKIM selector | CNAME → <token>.dkim.amazonses.com |
| Postmark | pm, or a custom selector you choose | TXT or CNAME |
| Mailgun | mailo, smtp, k1, or a chosen selector | TXT |
| Fastmail | fm1, fm2, fm3 | CNAME → fmN.<domain>.dkim.fmhosted.com |
Notice how many are CNAMEs. That is deliberate: pointing at the provider lets them rotate the underlying key without you touching DNS again. It also means dig +short TXT still returns the key, because the resolver follows the CNAME for you:
# The CNAME itself
dig +short CNAME selector2._domainkey.microsoft.com
selector2-microsoft-com._domainkey.microsoft.onmicrosoft.com.
# Querying TXT follows the CNAME and returns the key
dig +short TXT selector2._domainkey.microsoft.com
selector2-microsoft-com._domainkey.microsoft.onmicrosoft.com.
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."If the CNAME resolves but the TXT lookup returns nothing, the delegation target has no key yet — for Microsoft 365 that usually means signing has never been switched on for the domain. Microsoft 365 DKIM setup covers that case specifically.
Method 3 — Scan common selectors
When you have no headers and no idea who the provider is, brute force works, because the selector namespace people actually use is small. Query a candidate list and keep whatever answers.
domain=example.com
for s in google selector1 selector2 s1 s2 k1 k2 k3 \
default dkim mail email smtp zoho protonmail protonmail2 \
fm1 fm2 fm3 pm mandrill mailo mte1 mte2 sig1 scph0
do
rec=$(dig +short TXT "$s._domainkey.$domain")
[ -n "$rec" ] && echo "FOUND selector: $s"
doneThis is exactly what the DKIM checker does — it runs a much longer candidate list in parallel and validates whatever it finds, which is faster than a serial shell loop and does not depend on your local resolver. Use the loop when you are on a jump box with no browser.
2026q3 or a random SES token will never appear in any candidate list. Absence of evidence here is genuinely weak evidence — go back to Method 1 and get a real message.Reading the key record
| Tag | Meaning | Notes |
|---|---|---|
v=DKIM1 | Version | Recommended first tag; some valid records omit it |
k=rsa | Key type | rsa or ed25519; defaults to rsa if absent |
p= | Base64 public key | Empty p= means the key is explicitly revoked |
t=y | Testing mode | Receivers should not treat a failure as a failure — remove after testing |
t=s | Strict i= scope | Subdomains may not use this key |
h=sha256 | Permitted hash algorithms | Optional; restricts what the signer may use |
Long RSA keys exceed the 255-character limit for a single DNS character-string, so they are published as several quoted chunks that concatenate. dig shows them as adjacent quoted strings on one line; that is correct and not a corruption. What *is* a corruption is a copy-paste that leaves a space or newline inside the base64 of p=.
What if several systems send as the domain?
Then you have several selectors, and finding one does not mean you are done. A typical organization signs with its mailbox provider’s selector for staff mail, a transactional ESP’s selector for receipts and password resets, and a marketing platform’s selector for campaigns — three different selectors, all with d=example.com if they are configured correctly.
The way to enumerate them is by source, not by DNS. Send one message through each system and read the s= tag from each. If you cannot trigger every system on demand, DMARC aggregate reports do the job instead: each report names the source IP and the DKIM signing domain for every stream that sent as your domain that day. That is the only complete inventory available, which is another reason to publish rua= early — see DMARC record not found.
One selector per system also means one rotation schedule per system. When a vendor rotates and you had hard-coded a TXT key instead of using their CNAME, signing silently starts failing with no key for signature. If a stream that worked for months breaks overnight and the key no longer resolves, suspect a rotation you did not follow.
Related checks
- Verify the whole authentication picture with the deliverability test.
- See every TXT record on the domain at once with the TXT record lookup, and read the TXT record reference.
- If DKIM resolves but messages still fail, the problem is usually the body hash — see dkim=fail body hash did not verify.
- Check DMARC alignment for the signing domain with the DMARC checker.
- Confirm SPF is healthy alongside it with the SPF checker.