Tech Stack, Email Provider & SaaS Detector by Domain
Pricing
from $2.00 / 1,000 domain analyzed (dns)s
Tech Stack, Email Provider & SaaS Detector by Domain
Use when you have company domains and need their email provider, SaaS tools and tech stack (CMS, analytics, chat, payments). Reads DNS plus raw home page HTML and public scripts, no browser; robots.txt respected; evidence per finding. $0.002/domain, $0.005 with page.
Pricing
from $2.00 / 1,000 domain analyzed (dns)s
Rating
0.0
(0)
Developer
Djam
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Give it company domains. For each one it returns, with the evidence for every finding:
- the email provider (Google Workspace, Microsoft 365, Zoho Mail, OVHcloud Mail...), read from MX records;
- the SaaS tools the domain declares in DNS: services allowed to send its e-mail (SPF), verification tokens (Atlassian, HubSpot, DocuSign, OpenAI...), CNAME records of a few well-known subdomains;
- the website technologies found in the raw HTML of the home page, in up to 3 scripts served by the site itself and in its public Google Tag Manager container: CMS (WordPress, Shopify, Webflow...), analytics and tag managers, chat widgets (Zendesk, Intercom...), payment tools (Stripe, PayPal...), consent tools, frameworks, web server. Each one says where it was found (
source); - the DNS provider, the hosting platform and the CDN when DNS reveals them;
- the SPF and DMARC policies.
One action, one row per domain, structured JSON. DNS first: the e-mail provider, SPF/DMARC and SaaS proofs that page scanners do not give. It reads public DNS records and the public home page (after checking robots.txt), with the User-Agent LakadevStackBot/1.0 (+https://apify.com/lakadev/website-tech-stack-detector). No browser, no JavaScript executed, no API key, no login, no proxy.
When to use it
- Qualify B2B prospects. From a list of domains, find who runs WordPress or Shopify, loads HubSpot or Intercom, or sends mail through Salesforce or SendGrid, then keep the ones that fit your offer. Stripe is rarely visible on a home page (it loads at checkout), so a Stripe finding mostly comes from DNS and means an account, not live payments.
- Find the email provider of a domain. Google Workspace, Microsoft 365, Zoho, OVHcloud, Proton, a security gateway such as Mimecast or Proofpoint: the answer comes from MX records, with the MX host as proof.
- Spot the customers of a SaaS competitor. Domains that declare Zendesk, HubSpot, Atlassian or Salesforce in their DNS, or whose home page names their chat widget, are likely users or past users. A DNS verification token proves the domain has an account with the service, not that it uses it today.
- Audit e-mail posture at scale: SPF final mechanism (
~all,-all), DMARC policy (none,quarantine,reject). - Feed an AI agent that needs a structured answer about a company's stack instead of reading raw HTML.
It is not a replacement for a full technology database: it knows 54 website technologies and 34 DNS services (lists below).
How to read the results: an absence proves nothing. "No chat widget found" means none appears in the HTML, the scripts read or the GTM container, not that the site has none (tools loaded by the site's own JavaScript, or after consent, are invisible). If page.status is not fetched, an empty technologies means "not read", not "none".
Price
Pay per event, no platform usage billed on top:
| Event | Price | When |
|---|---|---|
| Domain analyzed (DNS) | $0.002 | the domain exists and its DNS was analyzed (status ok) |
| Home page analyzed | $0.003 more | the home page was fetched and analyzed (page.status = "fetched"); covers its scripts and GTM container |
| Actor start | $0.00005 | once per run (Apify's standard start event) |
Besides the tiny start fee, a full row costs $0.005; a DNS-only row (fetchHomepage: false) costs $0.002. Nothing is charged for invalid items, unknown domains (not_found), lookup errors, or for the page when it is robots_disallowed, blocked, http_error or unreachable. If your maximum cost per run is reached, the run stops cleanly at the first row it can no longer pay for.
Input
| Field | Type | Default | Description |
|---|---|---|---|
domains | array of strings (1 to 1,000) | required | Domains (apify.com), URLs (https://www.shopify.com/fr) or e-mail addresses (name@wordpress.org). The domain is extracted, www. is removed, duplicates are merged. |
includeSubdomainWww | boolean | true | Also look up www.<domain> in DNS to detect hosting and CDN. |
fetchHomepage | boolean | true | Read the home page and its scripts (robots.txt first) to detect website technologies. false: no HTTP request to the site, DNS only. |
{"domains": ["apify.com", "https://www.shopify.com/fr", "someone@wordpress.org", "zendesk.com"],"includeSubdomainWww": true,"fetchHomepage": true}
Domains are normalized with IDNA 2008 (UTS 46): Bücher.de becomes xn--bcher-kva.de. Subdomains are analyzed as given.
Output
One row per domain, in input order (after merging duplicates). Real run of 2026-10-01 on webflow.com, shortened (saas had 14 items and keeps 5). Three technologies come from the Google Tag Manager container (source: "gtm"), including the chat tool Qualified. Real values change over time.
{"input": "webflow.com","domain": "webflow.com","status": "ok","emailProvider": {"name": "Google Workspace","evidence": "MX aspmx.l.google.com"},"mx": ["aspmx.l.google.com","alt1.aspmx.l.google.com","alt2.aspmx.l.google.com","aspmx2.googlemail.com","aspmx3.googlemail.com"],"spf": {"record": "v=spf1 include:_spf.google.com include:spf.mailjet.com include:mail.zendesk.com include:_spf.salesforce.com include:mailgun.org ?all","includes": ["_spf.google.com","spf.mailjet.com","mail.zendesk.com","_spf.salesforce.com","mailgun.org"],"all": "?all"},"dmarc": {"policy": "reject","record": "v=DMARC1; p=reject; sp=none; rua=mailto:***@inbox.ondmarc.com,mailto:***@webflow.com,mailto:***@dmarc.mailgun.org,mailto:***@inbox.ondmarc.com; ruf=mailto:***@inbox.ondmarc.com,mailto:***@dmarc.mailgun.org,mailto:***@inbox.ondmarc.com; aspf=r; pct=100; fo=1; ri=3600"},"saas": [{"name": "Google Workspace","category": "email","evidence": "MX aspmx.l.google.com"},{"name": "Salesforce","category": "crm","evidence": "SPF include:_spf.salesforce.com"},{"name": "SendGrid","category": "email-sending","evidence": "CNAME s1._domainkey.webflow.com s1.domainkey.u2859722.wl223.sendgrid.net"},{"name": "Stripe","category": "payments","evidence": "TXT stripe-verification=081188df8f2b18461958…"},{"name": "Zendesk","category": "support","evidence": "SPF include:mail.zendesk.com"}],"dnsProvider": {"name": "Amazon Route 53","evidence": "NS ns-1078.awsdns-06.org"},"hosting": null,"cdn": null,"nameservers": ["ns-1078.awsdns-06.org","ns-1722.awsdns-23.co.uk","ns-344.awsdns-43.com","ns-958.awsdns-55.net"],"page": {"status": "fetched","url": "https://webflow.com/","httpStatus": 200},"technologies": [{"name": "Cloudflare","category": "cdn","version": null,"source": "page","evidence": "HEADER cf-ray: a43baf32dddb1fd3-IAD"},{"name": "Google Tag Manager","category": "tag-manager","version": null,"source": "page","evidence": "HTML https://www.googletagmanager.com/ns.html?id=GTM-55XXQM3F\" he"},{"name": "jQuery","category": "js-library","version": "3.5.1","source": "page","evidence": "SCRIPT https://d3e54v103j8qbb.cloudfront.net/js/jquery-3.5.1.min.dc5e7f18c8.js?s…"},{"name": "LinkedIn Insight Tag","category": "advertising","version": null,"source": "gtm","evidence": "GTM GTM-55XXQM3F snap.licdn.com"},{"name": "Meta Pixel","category": "advertising","version": null,"source": "gtm","evidence": "GTM GTM-55XXQM3F connect.facebook.net/"},{"name": "Qualified","category": "chat","version": null,"source": "gtm","evidence": "GTM GTM-55XXQM3F js.qualified.com"},{"name": "Webflow","category": "cms","version": null,"source": "page","evidence": "META generator Webflow"}],"failedLookups": [],"checkedAt": "2026-10-01T13:06:22Z","error": null}
How to read it: emailProvider is Google Workspace because the MX hosts are Google's. The saas list shows Stripe and Zendesk from DNS (tokens, SPF): accounts, not proof of live use. Qualified is listed with source: "gtm": it is configured in the site's tag manager container, which does not guarantee it is active on the home page.
Fields
input: the item as given. E-mail addresses are masked (***@x.com).domain: normalized domain;nullwhen the status isinvalid.status:ok,not_found(the domain does not exist or has no records),invalid(not a domain),error(lookups failed and nothing was found). Onlyokis billed.emailProvider:{name, evidence}.nullwith an emptymxmeans the domain itself receives no mail (the company may use another domain:notion.sohas no MX, its mail is onnotion.com).Unknownmeans the MX host is not in our list: readmxandsaas, since a mail gateway such as Proofpoint or Mimecast can sit in front of Google or Microsoft.None (null MX)means the domain declares it does not receive e-mail (RFC 7505).mx: MX hosts sorted by priority, then name.spf:record,includes(theinclude:targets of that record, no recursion),all(finalallmechanism);nullwithout SPF.dmarc:policy(value ofp=) and therecord;nullwithout DMARC.saas: services the domain declares in DNS:name,categoryandevidence("<TYPE> <value>").dnsProvider,hosting,cdn:{name, evidence}ornull.nameservers: NS targets, sorted.failedLookups: lookups that failed ("MX x.com"). A row with statusokcan be partial:mx = []with noMX x.comhere means "no MX"; with it, "MX unknown".page:statusisfetched(2xx page received and analyzed),robots_disallowed(robots.txt forbids the page, or answers 5xx),blocked(401, 403, 429, or an anti-bot challenge page: nothing is bypassed),http_error(other HTTP failure, too many redirects),unreachable(no usable answer, timeout, non-public address) ornot_fetched.urlis the last page URL requested,httpStatusits response code.technologies: empty unlesspage.statusisfetched. Each item:name,category,version(only for generators, jQuery file names andserverheaders, elsenull),source(page: the page HTML and headers;script: one of the site's own scripts;gtm: a Google Tag Manager container) andevidence(page:HEADER name: value,COOKIE name,META generator ...,SCRIPT url,LINK urlorHTML excerpt;script:SCRIPT <script url> <pattern>;gtm:GTM <container id> <pattern>).gtmmeans "configured in the site's GTM container", not necessarily active on the home page. If several sources find the same technology,pagewins overscript, thengtm. Thestatusof the row stays the DNS status.checkedAt: UTC time of the analysis.error: cause in English when status is notok.
No e-mail address appears in the output: anything that looks like one is rendered ***@domain.
What it detects
Generated from the signature files shipped with the Actor.
DNS services (34), by category (saas field and emailProvider):
- email: Fastmail, Google Workspace, iCloud Mail, Microsoft 365, OVHcloud Mail, Proton Mail, Zoho Mail
- security: GlobalSign, Jamf, Mimecast, Proofpoint
- analytics: Google Search Console, Mixpanel
- dev: Atlassian, OpenAI
- support: Atlassian Statuspage, Zendesk
- payments: Stripe
- marketing: HubSpot, Mailchimp, Marketo
- social: Meta
- other: Apple
- productivity: Adobe, DocuSign, Zapier, Zoom
- crm: Salesforce
- email-sending: Amazon SES, Brevo, Mailchimp Transactional, Mailgun, Postmark, SendGrid
DNS providers, hosting and CDN (from NS, CNAME and IP ranges):
- dns_providers: Cloudflare, Amazon Route 53, Google Cloud DNS, Azure DNS, OVHcloud, GoDaddy, Gandi, Namecheap, NS1, Akamai
- hosting: Vercel, Netlify, GitHub Pages, Shopify, Squarespace, Wix, Heroku, WP Engine
- cdn: Cloudflare, Fastly, Amazon CloudFront, Akamai
Website technologies (54), by category (technologies field; looked for in the HTML, the scripts and the GTM container):
- cms: Drupal, Ghost, Joomla, Squarespace, Webflow, Wix, WordPress
- ecommerce: BigCommerce, Magento, PrestaShop, Shopify, WooCommerce
- analytics: Google Analytics, Hotjar, Matomo, Microsoft Clarity, Plausible, Segment
- tag-manager: Google Tag Manager
- advertising: LinkedIn Insight Tag, Meta Pixel
- chat: Crisp, Drift, Gladly, Gorgias, HubSpot Chat, Intercom, LiveChat, Qualified, Tawk.to, Tidio, Zendesk
- marketing: HubSpot, Klaviyo
- payments: Adyen, Klarna, PayPal, Shop Pay, Stripe
- consent: Axeptio, Cookiebot, Didomi, OneTrust
- framework: Gatsby, Next.js, Nuxt
- js-library: jQuery, React, Vue.js
- cdn: Cloudflare
- hosting: Netlify, Vercel
- server: Apache HTTP Server, Nginx
Anything not in these lists is not reported by name: an unrecognized mail provider is Unknown, an unrecognized host or CDN is null.
Calling it from an AI agent
Through the Apify MCP server (https://mcp.apify.com): the agent finds the Actor with search-actors (for example "find the email provider and tech stack of a list of company domains"), reads its input schema and prices with fetch-actor-details, then runs it with call-actor:
{"actor": "lakadev/website-tech-stack-detector","input": {"domains": ["apify.com", "gitlab.com"], "fetchHomepage": true}}
call-actor waits at most about 45 seconds. A local run of 20 domains took about 8 seconds, but keep batches small for a direct call; for longer lists start the run asynchronously and read the dataset afterwards. Running an Actor requires an Apify token (or an x402 or Skyfire payment where available).
Through the API, synchronously:
curl -X POST "https://api.apify.com/v2/acts/lakadev~website-tech-stack-detector/run-sync-get-dataset-items" \-H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \-d '{"domains": ["apify.com", "gitlab.com"]}'
Limits
- No JavaScript is executed. Besides the raw home page, the Actor reads as text the first 3 scripts hosted on the site's own domain (or its subdomains) and up to 2 public Google Tag Manager containers (
googletagmanager.com/gtm.js?id=GTM-...) found in the page, and looks for the same patterns in them.robots.txtis checked for each origin read. A tool loaded by code that this does not reveal stays invisible: an absence proves nothing. A DNS token proves an account, not a current use (Stripe, for instance, rarely shows on a home page). - One page request per domain (plus redirects,
robots.txt, up to 3 site scripts and 2 GTM containers). A failing script is ignored. A page larger than 2 MB is analyzed on its first 2 MB, staysfetchedand is billed. Cookies are never sent back. - Pages behind anti-bot protection are reported as
blocked; nothing is bypassed (no proxy, no captcha solving). Measured on 100 well-known sites from the Apify platform (October 2026): 67 pages read, 22blocked, 8robots_disallowed, 3unreachable. The DNS part works for every existing domain. robots.txtis respected: a page it forbids isrobots_disallowed, and not billed.- No recursion into SPF
include:records. - No climb to the parent domain:
blog.x.comis analyzed as is, without inherited NS or DMARC. - No public suffix list:
co.ukis analyzed as a domain. - Detection relies on built-in signature lists (34 DNS services, 54 page technologies), not on a database of thousands of technologies.
- DNS goes to the public resolvers 1.1.1.1 and 8.8.8.8 (one try each, 3 seconds per try). The HTTP part takes at most 12 seconds per domain, and addresses that are not public are refused.
- At most 1,000 domains per run.
- If the run is restarted (platform migration), it resumes at the next row to write: no row is written or billed twice.
Legal and good manners
The Actor reads public DNS records and the public home page. It identifies itself with its User-Agent, reads and follows robots.txt (RFC 9309) before any page request, does not bypass protections, and never sends cookies. Some sites forbid automated browsing in their terms or in free text; check that your use is allowed. The output contains company-level technical data, and e-mail addresses are masked. Source code: MIT license.
FAQ
Does it run JavaScript or a browser? No. It reads the raw HTML, headers, DNS, a few of the site's own scripts and the public GTM container as text. Tools injected only at run time are not seen.
It found no chat widget or no Stripe. Does the site have none? Not necessarily. Stripe usually loads at checkout, not on the home page, and chat widgets are often loaded after consent. Use the DNS findings and page.status to judge.
What if the site blocks it? The page is reported as blocked or robots_disallowed and you are not charged for the page (nor for its scripts). DNS findings are still returned.
Am I charged for failures? No: only rows with status ok are billed, plus the page event when the page was actually read.
Does a SaaS found in DNS mean the company uses it today? Not necessarily. Verification tokens and SPF entries can outlive the contract. Treat them as strong hints, and read the evidence.
Is the same input always the same output? DNS findings are deterministic for the same DNS data; page findings depend on what the home page serves at that moment.
How many domains can I send? Up to 1,000 per run.