Email Provider & MX Lookup - SPF, DMARC Checker (Bulk)
Pricing
$4.00 / 1,000 domain looked ups
Email Provider & MX Lookup - SPF, DMARC Checker (Bulk)
Bulk email provider lookup and MX lookup from public DNS. For a list of domains, URLs, emails or Google Maps rows it reports Google Workspace vs Microsoft 365, SPF and DMARC checker results, security gateways and lead signals for $0.004/domain.
Pricing
$4.00 / 1,000 domain looked ups
Rating
0.0
(0)
Developer
Luke Hunter
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
2 days ago
Last modified
Categories
Share
For sales teams, lead-gen agencies, cold-email operators, RevOps and security consultants who need to know how a list of companies handles email. Paste domains, website URLs, email addresses or a Google Maps / company dataset and get one row per domain: the email provider (Google Workspace, Microsoft 365, Zoho, Proton, Fastmail, Mimecast, Proofpoint and more), the full MX lookup, an SPF DMARC checker verdict, BIMI and MTA-STS, the SaaS tools the company has verified its domain with, and ready-made lead signals.
$0.004 per domain with a DNS answer. 1,000 domains = $4. NXDOMAIN and failed lookups are free.
It is a bulk email provider lookup built on public DNS over HTTPS only (Google Public DNS, with Cloudflare as fallback). It never opens an SMTP connection, never probes a mailbox and never checks whether an address exists: that would be invasive, so it is not in the product. No scraping, no login, no proxy, no API key.
What you get
| Field group | What it tells you |
|---|---|
mxRecords, acceptsEmail, hasNullMx | The MX lookup (priority and host), and whether the domain accepts email at all (MX, or the A/AAAA fallback; a null MX means "no email here"). |
emailProvider, emailProviders | Provider inferred from the MX hosts: Google Workspace, Microsoft 365, Zoho Mail, Proton Mail, Fastmail, Mimecast, Proofpoint, Barracuda, IONOS, OVH, GoDaddy, Yandex, Amazon SES / WorkMail and others, else Self-hosted / other. |
securityGateway, securityGatewayVendor, underlyingProvider | A filtering gateway (Mimecast, Proofpoint, Barracuda, Cisco, Trend Micro...) in front of the mailboxes, and the mailbox provider behind it when SPF reveals one. |
spfPresent, spfRecord, spfIncludes, spfProviders, spfAll | The SPF record, its includes, the known senders in it (SendGrid, Mailchimp, Mandrill, HubSpot, Salesforce, Amazon SES, Mailgun, Postmark, Brevo, Klaviyo, Zendesk, Freshdesk...) and the closing -all / ~all / ?all / +all. |
dmarcPresent, dmarcPolicy, dmarcPct, dmarcHasRua | DMARC policy (none, quarantine, reject), pct, and whether aggregate reports are requested. The report address itself is never output. |
bimiPresent, mtaStsPresent | Whether the domain publishes BIMI and MTA-STS records. |
verificationTxt | Vendors the company verified its domain with (Google, Microsoft, Atlassian, DocuSign, Stripe, Apple, Facebook...). Vendor names only, a tech-stack signal; token values are never output. |
leadSignals | usesGoogleWorkspace, usesMicrosoft365, sendsMarketingEmail, hasHelpdesk, emailSecurityMaturity (none, basic, strong). |
Input is forgiving: https://www.Acme.co.uk/contact?x=1, Jo@Acme.co.uk and acme.co.uk all become acme.co.uk; international names such as bücher.de are converted to punycode; duplicates are merged.
Quick start
{"domains": ["apify.com", "shopify.com", "stripe.com"],"maxItems": 3}
Recipes
Find which leads use Google Workspace vs Microsoft 365
{"domains": ["acme-example.com", "https://www.globex-example.org/about", "sales@initech-example.net"],"maxItems": 500}
Filter the dataset on leadSignals.usesGoogleWorkspace or leadSignals.usesMicrosoft365, or group by emailProvider. Companies behind a Mimecast or Proofpoint gateway still show their mailbox provider in underlyingProvider when their SPF record names it.
Qualify a Google Maps lead list by email provider
Run your Google Maps scraper first, then pass its default dataset ID:
{"datasetId": "<default dataset ID of your Google Maps run>","maxItems": 2000}
Or paste rows directly: each row's website (then domain, url, or email) field is used.
{"rows": [{ "title": "Acme Dental", "website": "https://www.acme-example.com/" },{ "title": "Globex Plumbing", "email": "info@globex-example.org" }]}
Rows with only a free-mail address (gmail.com, outlook.com...) are skipped, free, since that says nothing about the business. Keep rows where acceptsEmail is true and the provider matches the pitch; drop hasNullMx and nxdomain rows before you send anything.
Monitor DMARC policy and provider changes
{"domains": ["acme-example.com", "globex-example.org"],"onlyChangedSinceLastRun": true,"slackWebhookUrl": "https://hooks.slack.com/services/<T>/<B>/<token>"}
Save it as a Task and add a weekly Schedule. The first run records every domain as the baseline. Later runs deliver, charge and notify only domains that are new to the watch or whose email provider or DMARC policy changed (a company moving from Google Workspace to Microsoft 365, a p=none that became p=reject, a domain that dropped DMARC). Each changed row carries changeType: "changed" and changes such as {"field": "emailProvider", "from": "Google Workspace", "to": "Microsoft 365"}. A migration is a buying signal for email security, migration and backup vendors.
Alerts: Discord, Telegram, Slack, Teams, Google Chat, phone push or any app
Add one or more destinations in the Notifications (optional) section and each run sends the domains it delivered. It only reads public DNS and notifies you: it never emails anyone.
| Channel | Fill in | What you get |
|---|---|---|
| Discord | discordWebhookUrl | One card per domain, 10 per message |
| Telegram | telegramBotToken + telegramChatId | Up to 10 domains per message, one line each |
| Slack | slackWebhookUrl | Block Kit message, up to 10 domains per message |
| Mattermost, Rocket.Chat | slackCompatibleWebhookUrl | A Markdown list |
| Microsoft Teams | teamsWebhookUrl | Adaptive Card from a Teams Workflows webhook |
| Google Chat | googleChatWebhookUrl | Card in a space |
| ntfy (phone push, no account) | ntfyTopic (optional ntfyServer, ntfyToken) | A push per domain, up to 10, then one "...and N more" |
| Pushover (phone push) | pushoverUserKey + pushoverAppToken | A push per domain, up to 10, then one "...and N more" |
| Zapier, Make, n8n, Pipedream | webhookUrl | One JSON POST per 100 delivered rows with the full dataset rows |
A change message reads like Email setup changed: acme-example.com, with email provider: Google Workspace → Microsoft 365; DMARC: none → reject. Messages carry vendor names, policies and booleans only, never an SPF or TXT value. A failing channel never fails the run; notifications are free. maxNotifications (default 25, max 100) caps chat and phone messages per run.
Input
| Field | Default | What it does |
|---|---|---|
domains | [] | Domains, URLs or email addresses. |
rows | [] | Dataset-style objects; the first usable website, domain, url... field (else email) is used. |
datasetId | none | Read rows from an Apify dataset in your account (up to 50,000 rows), e.g. a Google Maps run. |
maxItems | 100 | Hard cap on domains looked up and charged, 1 to 10,000. |
onlyChangedSinceLastRun | false | Monitor mode: deliver only new or changed domains. |
stateStoreName | domain-email-provider-lookup-state | Named store holding the monitor memory. Use a different name per watch list. |
| notification fields | none | See the alerts table. |
At least one of domains, rows or datasetId is required; an input with nothing usable stops with a clear error.
Example output
{"domain": "acme-example.com","input": "https://www.acme-example.com/pricing","status": "ok","error": null,"warnings": [],"acceptsEmail": true,"hasNullMx": false,"mxRecords": [{ "priority": 1, "host": "aspmx.l.google.com" },{ "priority": 5, "host": "alt1.aspmx.l.google.com" }],"emailProvider": "Google Workspace","emailProviders": ["Google Workspace"],"securityGateway": false,"securityGatewayVendor": null,"underlyingProvider": null,"spfPresent": true,"spfRecord": "v=spf1 include:_spf.google.com include:sendgrid.net include:servers.mcsv.net ~all","spfIncludes": ["_spf.google.com", "sendgrid.net", "servers.mcsv.net"],"spfProviders": ["Google Workspace", "SendGrid", "Mailchimp"],"spfAll": "~all","spfMultipleRecords": false,"dmarcPresent": true,"dmarcPolicy": "quarantine","dmarcSubdomainPolicy": null,"dmarcPct": 100,"dmarcHasRua": true,"bimiPresent": false,"mtaStsPresent": false,"verificationTxt": ["Google", "Atlassian", "Facebook"],"leadSignals": {"usesGoogleWorkspace": true,"usesMicrosoft365": false,"sendsMarketingEmail": true,"hasHelpdesk": false,"emailSecurityMaturity": "strong"},"changeType": null,"changes": null,"checkedAt": "2026-10-10T12:00:00.000Z"}
This sample is illustrative (a reserved-style example domain). Every row has the same fields; anything not applicable is null or empty, never guessed.
Status values
status | Meaning | Charged |
|---|---|---|
ok | The required DNS lookups (MX, TXT, _dmarc) got an answer. This includes a domain that exists but has no email records at all (acceptsEmail: false). | Yes |
nxdomain | The domain does not exist. | No |
dns_error | Neither resolver gave a usable answer (outage, SERVFAIL, timeout). Safe to run again. | No |
invalid | The entry was not a domain, URL or email. | No |
skipped | A free-mail address such as gmail.com taken from an email field. | No |
How the provider and security ratings are decided
- Provider is read from the most preferred MX group (lowest priority number) by matching the host's domain suffix against known providers. A secondary MX does not override it; every provider seen is listed in
emailProviders. An unrecognised host isSelf-hosted / other. - Gateway: when Mimecast, Proofpoint, Barracuda or a similar filter is the preferred MX it is reported as the provider with
securityGateway: true.underlyingProvidercomes from the SPF record when it names Google Workspace, Microsoft 365 or Zoho;usesGoogleWorkspaceandusesMicrosoft365honour it. emailSecurityMaturity:none= no SPF and no DMARC;strong= SPF ending-allor~alland DMARCquarantineorrejectatpct100; everything else isbasic.sendsMarketingEmailis true when SPF names a marketing platform (Mailchimp, HubSpot, Klaviyo, Brevo, Constant Contact, Marketo, ActiveCampaign...). Transactional senders (SendGrid, Mailgun, Postmark, SES) are listed inspfProvidersbut do not count.hasHelpdeskis true for Zendesk, Freshdesk, Help Scout, Intercom or Atlassian in SPF.
Use with AI agents (MCP)
This Actor works as a tool for Claude, ChatGPT, Cursor and other MCP clients through Apify's MCP server. Only a list of domains is needed, and each input property description is short and carries an example, so agents fill it in correctly.
Claude Desktop (claude_desktop_config.json), with your own token from Apify Console > Settings > API & Integrations:
{"mcpServers": {"apify-email-provider-lookup": {"command": "npx","args": ["-y", "mcp-remote","https://mcp.apify.com?tools=lukehunter/email-provider-mx-lookup","--header", "Authorization: Bearer ${APIFY_TOKEN}"],"env": { "APIFY_TOKEN": "<YOUR_APIFY_TOKEN>" }}}}
Clients that support OAuth (Claude.ai, VS Code) can connect with just the URL https://mcp.apify.com?tools=lukehunter/email-provider-mx-lookup and sign in to Apify. Never paste a real token into a shared file or chat.
Example. You ask: "Which of these ten prospects run on Microsoft 365, and do any have no DMARC?" The agent calls the tool lukehunter--email-provider-mx-lookup with:
{"domains": ["acme-example.com", "globex-example.org"],"maxItems": 10}
It is charged $0.004 per domain with a DNS answer, capped by maxItems.
Pricing
Pay-per-event: $0.004 per domain whose DNS lookups succeeded (status: ok). NXDOMAIN, DNS errors, unusable input and free-mail skips are delivered in the dataset for transparency and are never charged. In monitor mode only new or changed domains are delivered and charged; unchanged domains cost nothing.
| Domains delivered | Cost |
|---|---|
| 3 | $0.012 |
| 100 (default cap) | $0.40 |
| 1,000 | $4.00 |
| 10,000 (maximum) | $40.00 |
maxItems (hard maximum 10,000) and your Apify per-run spending limit both stop delivery before the cap is passed. Price changes follow Apify's notice rules; the Pricing tab always shows the rate you are charged.
Limitations
- Public DNS only. Results reflect the records the domain publishes today, through Google Public DNS (Cloudflare if Google fails). The Actor never connects to a mail server, so it cannot say whether a mailbox exists, whether mail would be accepted or delivered, or what a company's spam filter does.
- The provider is an inference from MX hostnames. A company can host mail with a vendor under its own MX names (shown as
Self-hosted / other), or forward mail elsewhere. TreatemailProvideras a segmentation signal, not an audit. - Subdomains are looked up as given.
mail.acme.comis checked asmail.acme.com; there is no public-suffix reduction to a parent domain. Pass the company's main domain. - SPF is read, not evaluated. Includes are not expanded recursively, so
spfProviderscovers what the record names directly (plusredirect=), not senders hidden two levels down.spfIncludesandspfRecordshow exactly what was published. - Malformed DNS is reported, not hidden. Several SPF or DMARC records (invalid by RFC), bad MX data and truncated resolver answers add entries to
warnings. Several DMARC records count as no DMARC, as receivers treat them. - Verification tokens are never output. Only the vendor names for TXT records like
google-site-verification=are reported. - Politeness. About 10 queries in flight at once, with retry and backoff on 429 and 5xx. A run stops after 40 minutes and says how many domains were not looked up.
- Not affiliated with Google, Microsoft or any provider named here. Use results in line with applicable law (for outreach, GDPR, PECR, CAN-SPAM); this Actor does not send email.
Use it from your code, Make, Zapier or n8n
Built for automated pipelines: small runs, stable field names, one row per item, and you pay only for rows actually delivered.
One API call that runs the Actor and returns the data (replace $APIFY_TOKEN with your token from Apify Console → Settings → Integrations):
curl -s -X POST "https://api.apify.com/v2/acts/lukehunter~email-provider-mx-lookup/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"domains": ["apify.com", "shopify.com", "stripe.com"], "maxItems": 3}'
JavaScript (npm i apify-client):
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('lukehunter~email-provider-mx-lookup').call({"domains": ["apify.com","shopify.com","stripe.com"],"maxItems": 3});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python (pip install apify-client):
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('lukehunter~email-provider-mx-lookup').call(run_input={"domains": ["apify.com", "shopify.com", "stripe.com"], "maxItems": 3})items = client.dataset(run['defaultDatasetId']).list_items().items
Schedules, webhooks and no-code tools: save your input as a Task, add a Schedule (e.g. hourly or daily), and attach a webhook or one of the Integrations tab's connectors (Make, Zapier, n8n, Google Sheets, Slack) to push each run's results into your own system.
Only new items each run: set "onlyChangedSinceLastRun": true on a scheduled Task and every run after the first delivers, and charges for, only items it hasn't delivered before for that same input. That makes it a ready-made change feed.
Feedback: an honest rating on the Store page, good or bad, helps others decide if this Actor fits their needs. Missing a field or found a problem? Open an issue on the Actor page.
FAQ
Do you connect to the mail server or check if an address exists? No, never. Only public DNS records are read.
Why do I get a row for a domain I wasn't charged for? Rows with nxdomain, dns_error, invalid or skipped are free. Filter on status: ok to see only charged rows.
What does Self-hosted / other mean? The MX hosts are not one of the known providers: a company's own server, a regional host, or a provider not in the list.
Why is a gateway like Mimecast the provider? It is the preferred MX, so it is what a sender reaches first. Check underlyingProvider and the leadSignals for the mailbox vendor behind it.
Can I use my Google Maps results? Yes: pass the run's dataset ID as datasetId, or paste rows with a website field.
How do I get alerts when a provider changes? Set onlyChangedSinceLastRun, add a destination and a weekly Schedule. See the DMARC monitoring recipe.
Related Actors
Other data tools from the same developer, built to the same standard: official or public sources, hard cost caps, and honest documentation of limits.
- French Company Leads: French companies (entreprises) from the official Sirene-based API, filtered by NAF code, department, headcount and creation date, with SIREN/SIRET, officers and new-company alerts.
- Poland KRS Company Lookup: Polish companies from the official KRS API by KRS number: NIP, REGON, address, share capital, PKD and the board as published, with optional VAT status.
- Website Contact Scraper: emails, phone numbers and social profile links from any list of company domains, with the page each came from and a changed-contacts-only mode for scheduled runs.
- Impressum Scraper: legal entity data from the imprint of any company website in Germany, Austria and Switzerland: legal name and form, managing directors, HRB/HRA or FN register, VAT id and address, with a changed-data-only mode for scheduled runs.
- Website Tech Stack Detector: the technologies a website runs (CMS, ecommerce platform, analytics, ad pixels, chat, payments, CDN, frameworks) from its home page, with the evidence for each match and a changed-technologies-only mode for scheduled runs.
- Google Maps Email Extractor & Lead Enricher: emails, phones, social links, named people and the tech stack of every business in your Google Maps Scraper results, one enriched row per business, with filters such as only Shopify stores with an email.
- Federal Register Rule Effective-Date Radar: final federal rules about to take effect, with citations, dockets and urgency.
- UK Tenders Monitor: new UK public-sector tenders from Contracts Finder and Find a Tender, filtered by CPV code, value, region and buyer, with Slack, Discord and Telegram alerts.