# Website Tech Stack Detector: CMS, Analytics, Email & DNS (`leonardoo/website-tech-stack-detector`) Actor

Find the technologies behind any list of websites: CMS, e-commerce platform, analytics, ad pixels, marketing tools, chat, payments, CDN and hosting, plus email provider and SaaS tools from DNS. BuiltWith and Wappalyzer alternative.

- **URL**: https://apify.com/leonardoo/website-tech-stack-detector.md
- **Developed by:** [Clean Data Feeds](https://apify.com/leonardoo) (community)
- **Categories:** Lead generation, SEO tools, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 website analyzeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Website Tech Stack Detector - CMS, Analytics, Marketing, Email & DNS

Find out **which technologies any list of websites uses**: CMS and site builder, e-commerce platform, analytics and tag managers, advertising pixels, marketing automation and CRM, live chat, payments, JavaScript frameworks, CDN, hosting and web server. It also reads **public DNS** to show **email hosting (Google Workspace, Microsoft 365...), email-sending services (SendGrid, Amazon SES, Mailgun...), DNS hosting, DMARC policy and verified SaaS tools** (Atlassian, Slack, DocuSign, Zoom...). It's a fast, low-cost **BuiltWith / Wappalyzer alternative** for lead lists and market research.

### What does it do?

For each domain it:

1. Fetches the **public homepage once** (only if robots.txt allows it) and checks HTTP headers, cookie *names*, `<script>`, `<link>` and `<meta>` tags and HTML markers.
2. Queries **public DNS**: MX, TXT/SPF, NS and `_dmarc` records.
3. Matches everything against **192 technology signatures**, adds versions where they are visible (e.g. WordPress, nginx, Angular), and rates each detection `high`, `medium` or `low` confidence with the evidence (`detectedVia`).

No browser and no proxies: about **1 second per domain**, with up to 30 domains in parallel.

### Who is it for?

- **Sales and lead-gen teams**: build "companies using Shopify + Klaviyo" or "sites on HubSpot" lists with the `onlySitesUsing` filter, then personalize outreach.
- **Agencies and SaaS marketers**: find prospects on a competitor's platform, or find migration opportunities (e.g. Universal Analytics leftovers, old jQuery versions).
- **Investors and analysts**: technographic snapshots of a portfolio or market.
- **IT and security teams**: an inventory of email security (SPF, DMARC, gateways) and CDNs across many domains.

### Input

| Field | Description |
|---|---|
| `domains` | Domains or URLs, one per line |
| `onlySitesUsing` | Optional: output only sites using any of these technologies (e.g. `Shopify`, `HubSpot`) |
| `analyzeHtml` / `analyzeDns` | Turn either detection layer on or off (both on by default) |
| `includeEvidence` | Add `detectedVia` per technology |
| `includeDnsRecords` | Add raw MX / NS / SPF records |
| `maxItems` / `maxConcurrency` | Limits |

### Output

One record per domain. Real example (shortened):

```json
{
    "domain": "apify.com",
    "finalUrl": "https://apify.com/",
    "statusCode": 200,
    "title": "Apify: Marketplace of ready-to-run tools for AI",
    "technologyCount": 13,
    "technologyNames": "Amazon CloudFront, Amazon Route 53, Google Workspace, DMARC, Next.js, React, Intercom, HubSpot, Google Search Console, HSTS, Google Tag Manager, Amazon SES, Mailgun",
    "cms": [],
    "analytics": ["Google Tag Manager"],
    "marketingAutomation": ["HubSpot"],
    "liveChatAndSupport": ["Intercom"],
    "jsFrameworks": ["Next.js", "React"],
    "cdnAndHosting": ["Amazon CloudFront"],
    "emailHosting": ["Google Workspace"],
    "emailSendingServices": ["Amazon SES", "Mailgun"],
    "dnsHosting": ["Amazon Route 53"],
    "hasSpf": true,
    "dmarcPolicy": "reject",
    "technologies": [
        {"name": "Next.js", "category": "JavaScript framework", "version": null, "detectedVia": ["html"], "confidence": "medium"},
        {"name": "HubSpot", "category": "Marketing automation", "version": null, "detectedVia": ["script", "dns-spf"], "confidence": "high"}
    ]
}
```

Summary fields: `cms`, `ecommercePlatform`, `analytics`, `advertising`, `marketingAutomation`, `liveChatAndSupport`, `payments`, `jsFrameworks`, `cdnAndHosting`, `webServer`, `emailHosting`, `emailSendingServices`, `dnsHosting`. The `technologyNames` column is handy for CSV and Excel.

### Pricing

Pay per event, no monthly fee:

- **$2.50 per 1,000 websites** analyzed ($0.0025 per site).
- **$0.005 per run** start fee.

You only pay for websites whose results are saved to the dataset. Set a maximum cost per run to cap spending.

### Responsible use and data

- **One polite request per site.** The Actor reads robots.txt first. If the homepage is disallowed, it skips the HTML and reports DNS-only results with a `note`.
- **No bypassing.** If a site blocks automated visitors (403, challenge pages), the Actor reports the status code and DNS results and does not retry through proxies or browsers.
- **No personal data.** The output is about technologies, not people. Cookie *values* and raw TXT verification tokens are never output.
- The technology signatures were written for this Actor. No third-party fingerprint database is copied.

### Limits and notes

- Detection is based on the homepage only. Tools loaded only on inner pages, after cookie consent, or by a tag manager at runtime can be missed. DNS detection helps fill the gap.
- Apex-domain DNS is used (`www.` is stripped). Subdomain-specific email setups can differ.
- Signatures are maintained and extended over time. Ask for a technology in the Issues tab.

### FAQ

**How is this different from BuiltWith or Wappalyzer?** It's pay-per-result with no subscription, it runs on your own list, and it adds DNS-based detection (email provider, SPF senders, DMARC, verified SaaS) that HTML-only tools miss.

**What does "confidence" mean?** `high`: a specific header, meta tag, script URL, cookie or DNS record matched (or several signals agreed). `medium`: a single HTML marker matched. `low`: implied by another technology (e.g. WooCommerce implies WordPress).

# Actor input Schema

## `domains` (type: `array`):

One per line, e.g. example.com or https://www.example.com. Each domain is analyzed once (homepage + DNS).

## `onlySitesUsing` (type: `array`):

Optional lead-list filter: output a site only if one of its detected technologies contains any of these names, e.g. Shopify, HubSpot, Klaviyo. Leave empty to output every site.

## `analyzeHtml` (type: `boolean`):

Fetch the public homepage once (only if robots.txt allows it) and detect from HTML, scripts, meta tags, headers and cookie names.

## `analyzeDns` (type: `boolean`):

Query public DNS (MX, TXT/SPF, NS, DMARC) to detect email hosting, email-sending services, verified SaaS tools and DNS hosting.

## `includeEvidence` (type: `boolean`):

Add detectedVia (html, script, header, meta, cookie, dns-mx, dns-spf...) to each technology.

## `includeDnsRecords` (type: `boolean`):

Add the raw MX, NS and SPF records to each result.

## `maxItems` (type: `integer`):

Analyze at most this many domains from the list (0 = all).

## `maxConcurrency` (type: `integer`):

Domains analyzed in parallel.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "wordpress.org",
    "shopify.com",
    "vercel.com",
    "hubspot.com"
  ],
  "analyzeHtml": true,
  "analyzeDns": true,
  "includeEvidence": true,
  "includeDnsRecords": false,
  "maxItems": 0,
  "maxConcurrency": 10
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domains": [
        "apify.com",
        "wordpress.org",
        "shopify.com",
        "vercel.com",
        "hubspot.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("leonardoo/website-tech-stack-detector").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "domains": [
        "apify.com",
        "wordpress.org",
        "shopify.com",
        "vercel.com",
        "hubspot.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("leonardoo/website-tech-stack-detector").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "domains": [
    "apify.com",
    "wordpress.org",
    "shopify.com",
    "vercel.com",
    "hubspot.com"
  ]
}' |
apify call leonardoo/website-tech-stack-detector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,leonardoo/website-tech-stack-detector"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/h304wwdsol2YSS3If/builds/galZptw2FaYMc7VKU/openapi.json
