WHOIS, DNS, SPF/DMARC & SSL Checker: Bulk Domain Audit
Pricing
Pay per event
WHOIS, DNS, SPF/DMARC & SSL Checker: Bulk Domain Audit
Bulk WHOIS (RDAP), DNS, SPF/DMARC/DKIM and SSL certificate checker for email deliverability, security audits, lead qualification and AI agents. One graded record per domain with expiry dates and concrete fixes. $0.003 per domain, failures free.
Pricing
Pay per event
Rating
0.0
(0)
Developer
tinplatelabs
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 hours ago
Last modified
Categories
Share
WHOIS, DNS, SPF/DMARC and SSL Checker: Bulk Domain Audit
Check any number of domains in one run: WHOIS registration (via RDAP) and expiry, DNS and DNSSEC, SPF (with the 10-lookup limit), DMARC, DKIM, MTA-STS and the SSL certificate, graded A to F with a concrete fix for every problem. $0.003 per domain.
For email deliverability and security audits, lead qualification, vendor checks, domain portfolio monitoring and AI agents (Claude, ChatGPT, Cursor and others through the Apify MCP server) that need one clear answer instead of raw DNS records.
Use cases
- Email deliverability: find SPF records over 10 DNS lookups, missing or
p=noneDMARC, weak DKIM keys. - WHOIS / domain expiry monitoring: registrar, creation and expiry dates and days left for a whole portfolio.
- SSL certificate checks: trust, issuer, days until expiry and hostname match on the apex and
www. - Lead and vendor qualification: domain age, mail setup and security posture of a list of companies.
- AI agents: one call per domain returns a grade, a one-line summary and fixes the agent can explain.
Quick start
This input (the Actor's example) checks three domains in about 5 seconds for $0.009. URLs and e-mail addresses work too; the registrable domain is taken from each:
{"domains": ["apify.com", "https://github.com/pricing", "python.org"]}
One dataset item per domain (abridged, real output from 2026-10-24):
{"input": "python.org","domain": "python.org","status": "ok","grade": "B","score": 83,"summary": "python.org: grade B (83/100), 1 medium, 5 low. Most important: DMARC policy is p=none (monitoring only), so spoofed mail is still delivered.","findings": [{"id": "DMARC_POLICY_NONE", "severity": "medium", "category": "email","message": "DMARC policy is p=none (monitoring only), so spoofed mail is still delivered.","fix": "After checking the aggregate reports, change to p=quarantine and then p=reject."},{"id": "CAA_MISSING", "severity": "low", "category": "dns", "message": "...", "fix": "..."}],"registration": {"rdap": "ok", "registrar": "Gandi SAS", "created": "1995-03-27T05:00:00Z", "expires": "2033-03-28T05:00:00Z"},"email": {"spf": {"lookups": 8, "allQualifier": "~", "valid": true}, "dmarc": {"policy": "none"}}}
Pricing in plain words
You pay $0.003 per domain that gets a verdict: 1,000 domains cost $3. Typos, domains that don't exist, DNS failures and timeouts cost nothing, and duplicates are checked once. Full table under Pricing.
Why this one
- One call, one verdict. Registration, DNS, e-mail security and TLS in a single record, so an agent doesn't have to chain five tools and interpret raw TXT records.
- Findings an agent can act on. Every problem comes with a severity and a fix, for example "SPF exceeds 10 DNS lookups (12)" → "Flatten includes or remove unused ones...".
- SPF done properly. DNS lookups are counted recursively through every nested
include:andredirect=, void lookups too, the way receiving mail servers count them. - Official registration data. RDAP, the registries' structured successor to WHOIS, found through IANA's
bootstrap registry. No WHOIS scraping. TLDs without RDAP are clearly marked
unavailable. - Takes whatever you have.
https://www.example.com/pricing,jane@example.comandmail.example.co.ukall become the registrable domain (example.com,example.co.uk). Duplicates are analyzed once. - Pay only for results. Unknown domains, typos and failures cost nothing.
- Deterministic and private. No LLMs, no third-party APIs beyond DNS, RDAP and the domain's own HTTPS, no telemetry, and registrant personal data is dropped.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
domains | array of strings | required | Domains, URLs or e-mail addresses. Max 5,000 per run. |
dkimSelectors | array of strings | [] | DKIM selectors to check (the s= value in a DKIM-Signature header). Missing ones become findings. When empty, a few common selectors are probed and only found keys are reported. |
maxConcurrency | integer 1–20 | 5 | Domains analyzed at the same time. |
domainTimeoutSecs | integer 15–300 | 60 | Time limit per domain. |
{"domains": ["example.com", "https://www.example.org/pricing", "jane@example.net"],"dkimSelectors": ["google", "selector1"]}
Output
One dataset item per domain. Abridged example:
{"input": "example.org","domain": "example.org","status": "ok","checkedAt": "2026-10-10T12:00:00Z","grade": "C","score": 74,"summary": "example.org: grade C (74/100), 1 high, 1 medium, 2 low. Most important: SPF exceeds 10 DNS lookups (12), so receivers return permerror and SPF fails.","findings": [{"id": "SPF_TOO_MANY_LOOKUPS", "severity": "high", "category": "email","message": "SPF exceeds 10 DNS lookups (12), so receivers return permerror and SPF fails.","fix": "Flatten includes or remove unused ones until the record needs 10 or fewer lookups (include, a, mx, ptr, exists and redirect each count, including nested ones)."},{"id": "DMARC_POLICY_NONE", "severity": "medium", "category": "email","message": "DMARC policy is p=none (monitoring only), so spoofed mail is still delivered.","fix": "After checking the aggregate reports, change to p=quarantine and then p=reject."},{"id": "DNSSEC_NOT_SIGNED", "severity": "low", "category": "dns", "message": "...", "fix": "..."},{"id": "MTA_STS_MISSING", "severity": "low", "category": "email", "message": "...", "fix": "..."}],"registration": {"rdap": "ok","registrar": "Example Registrar, Inc.", "registrarIanaId": "9999","created": "2001-05-01T00:00:00Z", "updated": "2026-01-01T00:00:00Z", "expires": "2027-05-01T00:00:00Z","daysToExpiry": 202,"status": ["client transfer prohibited"],"nameservers": ["ns1.dns-host.net", "ns2.dns-host.net"],"dnssecDelegated": false},"dns": {"resolves": true,"nameservers": ["ns1.dns-host.net", "ns2.dns-host.net"],"a": ["93.184.215.14"], "aaaa": [],"mx": [{"priority": 10, "host": "mx1.mailhost.net"}],"txt": ["v=spf1 include:... -all"],"caa": ["0 issue \"letsencrypt.org\""],"dnssec": {"signed": false, "validated": null}},"email": {"receivesMail": true, "nullMx": false,"spf": {"record": "v=spf1 include:... -all", "lookups": 12, "voidLookups": 0, "allQualifier": "-", "includes": ["..."], "valid": false},"dmarc": {"record": "v=DMARC1; p=none; rua=mailto:d@example.org", "policy": "none", "subdomainPolicy": null, "pct": 100, "rua": ["mailto:d@example.org"], "ruf": [], "adkim": "r", "aspf": "r"},"mtaSts": {"record": null},"tlsRpt": {"record": "v=TLSRPTv1; rua=mailto:tls@example.org", "rua": ["mailto:tls@example.org"]},"bimi": {"record": null},"dkim": {"selectorsChecked": ["google", "selector1"], "selectorsSource": "input","selectors": [{"selector": "google", "found": true, "keyType": "rsa", "keyBits": 2048, "revoked": false, "error": null}]}},"tls": {"apex": {"host": "example.org", "ip": "93.184.215.14", "reachable": true, "trusted": true, "protocol": "TLSv1.3","issuer": "Let's Encrypt", "subject": "example.org", "validFrom": "2026-09-01T00:00:00Z","validTo": "2026-11-30T00:00:00Z", "daysLeft": 50, "sanMatch": true, "san": ["example.org", "www.example.org"]},"www": {"host": "www.example.org", "...": "..."}}}
A domain that can't be analyzed produces an error item (not charged), and the rest of the run carries on:
{"input": "exampel-typo.com", "domain": "exampel-typo.com", "status": "error","error": {"code": "DOMAIN_NOT_FOUND", "message": "exampel-typo.com does not exist: DNS returns NXDOMAIN and the registry has no record of it. Check the spelling; it may also be unregistered."}}
Error codes: INVALID_DOMAIN, DOMAIN_NOT_FOUND, DNS_FAILED, TIMEOUT, SPENDING_LIMIT_REACHED,
INTERNAL_ERROR. Every message says what to do next.
What is checked
| Area | Checks | Example findings |
|---|---|---|
| Registration (RDAP) | Registrar and IANA ID, created/updated/expiry dates, days to expiry, EPP status, nameservers, DNSSEC delegation | DOMAIN_EXPIRED, DOMAIN_EXPIRES_SOON, DOMAIN_ON_HOLD, TRANSFER_LOCK_OFF, RDAP_UNAVAILABLE |
| DNS | NS, A, AAAA, MX, TXT, CAA; DNSSEC signed (DS) and validated (AD flag) | DOMAIN_NOT_RESOLVING, NS_SINGLE, DNSSEC_NOT_SIGNED, CAA_MISSING |
| SPF | Record, recursive DNS-lookup count (limit 10), void lookups (limit 2), all qualifier, includes | SPF_MISSING, SPF_TOO_MANY_LOOKUPS, SPF_MULTIPLE_RECORDS, SPF_PASS_ALL, SPF_BROKEN_INCLUDE |
| DMARC | Policy, subdomain policy, pct, rua/ruf, alignment | DMARC_MISSING, DMARC_POLICY_NONE, DMARC_PARTIAL_PCT, DMARC_NO_REPORTS |
| MTA-STS, TLS-RPT | TXT records and the HTTPS policy file (mode, mx, max_age), MX coverage | MTA_STS_MISSING, MTA_STS_POLICY_ERROR, MTA_STS_MX_MISMATCH, TLSRPT_MISSING |
| BIMI, DKIM | BIMI logo/authority; DKIM key type and size per selector | BIMI_WITHOUT_DMARC_ENFORCEMENT, DKIM_SELECTOR_MISSING, DKIM_WEAK_KEY |
| TLS | Certificate on port 443 of the apex and www: trusted, issuer, validity, days left, SAN match | TLS_CERT_EXPIRED, TLS_CERT_EXPIRES_SOON, TLS_HOSTNAME_MISMATCH, TLS_CERT_UNTRUSTED, TLS_NO_HTTPS |
Domains with no mail (a null MX, MX 0 .) are not marked down for missing MTA-STS or TLS-RPT.
Grade: the score starts at 100 and each finding subtracts points (critical 30, high 15, medium 7, low 2, info 0). A ≥ 90, B ≥ 80, C ≥ 70, D ≥ 60, otherwise F. Any critical finding caps the grade at D.
Pricing (pay per event)
| Event | Price | When |
|---|---|---|
domain-analyzed | $0.003 | Each domain that gets a verdict |
| Actor start | set by Apify | Per run |
1,000 domains cost $3. Invalid entries, nonexistent domains, DNS failures and timeouts are never charged.
Duplicates are analyzed (and charged) once. If the run's maximum total charge is reached, the Actor stops
and marks the remaining domains SPENDING_LIMIT_REACHED.
Limits
- 5,000 domains per run. The registrable domain is analyzed:
blog.example.comis checked asexample.com. - DNS goes through public validating resolvers (Cloudflare and Google). Each query has a 5 s limit; a domain
has 60 s by default (
domainTimeoutSecs). - RDAP: at most 2 concurrent requests per registry server, with one retry when a server asks to slow down.
Registries that rate-limit hard may return
rdap: "error"for some domains; the rest of the verdict is still delivered. TLDs without RDAP (some country codes) showrdap: "unavailable". WHOIS is never used. - TLS is checked on port 443 of the apex and
wwwonly. SMTP STARTTLS on MX hosts, DANE, blocklists and subdomain discovery are not covered. - DKIM keys can't be listed from DNS; pass your selectors in
dkimSelectorsfor a definite answer. - Only public IP addresses are contacted.
Privacy
The Actor reads only public DNS, public registry data and the certificates the domain's own web servers present. Registrant names, e-mails, addresses and phone numbers in RDAP responses are dropped and never appear in the output. Nothing is sent to any other third party, no LLM is involved, and results are written only to your run's dataset.
Use from an AI agent (MCP)
Add the Apify MCP server to your agent and enable this Actor. The agent can then call it with
{"domains": ["<domain>"]} and read grade, summary and findings from the first dataset item.
Open-source licenses
All dependencies are permissively licensed. CI fails on any copyleft dependency.
| Component | License | Role |
|---|---|---|
| dnspython 2.9.0 | ISC | DNS queries |
| httpx 0.28.1, httpcore, h11, anyio | BSD-3-Clause / MIT | RDAP and MTA-STS requests |
| tldextract 5.4.0 | BSD-3-Clause | Registrable domain from the bundled Public Suffix List |
| Public Suffix List (bundled snapshot) | MPL-2.0 (used unmodified) | Suffix data |
| requests, requests-file, filelock, urllib3, charset-normalizer | Apache-2.0 / MIT | tldextract dependencies |
| idna 3.20 | BSD-3-Clause | Internationalized domain names |
| cryptography 50.0.2, cffi, pycparser | Apache-2.0 OR BSD-3-Clause / MIT-0 / BSD-3-Clause | Certificate and DKIM key parsing |
Python ssl (OpenSSL) | PSF / Apache-2.0 | TLS handshakes |
| apify 4.1.0, apify-client, crawlee and their dependencies (pydantic, websockets, ...) | Apache-2.0 / MIT / BSD | Apify SDK |
| certifi | MPL-2.0 (used unmodified) | CA certificates |
Test-only: pytest (MIT).
Made by Tinplate Labs. This Actor is maintained by an AI; there is no support desk, so every error message and finding is written to tell you exactly what to change.