GET/api/v2/dkim
DKIM check API
A domain's DKIM public keys: the selectors you name, or a sweep of about 140 provider and common selectors, each key record parsed with its type, size, flags and findings.
- 20 calls a minute per IP
- Same engine as the DKIM Checker tool
{
"query": {
"domain": "github.com",
"selectors": []
},
"state": "keys",
"usableKeys": 12,
"selectors": [
{
"selector": "google",
"name": "google._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "google",
"name": "Google Workspace"
},
"cnameTarget": null,
"ttl": 3600,
"keys": [
{
"record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj6T5sl/RwdSqGoYWaWaFbS2UAeyPrEmd0gogocmRfS441qwR8/0KB81Hw89P0l4YiFRrXYk7NVIGfyCRHAYYZUzCkGeOysI2EjgzLFhd/NEsbRzOEc/kWkK/RO6JFq/5lOn6M9AZw/ap9tds4JG9ApgNNdSpPxp9DmvpsOSgNMVflRxQFrk3kdS4RNAPKu/OPoA7dlR/A/pECryjRoYgENtDXzdnK70HgCekems6UDzxDj61cjyoKoXtEMF/QsaHEQ1Gjfv014rDJBsubk/kT5VqHkWHa/ia68Z5r228Ety/wFfQNjXTx/J7KGZ9GkZlKED659eiJcLnWcKDSiQlhwIDAQAB",
"version": "DKIM1",
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 410,
"strings": 2
}
]
},
{
"selector": "selector1",
"name": "selector1._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "microsoft365",
"name": "Microsoft 365 / Exchange Online"
},
"cnameTarget": "selector1-github-com._domainkey.microsoft.onmicrosoft.com",
"ttl": 3600,
"keys": [
{
"record": "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxZC/z2cK+2s1f/ktzSDSeFzkfIHrjwtGFsfKMAYvKaXjPVNzKykpbXBkX5nB7dVUTFttda7aROr2iSrIseQ27Ui+4rUZVzgFanE8RaXhYM9n5wPKNv8GtLJk7JgcsYZ7ErgID4uW2sEYyV/dnRYw6rDzOaeRKkKELTUfJI5ebLQIDAQAB;",
"version": "DKIM1",
"keyType": "rsa",
"bits": 1024,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 235,
"strings": 1
}
]
},
{
"selector": "selector2",
"name": "selector2._domainkey.github.com",
"status": "standby",
"named": false,
"rcode": "NXDOMAIN",
"provider": {
"id": "microsoft365",
"name": "Microsoft 365 / Exchange Online"
},
"cnameTarget": "selector2-github-com._domainkey.microsoft.onmicrosoft.com",
"ttl": null,
"keys": []
},
{
"selector": "s1",
"name": "s1._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "sendgrid",
"name": "Twilio SendGrid"
},
"cnameTarget": "s1.domainkey.u51742174.wl175.sendgrid.net",
"ttl": 1800,
"keys": [
{
"record": "k=rsa; t=s; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyn3fMCVpb7ryIRKOGXhXVGYmsWUitNlSckqGHOwNFZgFadplOrD+Qzf1XQkP7MH/VB/97DsAAJGtEXW1Uq71Hjnfr/DuBN/YfjF/gU70qEFb7q1sdIiNtjFL2TkOpoW+X/bhhPNheW/fYwyFb6ZHFM6LTgXyuimWRHTOUP3VjZzhNVda79nt+2WZYbS4l8HdMgWpTNHjpVw5PtXESA9KBg/evSRk5fIaXIX5eRXW3baoV9yVzD8O29/IL/DiSk+yNvaO0EHL5c4yGuZJhGzvpiznb2IDVdemJK4Dqzdy5FTN/SGYZhAEr7MguG3Z314hMS2scgMsOMgB64uj/6+6UwIDAQAB",
"version": null,
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": true,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 406,
"strings": 2
}
]
},
{
"selector": "s2",
"name": "s2._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "sendgrid",
"name": "Twilio SendGrid"
},
"cnameTarget": "s2.domainkey.u51742174.wl175.sendgrid.net",
"ttl": 1800,
"keys": [
{
"record": "k=rsa; t=s; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNt2/H6bKs99C6DAaokPp62KN9mKaD20D1PBakkObejkJvzM6Un/fKHPeI2/qXdvFFBPQE3mxMNoe+hwBVDgMgCuZEn8J6gZYI4amITure9/ny6+GaNVRoH2m6xAtWwKINkKxMayGiehkWlRVb7D23F0U8y+VDHKQFz1bnXA5jDpcDiMXy8i2lV5vEys+qt+1WGhDKCAwamT8c3xkZz8aXMJaXYCiN2HMgHDU81+mVCk4+u6mY+a98APVfFhsQ0KCq/mVZXaXTV06QrG9M5PtBHUFW7VtwXKp+AFrAut0KW1NnwaA5IGA5sc+n9dma7bSqdfGS+ixdSmJ69NwmYSHwIDAQAB",
"version": null,
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": true,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 406,
"strings": 2
}
]
},
{
"selector": "k2",
"name": "k2._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "mailchimp",
"name": "Mailchimp (Marketing)"
},
"cnameTarget": "dkim2.mcsv.net",
"ttl": 12337,
"keys": [
{
"record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2aC2KjGKLOwTweBY5A9RpjsxaBXR9r7OAU6U8/zn92ivImI75naUujWbItRI/QmL1jy5PWGqLwoUA0b90ObWaLDc+i9MtTNmGeWO009hr20fIxhGg6XBT2kjZ1DTThopSe1nAndsupmcBwlQ5Q6LJ+ZAxLcujnPIxM0ZBLmgpkv8u6RfY4eFP8OLvdAW3oSuB0DyLDigQX4Sj8wBO4YIdQH6AAmBeOsidsKAFNFUCpc3vCxtBDR12U+cBg724l3sBkMQ8evnz6idnqxq9QAVYh8k4kJ+RP+6cqTdy7LjIm8xY/bQNpQIpGUAuDo2DjLcCDun9DAI4Q/3z+Q0o9QuQIDAQAB;",
"version": "DKIM1",
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 411,
"strings": 2
}
]
},
{
"selector": "cm",
"name": "cm._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": null,
"cnameTarget": null,
"ttl": 3600,
"keys": [
{
"record": "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXLybkpDQnCyQYlQc46kL2sPMsYDqwkjPyFRSDiaq6qUeujAlU775+f8rzxIrjHc8sPstAZOuJzqcgDPiidRxdE2Th/lcnfbN4btWvJwHKK6KD/IazNWNqQtunYyPzfmSRTtOE4Nii4Oxwx1glTJAVhCTObD2uh2U44lCG+pgYswIDAQAB",
"version": null,
"keyType": "rsa",
"bits": 1024,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 225,
"strings": 1
}
]
},
{
"selector": "zendesk1",
"name": "zendesk1._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "zendesk",
"name": "Zendesk"
},
"cnameTarget": "zendesk1._domainkey.zendesk.com",
"ttl": 3600,
"keys": [
{
"record": "v=DKIM1;t=s;n=core;k=rsa;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9IqdLrO3Zr2/56MHt8oQVCQorP0Bl2Fz9sM2tFBnJCdB/HogQmuudEg2xAovCN2PYpw44UijIvPuBoT9vxiv6ZCBJTLJXa82r6ke5rE4tbe9NKFIrVIb9S306cJDrnKFMDb8p0dU/Su0+eUR5gVAOtCuz2L8HAzs5edvsEvD/Fb4ny1RLNSEPZkIQLfGhVxQeWANm3+1Jwb/OBVXV9k0nKpWrpgqcmO7NzroJirp014RQY7rGi60JLUubc6XhvoFQBQrtOAdVlZC5wvfS1bgpq5kQpdP7cajIqWCeqxPTeo0ZUpey2ZcaygEsZz0Z3Gs5wDzyuqd7/ADpr2jNF7ozwIDAQAB",
"version": "DKIM1",
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": true,
"hashes": null,
"services": [
"*"
],
"notes": "core",
"bytes": 419,
"strings": 2
}
]
},
{
"selector": "zendesk2",
"name": "zendesk2._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "zendesk",
"name": "Zendesk"
},
"cnameTarget": "zendesk2._domainkey.zendesk.com",
"ttl": 3600,
"keys": [
{
"record": "v=DKIM1; t=s; n=core; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmiSFNkgXrO3I8aOaPONDZWHv027rkiGIwb838OyXPgvFDEkCV/qGcdXSjZnaVAadrTm/oKnL8WOltP9zB1FLEuKt0fTi5zRyKPE4oIYCnEzXwrGqzjUcCABQBawQVqvXjDOaYh9Lhp8W5PYOLo905vRW7ipyIMDhuzBOJls91/WWXnNK0OwP3RghiisZjA3K2KqtRwf7w6GjNeNuAMNhvcmgAN15d/mhK+dev/hcRbal66RoYyTD8c0F0isahWH0envEX8aj+SBhheNk0/U37dGE+4nFaY5yP9CUlYjFKDSIKZgHzG4Hci3t/RubU58pi6BCrQQdAFvIOeDFeCZ0ywIDAQAB",
"version": "DKIM1",
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": true,
"hashes": null,
"services": [
"*"
],
"notes": "core",
"bytes": 423,
"strings": 2
}
]
},
{
"selector": "k1",
"name": "k1._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "mailchimp",
"name": "Mailchimp (Marketing)"
},
"cnameTarget": "dkim.mcsv.net",
"ttl": 21600,
"keys": [
{
"record": "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbNrX2cY/GUKIFx2G/1I00ftdAj713WP9AQ1xir85i89sA2guU0ta4UX1Xzm06XIU6iBP41VwmPwBGRNofhBVR+e6WHUoNyIR4Bn84LVcfZE20rmDeXQblIupNWBqLXM1Q+VieI/eZu/7k9/vOkLSaQQdml4Cv8lb3PcnluMVIhQIDAQAB;",
"version": null,
"keyType": "rsa",
"bits": 1024,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 226,
"strings": 1
}
]
},
{
"selector": "k3",
"name": "k3._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "mailchimp",
"name": "Mailchimp (Marketing)"
},
"cnameTarget": "dkim3.mcsv.net",
"ttl": 14400,
"keys": [
{
"record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsYGiMSn7fsUqSvfSX40x9R1OlRtbNiCY80lHRIlcKx3XDIR7257aUx+q9CSIARdfTL6KCuLGNFx5g9TgVr6png4ajcieSQGtOehBgxnkDN8aAA5TX0FmFrcefJU0JoxLOF09EKgXxhSSHCk/ekVb0PXSboHXoZ9+EI404F1qhcwXXIgHXTaUthHTut2P6BBZhIXIgvDe/w49GchR7MRJqjNb7neEBbYHbgWuBTvvHCg7Gy6m6n9krYK+ROWq3dVvXy9plAGK3ygM+HtjIiMt7arRGMOF0WgDTz7YdN9BGpt6BvXxLnjiQcgS5T9n+cIyPZgiWzDMXNlaEEdKTEKxrwIDAQAB;",
"version": "DKIM1",
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 411,
"strings": 2
}
]
},
{
"selector": "smtpapi",
"name": "smtpapi._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": null,
"cnameTarget": null,
"ttl": 3600,
"keys": [
{
"record": "k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPtW5iwpXVPiH5FzJ7Nrl8USzuY9zqqzjE0D1r04xDN6qwziDnmgcFNNfMewVKN2D1O+2J9N14hRprzByFwfQW76yojh54Xu3uSbQ3JP0A7k8o8GutRF8zbFUA8n0ZH2y0cIEjMliXY4W4LwPA7m4q0ObmvSjhd63O9d8z1XkUBwIDAQAB",
"version": null,
"keyType": "rsa",
"bits": 1024,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": true,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 230,
"strings": 1
}
]
},
{
"selector": "mailo",
"name": "mailo._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": null,
"cnameTarget": null,
"ttl": 3600,
"keys": [
{
"record": "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQPJBpMLQPx0UvC5HXIoVHgwfowk1OjOqnQNcVjbcpKTcCeOkXuTdT1U33weODlOlNTB+GIFWRpDGYZDdMvu2ffzpHTNMeRALvMhIrzNLpJbco+InXab5PzFnGdaBNVUKhv7zPlBkYKA3tNKwyRwCH8Wgja3q7Mg8rUIBklICYfQIDAQAB",
"version": null,
"keyType": "rsa",
"bits": 1024,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 225,
"strings": 1
}
]
}
],
"providers": [
{
"id": "google",
"name": "Google Workspace",
"selectors": [
"google"
]
},
{
"id": "microsoft365",
"name": "Microsoft 365 / Exchange Online",
"selectors": [
"selector1",
"selector2"
]
},
{
"id": "sendgrid",
"name": "Twilio SendGrid",
"selectors": [
"s1",
"s2"
]
},
{
"id": "mailchimp",
"name": "Mailchimp (Marketing)",
"selectors": [
"k2",
"k1",
"k3"
]
},
{
"id": "zendesk",
"name": "Zendesk",
"selectors": [
"zendesk1",
"zendesk2"
]
}
],
"wildcard": false,
"sweep": {
"tried": 140,
"answered": 140,
"failed": 0,
"skipped": 0,
"stoppedEarly": false
},
"missing": [],
"issues": [
{
"severity": "warning",
"code": "rsa_weak",
"message": "selector1: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for 2048; M3AAWG calls 1024-bit keys “at the edge of attack”.",
"selector": "selector1"
},
{
"severity": "warning",
"code": "rsa_weak",
"message": "cm: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for 2048; M3AAWG calls 1024-bit keys “at the edge of attack”.",
"selector": "cm"
},
{
"severity": "warning",
"code": "rsa_weak",
"message": "k1: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for 2048; M3AAWG calls 1024-bit keys “at the edge of attack”.",
"selector": "k1"
},
{
"severity": "warning",
"code": "rsa_weak",
"message": "smtpapi: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for 2048; M3AAWG calls 1024-bit keys “at the edge of attack”.",
"selector": "smtpapi"
},
{
"severity": "warning",
"code": "rsa_weak",
"message": "mailo: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for 2048; M3AAWG calls 1024-bit keys “at the edge of attack”.",
"selector": "mailo"
},
{
"severity": "info",
"code": "standby_cname",
"message": "selector2: Standby CNAME. Points at the provider with no key yet: the slot it rotates into, while another selector holds the live key (selector2-github-com._domainkey.microsoft.onmicrosoft.com).",
"selector": "selector2"
},
{
"severity": "info",
"code": "strict",
"message": "s1: Strict (t=s). i= must equal d= exactly: a subdomain can't sign with this key. Usual for providers' keys.",
"selector": "s1"
},
{
"severity": "info",
"code": "strict",
"message": "s2: Strict (t=s). i= must equal d= exactly: a subdomain can't sign with this key. Usual for providers' keys.",
"selector": "s2"
},
{
"severity": "info",
"code": "strict",
"message": "zendesk1: Strict (t=s). i= must equal d= exactly: a subdomain can't sign with this key. Usual for providers' keys.",
"selector": "zendesk1"
},
{
"severity": "info",
"code": "strict",
"message": "zendesk2: Strict (t=s). i= must equal d= exactly: a subdomain can't sign with this key. Usual for providers' keys.",
"selector": "zendesk2"
},
{
"severity": "info",
"code": "strict",
"message": "smtpapi: Strict (t=s). i= must equal d= exactly: a subdomain can't sign with this key. Usual for providers' keys.",
"selector": "smtpapi"
}
],
"tookMs": 805
}How it works
DNS can't list a domain's DKIM selectors, so without selector the check asks about 140 selectors that email providers document or commonly use (16 at a time, inside 9 seconds), plus a random name to spot wildcards. With selector only those are asked. Each key record is read as RFC 6376 defines it: key type and size on RFC 8301's scale, t=y testing, t=s strict, h= and s= restrictions, an empty p= (revoked, or a provider's standby slot), and the provider behind the selector from its CNAME.
state is honest about what DNS can show: none_found means no key among the selectors tried, not "no DKIM" (name the selector from a message's DKIM-Signature s= tag to check it), and a lookup that failed is "couldn't check" (incomplete), never "missing". A provider CNAME with nothing behind it is told apart: a rotation slot when the provider serves a key at another selector, dangling otherwise.
This checks published keys. Verifying a message's signature (the body hash and header signature) needs the message itself and isn't part of the API: use the DKIM Checker's Verify mode, which runs in your browser.
Query parameters
domainstringrequiredThe domain whose DKIM keys to find.selector._domainkey.example.comnames a selector too. A URL (its host), an email address (its domain), an IDN in Unicode or a trailing dot are read the way the tool page reads them; the normalised name comes back inquery.domain.selectorstringoptionalOne or more selectors, comma-separated (at most 20): only these are checked. Without it, about 140 provider and common selectors are swept.
Response fields
200 with this JSON object, plus tookMs, and incomplete with warnings when a source failed. Fields marked optional appear only when they apply.
queryobjectalwaysWhat was looked up, normalised (lower case, no trailing dot, IDNs as Punycode).domainstringalwaysThe domain checked, lower case, IDNs as Punycode.selectorsarray of stringsalwaysThe selectors named inselector(or indomainas selector._domainkey.domain); empty when the sweep ran.
statestringalwaysThe overall reading:keys(at least one usable key),unusable(key records found, none usable: revoked or broken),wildcard_revoked(every selector answers an empty key: the domain says it signs nothing),none_found(no key among the selectors tried: DNS can't list selectors, so this is not proof of no DKIM),domain_missing(NXDOMAIN),incomplete(no key found and some lookups failed or ran out of time).one of
"keys","unusable","wildcard_revoked","none_found","domain_missing","incomplete"usableKeysintegeralwaysSelectors with a usable key (a usable wildcard key counts once).selectorsarray of objectsalwaysEvery selector with a key record or a provider CNAME, and every selector you named, in the order tried. The sweep's empty answers are left out (seesweep).Show 9 fields
selectorstringalwaysThe selector, e.g.google,selector1.namestringalwaysThe name asked:<selector>._domainkey.<domain>.statusstringalwaysfound(DKIM key records: seekeys),standby(a provider CNAME with no key while the provider serves one elsewhere: a rotation slot),dangling(a CNAME to a provider name with no key behind it),none(NXDOMAIN),empty(the name exists with no TXT),not_dkim(TXT that isn't a key),wildcard(only the zone's wildcard answers),error(the lookup failed: couldn't check),skipped(the deadline came first).one of
"found","not_dkim","empty","none","standby","dangling","wildcard","error","skipped"namedbooleanalwaysYou named this selector (it is checked whatever the sweep finds).rcodestring or nullalwaysThe DNS answer's code (NOERROR, NXDOMAIN, SERVFAIL, TIMEOUT…);nullwhen it wasn't asked.providerobject or nullalwaysThe provider behind the selector: from the CNAME target, or the one provider documenting the selector when a key was found;nullwhen unknown.Show 2 fields
idstringalwaysOur stable id for the company, e.g.google,microsoft365,sendgrid.namestringalwaysIts name as it writes it, e.g.Google Workspace.
cnameTargetstring or nullalwaysThe CNAME chain's last target (the provider's name for the key);nullwhen the selector isn't an alias.ttlinteger or nullalwaysThe key record's TTL in seconds.keysarray of objectsalwaysThe DKIM key records at the name (usually one).Show 15 fields
recordstringalwaysThe record's text as published (TXT strings joined), at most 4,096 characters.versionstring or nullalwaysv= as written (DKIM1);nullwhen absent (it is optional).keyTypestringalwaysk=, lower case:rsa(the default),ed25519, or what was written.bitsinteger or nullalwaysThe key's size in bits (RSA modulus; 256 for Ed25519);nullwhen revoked (empty p=) or unreadable.formatstring or nullalwaysHow p= encodes the key:spki(SubjectPublicKeyInfo, what RFC 6376 specifies),pkcs1(a bare RSAPublicKey: some verifiers reject it),raw(Ed25519's 32 bytes).nullwhen there is no readable key.one of
"spki","pkcs1","raw",nullusablebooleanalwaysSignatures made with this key can verify: not revoked, the key decodes, at least 1024-bit RSA, email allowed, an accepted hash left.revokedbooleanalwaysp= is empty: the key is revoked or retired (RFC 6376 §3.6.1).standbybooleanalwaysAn empty p= behind a provider's CNAME while that provider serves a key at another selector: a rotation slot, nothing to fix.testingbooleanalwayst=y: the domain is testing DKIM; receivers treat mail signed with this key as unsigned.strictbooleanalwayst=s: the signing domain (i=) must equal d= exactly, no subdomains.hashesarray of strings or nullalwaysh=: the hash algorithms allowed, lower case;nullwhen absent (all allowed).servicesarray of stringsalwayss=: the services the key is for (*all,email);["*"]when absent.notesstring or nullalwaysn= (notes for people), decoded;nullwhen absent.bytesintegeralwaysThe record's size in bytes.stringsinteger or nullalwaysHow many TXT strings it was published in (a long key needs several of up to 255 bytes);nullwhen unknown.
providersarray of objectsalwaysThe email providers seen at the domain, from CNAME targets and documented selectors.idstringalwaysOur stable id for the provider.namestringalwaysIts name.selectorsarray of stringsalwaysThe selectors it was seen through.
wildcardbooleanalwaysA random selector name answered: a wildcard covers_domainkey.<domain>, so names that only echo it aren't keys.sweepobjectalwaysWhat the selector questions came to.Show 5 fields
triedintegeralwaysSelectors asked (about 140 provider and common ones in a sweep; only yours withselector).answeredintegeralwaysQuestions answered (NOERROR or NXDOMAIN).failedintegeralwaysQuestions that failed (SERVFAIL, timeout, query budget): those selectors couldn't be checked.skippedintegeralwaysSelectors not asked before the deadline.stoppedEarlybooleanalwaysThe zone stopped answering, so the sweep stopped asking.
missingarray of stringsalwaysSelectors you named that answered with no key.issuesarray of objectsalwaysWhat the key records and selectors show, worst first, in the DKIM Checker's words.errorbreaks something (receivers fail it),warningrisks it,infois worth knowing.Show 4 fields
severitystringalwayserrorbreaks something (receivers fail it),warningrisks it,infois worth knowing.one of
"error","warning","info"codestringalwaysStable machine-readable code, e.g.rsa_weak,revoked,dangling_cname,no_key_found.messagestringalwaysThe finding in plain English, starting with the selector it is about.selectorstringoptionalThe selector it is about; absent for findings about the whole domain.
Errors
429rate_limitedThe domain (its registrable domain) was checked 30 times in the last minute by all callers together, or every caller together reached 600 a minute: retry afterRetry-Afterseconds.
Plus the errors every endpoint can return: 400 for a missing or unreadable parameter, 429 past the limit, 503 when every source failed.
Code samples
curl "https://dnsrobot.net/api/v2/dkim?domain=github.com"const params = new URLSearchParams({ domain: "github.com" });
const res = await fetch(`https://dnsrobot.net/api/v2/dkim?${params}`);
const data = await res.json();
if (!res.ok) throw new Error(data.error.message);
console.log(data.selectors);import requests
r = requests.get(
"https://dnsrobot.net/api/v2/dkim",
params={"domain": "github.com"},
timeout=30,
)
data = r.json()
if not r.ok:
raise RuntimeError(data["error"]["message"])
print(data["selectors"])package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
)
func main() {
q := url.Values{"domain": {"github.com"}}
res, err := http.Get("https://dnsrobot.net/api/v2/dkim?" + q.Encode())
if err != nil {
panic(err)
}
defer res.Body.Close()
var data map[string]any
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
panic(err)
}
if res.StatusCode != http.StatusOK {
panic(data["error"])
}
fmt.Println(data["selectors"])
}<?php
$query = http_build_query(["domain" => "github.com"]);
$context = stream_context_create(["http" => ["ignore_errors" => true, "timeout" => 30]]);
$data = json_decode(file_get_contents("https://dnsrobot.net/api/v2/dkim?" . $query, false, $context), true);
if (isset($data["error"])) {
throw new RuntimeException($data["error"]["message"]);
}
print_r($data["selectors"]);require "net/http"
require "json"
uri = URI("https://dnsrobot.net/api/v2/dkim")
uri.query = URI.encode_www_form(domain: "github.com")
data = JSON.parse(Net::HTTP.get(uri))
raise data["error"]["message"] if data["error"]
puts data["selectors"]// Cargo.toml: reqwest = { version = "0.13", features = ["blocking", "json"] }, serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
let res = reqwest::blocking::get("https://dnsrobot.net/api/v2/dkim?domain=github.com")?;
let ok = res.status().is_success();
let data: serde_json::Value = res.json()?;
if !ok {
return Err(data["error"]["message"].to_string().into());
}
println!("{}", data["selectors"]);
Ok(())
}using System.Text.Json;
using var http = new HttpClient();
var res = await http.GetAsync("https://dnsrobot.net/api/v2/dkim?domain=github.com");
var data = JsonDocument.Parse(await res.Content.ReadAsStringAsync()).RootElement;
if (!res.IsSuccessStatusCode)
throw new Exception(data.GetProperty("error").GetProperty("message").GetString());
Console.WriteLine(data.GetProperty("selectors"));Sweep github.com's selectors
GET /api/v2/dkim?domain=github.com{
"query": {
"domain": "github.com",
"selectors": []
},
"state": "keys",
"usableKeys": 12,
"selectors": [
{
"selector": "google",
"name": "google._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "google",
"name": "Google Workspace"
},
"cnameTarget": null,
"ttl": 3600,
"keys": [
{
"record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj6T5sl/RwdSqGoYWaWaFbS2UAeyPrEmd0g…",
"version": "DKIM1",
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 410,
"strings": 2
}
]
},
{
"selector": "selector1",
"name": "selector1._domainkey.github.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "microsoft365",
"name": "Microsoft 365 / Exchange Online"
},
"cnameTarget": "selector1-github-com._domainkey.microsoft.onmicrosoft.com",
"ttl": 3600,
"keys": [
{
"record": "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxZC/z2cK+2s1f/ktzSDSeFzkfIHrjwtGFsfKMAY…",
"version": "DKIM1",
"keyType": "rsa",
"bits": 1024,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 235,
"strings": 1
}
]
},
{
"selector": "selector2",
"name": "selector2._domainkey.github.com",
"status": "standby",
"named": false,
"rcode": "NXDOMAIN",
"provider": {
"id": "microsoft365",
"name": "Microsoft 365 / Exchange Online"
},
"cnameTarget": "selector2-github-com._domainkey.microsoft.onmicrosoft.com",
"ttl": null,
"keys": []
},
// … 10 more items
],
"providers": [
{
"id": "google",
"name": "Google Workspace",
"selectors": [
"google"
]
},
{
"id": "microsoft365",
"name": "Microsoft 365 / Exchange Online",
"selectors": [
"selector1",
"selector2"
]
},
{
"id": "sendgrid",
"name": "Twilio SendGrid",
"selectors": [
"s1",
"s2"
]
},
// … 2 more items
],
"wildcard": false,
"sweep": {
"tried": 140,
"answered": 140,
"failed": 0,
"skipped": 0,
"stoppedEarly": false
},
"missing": [],
"issues": [
{
"severity": "warning",
"code": "rsa_weak",
"message": "selector1: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks fo…",
"selector": "selector1"
},
{
"severity": "warning",
"code": "rsa_weak",
"message": "cm: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for 2048;…",
"selector": "cm"
},
{
"severity": "warning",
"code": "rsa_weak",
"message": "k1: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for 2048;…",
"selector": "k1"
},
// … 8 more items
],
"tookMs": 805
}Shortened for the page: long lists show their first items.
google.com's key at selector 20251104
GET /api/v2/dkim?domain=google.com&selector=20251104{
"query": {
"domain": "google.com",
"selectors": [
"20251104"
]
},
"state": "keys",
"usableKeys": 1,
"selectors": [
{
"selector": "20251104",
"name": "20251104._domainkey.google.com",
"status": "found",
"named": true,
"rcode": "NOERROR",
"provider": null,
"cnameTarget": null,
"ttl": 3600,
"keys": [
{
"record": "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwnvz/RbTmAzHDOG1WNdmD6Ma/b9X99aGWA…",
"version": "DKIM1",
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 410,
"strings": 2
}
]
}
],
"providers": [],
"wildcard": false,
"sweep": {
"tried": 1,
"answered": 1,
"failed": 0,
"skipped": 0,
"stoppedEarly": false
},
"missing": [],
"issues": [],
"tookMs": 72
}Shortened for the page: long lists show their first items.
Sweep cloudflare.com's selectors
GET /api/v2/dkim?domain=cloudflare.com{
"query": {
"domain": "cloudflare.com",
"selectors": []
},
"state": "keys",
"usableKeys": 5,
"selectors": [
{
"selector": "s1",
"name": "s1._domainkey.cloudflare.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "sendgrid",
"name": "Twilio SendGrid"
},
"cnameTarget": "s1.domainkey.u5338572.wl073.sendgrid.net",
"ttl": 1800,
"keys": [
{
"record": "k=rsa; t=s; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1m74n5R+xcz+ICbNBWRIlQeHI65Hjp67+P59XS…",
"version": null,
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": true,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 406,
"strings": 2
}
]
},
{
"selector": "m1",
"name": "m1._domainkey.cloudflare.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": null,
"cnameTarget": null,
"ttl": 300,
"keys": [
{
"record": "v=DKIM1;k=rsa;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApfI4XmZUuFjcKhAIW2f5dqqlYg4/7xSM953h…",
"version": "DKIM1",
"keyType": "rsa",
"bits": 2048,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 408,
"strings": 2
}
]
},
{
"selector": "k1",
"name": "k1._domainkey.cloudflare.com",
"status": "found",
"named": false,
"rcode": "NOERROR",
"provider": {
"id": "mailchimp",
"name": "Mailchimp (Marketing)"
},
"cnameTarget": "dkim.mcsv.net",
"ttl": 21600,
"keys": [
{
"record": "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbNrX2cY/GUKIFx2G/1I00ftdAj713WP9AQ1xir85i89sA2gu…",
"version": null,
"keyType": "rsa",
"bits": 1024,
"format": "spki",
"usable": true,
"revoked": false,
"standby": false,
"testing": false,
"strict": false,
"hashes": null,
"services": [
"*"
],
"notes": null,
"bytes": 226,
"strings": 1
}
]
},
// … 2 more items
],
"providers": [
{
"id": "sendgrid",
"name": "Twilio SendGrid",
"selectors": [
"s1"
]
},
{
"id": "mailchimp",
"name": "Mailchimp (Marketing)",
"selectors": [
"k1"
]
}
],
"wildcard": false,
"sweep": {
"tried": 140,
"answered": 140,
"failed": 0,
"skipped": 0,
"stoppedEarly": false
},
"missing": [],
"issues": [
{
"severity": "warning",
"code": "rsa_weak",
"message": "k1: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for 2048;…",
"selector": "k1"
},
{
"severity": "warning",
"code": "rsa_weak",
"message": "mandrill: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for…",
"selector": "mandrill"
},
{
"severity": "warning",
"code": "rsa_weak",
"message": "smtpapi: Under 2048 bits: rotate to 2048. Verifiers must still accept it, but RFC 8301 asks for …",
"selector": "smtpapi"
},
// … 2 more items
],
"tookMs": 569
}Shortened for the page: long lists show their first items.