Tech Stack, Email Provider & SaaS Detector by Domain avatar

Tech Stack, Email Provider & SaaS Detector by Domain

Pricing

from $2.00 / 1,000 domain analyzed (dns)s

Go to Apify Store
Tech Stack, Email Provider & SaaS Detector by Domain

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

Djam

Maintained by Community

Actor 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:

EventPriceWhen
Domain analyzed (DNS)$0.002the domain exists and its DNS was analyzed (status ok)
Home page analyzed$0.003 morethe home page was fetched and analyzed (page.status = "fetched"); covers its scripts and GTM container
Actor start$0.00005once 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

FieldTypeDefaultDescription
domainsarray of strings (1 to 1,000)requiredDomains (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.
includeSubdomainWwwbooleantrueAlso look up www.<domain> in DNS to detect hosting and CDN.
fetchHomepagebooleantrueRead 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; null when the status is invalid.
  • status: ok, not_found (the domain does not exist or has no records), invalid (not a domain), error (lookups failed and nothing was found). Only ok is billed.
  • emailProvider: {name, evidence}. null with an empty mx means the domain itself receives no mail (the company may use another domain: notion.so has no MX, its mail is on notion.com). Unknown means the MX host is not in our list: read mx and saas, 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 (the include: targets of that record, no recursion), all (final all mechanism); null without SPF.
  • dmarc: policy (value of p=) and the record; null without DMARC.
  • saas: services the domain declares in DNS: name, category and evidence ("<TYPE> <value>").
  • dnsProvider, hosting, cdn: {name, evidence} or null.
  • nameservers: NS targets, sorted.
  • failedLookups: lookups that failed ("MX x.com"). A row with status ok can be partial: mx = [] with no MX x.com here means "no MX"; with it, "MX unknown".
  • page: status is fetched (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) or not_fetched. url is the last page URL requested, httpStatus its response code.
  • technologies: empty unless page.status is fetched. Each item: name, category, version (only for generators, jQuery file names and server headers, else null), source (page: the page HTML and headers; script: one of the site's own scripts; gtm: a Google Tag Manager container) and evidence (page: HEADER name: value, COOKIE name, META generator ..., SCRIPT url, LINK url or HTML excerpt; script: SCRIPT <script url> <pattern>; gtm: GTM <container id> <pattern>). gtm means "configured in the site's GTM container", not necessarily active on the home page. If several sources find the same technology, page wins over script, then gtm. The status of the row stays the DNS status.
  • checkedAt: UTC time of the analysis. error: cause in English when status is not ok.

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.txt is 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, stays fetched and 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, 22 blocked, 8 robots_disallowed, 3 unreachable. The DNS part works for every existing domain.
  • robots.txt is respected: a page it forbids is robots_disallowed, and not billed.
  • No recursion into SPF include: records.
  • No climb to the parent domain: blog.x.com is analyzed as is, without inherited NS or DMARC.
  • No public suffix list: co.uk is 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.

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.