# Tech Stack & SaaS Detector (Wappalyzer / BuiltWith alternative) (`moha-tah/tech-stack-detector`) Actor

Detect the technology stack of any website in bulk: CMS, ecommerce, analytics, frameworks, CDN, plus email provider and SaaS tools revealed by public DNS records (Google Workspace, Microsoft 365, HubSpot, Salesforce, Stripe…). HTTP only, no browser, pay per domain.

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

## Pricing

Pay per event

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

**Find out what any website is built with, and which SaaS tools the company behind it pays for.** Paste a list of domains and get one clean row per site: CMS, ecommerce platform, analytics, tag managers, frameworks, CDN, payment and chat widgets, **plus the email provider and back-office SaaS revealed by public DNS records** (Google Workspace, Microsoft 365, HubSpot, Salesforce, Atlassian, Zoom, Stripe, DocuSign…).

A pay-per-domain **Wappalyzer and BuiltWith alternative** for lead lists, Clay tables and competitive research. No subscription, no browser, no API key.

### What does Tech Stack & SaaS Detector do?

For every domain you give it, the Actor:

1. Loads the homepage over plain HTTP (following redirects, respecting robots.txt) and matches **7,600+ technology fingerprints** against the HTML, scripts, headers, cookies and meta tags.
2. Reads the domain's **public DNS records** (MX, SPF/TXT, domain-verification tokens, NS, CNAME) to detect tools that never appear on the website: email hosting, email-sending services, CRM, collaboration and security SaaS.
3. Returns technologies with **category, version (when exposed), confidence score and how each one was detected**, plus the page title, description, language and company social profiles.

Everything runs on the Apify platform, so you get an API, scheduling, integrations (Make, Zapier, n8n, Clay via HTTP, Google Sheets) and datasets you can export as JSON, CSV or Excel.

### Why use it?

- **Build prospect lists by technology**: "Shopify stores that use Klaviyo", "companies on HubSpot but not Salesforce", "WordPress sites without a cookie banner".
- **Enrich CRM or Clay rows** with tech stack and email provider (Google Workspace vs Microsoft 365 is a strong ICP signal).
- **Competitive and market research**: see which analytics, A/B-testing or payment tools your competitors adopt.
- **Agencies and consultants**: qualify leads before a call, audit client portfolios.
- **Detect what front-end tools miss**: DNS reveals Salesforce, Zendesk, Atlassian, Zoom, DocuSign, OpenAI and more, even when nothing is visible on the homepage.

### How to use it

1. Click **Try for free** and paste your domains (one per line) into **Domains or URLs**. `shopify.com`, `https://www.shopify.com/` and `www.shopify.com/pricing` all work.
2. Optionally list **Technologies to match** (e.g. `Shopify`, `Klaviyo`, `Google Workspace`) to get ready-made true/false columns.
3. Click **Start**. Expect roughly 20 domains per minute with the default 2 GB of memory (more memory means more CPU and faster runs).
4. Download the results or connect them to your tools via the API.

### Input example

```json
{
  "domains": ["allbirds.com", "apify.com", "wordpress.org"],
  "matchTechnologies": ["Shopify", "Google Workspace", "WordPress"],
  "detectDns": true,
  "includeCompanyProfile": true
}
```

### Output example

One row per domain (simplified):

```json
{
  "domain": "www.allbirds.com",
  "url": "https://www.allbirds.com/",
  "ok": true,
  "technologyCount": 17,
  "technologyNames": ["Shopify", "Cloudflare", "Google Tag Manager", "Apple Pay", "PayPal", "Microsoft 365", "DocuSign", "Miro"],
  "emailProviders": ["Microsoft 365"],
  "matches": {"Shopify": true, "Google Workspace": false, "WordPress": false},
  "matchesAny": true,
  "technologies": [
    {"name": "Shopify", "version": null, "confidence": 100, "categories": ["Ecommerce"],
     "website": "https://shopify.com", "saas": true, "detectedVia": ["cookies", "scriptSrc"], "impliedBy": null},
    {"name": "Microsoft 365", "version": null, "confidence": 100, "categories": ["Webmail", "Email"],
     "website": "https://www.microsoft.com/microsoft-365", "saas": true, "detectedVia": ["dns"], "impliedBy": null}
  ],
  "title": "Allbirds: Comfortable, Sustainable Shoes & Apparel",
  "language": "en-US",
  "socialProfiles": {"instagram": "https://www.instagram.com/allbirds", "x": "https://twitter.com/allbirds"},
  "scannedAt": "2026-09-27T21:40:02+00:00"
}
```

The Output tab has three views: **Overview** (one row per domain), **Technologies** (one row per technology, handy for pivot tables) and **Matches**. You can download the dataset in various formats such as JSON, CSV, Excel, XML or HTML.

#### Data fields

| Field | Description |
|---|---|
| `domain`, `url`, `statusCode` | Analyzed host, final URL after redirects, HTTP status |
| `ok`, `error` | Whether results were produced; reason if not |
| `technologyNames`, `technologyCount` | Flat list of detected technologies |
| `technologies[]` | `name`, `version`, `confidence` (0–100), `categories`, `website`, `saas`, `detectedVia` (html, scriptSrc, headers, cookies, meta, dom, dns, implied), `impliedBy` |
| `categories` | Category → technologies (CMS, Ecommerce, Analytics, CRM, Email…) |
| `emailProviders` | Email host from MX records (Google Workspace, Microsoft 365, Zoho, Proton, Mimecast…) |
| `matches`, `matchesAny`, `matchesAll` | Only when *Technologies to match* is set |
| `title`, `description`, `language`, `socialProfiles` | Company profile from the homepage (company pages only, no personal profiles) |
| `dnsRecords` | Raw DNS records (optional) |

### How much does it cost?

You pay **per successfully analyzed domain**. Domains that are unreachable or return nothing are **not charged**. Check the price on the **Pricing** tab. There's no subscription and no minimum. The Apify Free plan's monthly credits are enough to test it on hundreds of domains.

### Tips

- **Speed:** raise *Max concurrency* (default 10) for large lists. Each domain is visited with a polite delay, so large lists stay safe.
- **Precision vs recall:** *Minimum confidence* 50 (default) hides weak hints; set 0 to see everything, or 100 for certainty only.
- **Only interested in a few tools?** Set *Technologies to match* and *Only output domains that match*.
- **Debugging a detection:** enable *Include evidence* to see which script, header or DNS record matched.

### FAQ

**How is this different from Wappalyzer or BuiltWith?**
It uses the open-source Wappalyzer-format rule set maintained by the community (7,600+ technologies) and adds a DNS layer those tools don't expose per domain. You pay per domain instead of a monthly plan.

**What can't it detect?**
It doesn't run a browser, so technologies that only appear after JavaScript executes (some single-page-app libraries, tags injected by tag managers) can be missed. Back-end tools with no public footprint (no DNS record, nothing in HTML) are invisible to any detector.

**Is it legal?**
It reads only what any visitor's browser receives from a site's public homepage, plus public DNS. It respects robots.txt by default and collects **no personal data**: no emails, no phone numbers, no personal social profiles. You're responsible for how you use the results (e.g. anti-spam laws when prospecting).

**Can I use it from Clay, Make, Zapier or n8n?**
Yes. Call the Actor via the Apify API ("Run Actor synchronously and get dataset items") with one or more domains.

**Something wrong or missing?**
Open an issue on the **Issues** tab with the domain and the expected technology. New fingerprints are usually added within days.

### Credits

Technology fingerprints come from [webappanalyzer](https://github.com/enthec/webappanalyzer) (GPL-3.0), a community fork of the original Wappalyzer rules. DNS resolution uses public DNS-over-HTTPS resolvers (Cloudflare, Google).

# Actor input Schema

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

Websites to analyze, one per line. Bare domains (shopify.com) or full URLs both work. Duplicates are removed.

## `matchTechnologies` (type: `array`):

Adds a true/false column per technology (e.g. Shopify, Klaviyo, HubSpot, Google Workspace) plus 'matchesAny' / 'matchesAll'. Names are case-insensitive and follow the Wappalyzer naming.

## `onlyMatching` (type: `boolean`):

Hide domains that match none of 'Technologies to match'. Analyzed domains are still charged.

## `detectDns` (type: `boolean`):

Reads public MX, TXT (SPF and domain-verification tokens), NS, SOA and CNAME records to reveal email providers and back-office SaaS (Google Workspace, Microsoft 365, Salesforce, HubSpot, Atlassian, Zoom, Stripe…).

## `includeCompanyProfile` (type: `boolean`):

Adds page title, meta description, language and company social profile links found on the homepage.

## `minConfidence` (type: `integer`):

Hide detections below this confidence. Most rules score 100; weak hints score 25-50.

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

Adds up to 3 short evidence strings per technology (which header, script or record matched).

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

Adds the raw MX/TXT/NS/SOA/CNAME records to each row.

## `respectRobotsTxt` (type: `boolean`):

When a site disallows its homepage for crawlers, only DNS is analyzed. Turn off only for sites you own or are authorized to scan.

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

Domains analyzed in parallel.

## `requestTimeoutSecs` (type: `integer`):

Timeout per HTTP request. Retries with backoff are automatic.

## Actor input object example

```json
{
  "domains": [
    "shopify.com",
    "apify.com",
    "wordpress.org"
  ],
  "matchTechnologies": [],
  "onlyMatching": false,
  "detectDns": true,
  "includeCompanyProfile": true,
  "minConfidence": 50,
  "includeEvidence": false,
  "includeDnsRecords": false,
  "respectRobotsTxt": true,
  "maxConcurrency": 10,
  "requestTimeoutSecs": 20
}
```

# 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": [
        "shopify.com",
        "apify.com",
        "wordpress.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("moha-tah/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": [
        "shopify.com",
        "apify.com",
        "wordpress.org",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("moha-tah/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": [
    "shopify.com",
    "apify.com",
    "wordpress.org"
  ]
}' |
apify call moha-tah/tech-stack-detector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,moha-tah/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/Kgcvm7HjiAC968qBy/builds/n9jlipMoWfz2OxJHv/openapi.json
