# Tech Stack Detector like Wappalyzer & BuiltWith (`wrenfield-data/website-tech-stack-detector`) Actor

Detect the technologies behind any list of websites: CMS, ecommerce platform, analytics, ad pixels, marketing tools, payment, CDN, hosting, frameworks and 7,600+ more, plus email provider and SPF senders from DNS. One clean row per website. Pay only for websites analysed.

- **URL**: https://apify.com/wrenfield-data/website-tech-stack-detector.md
- **Developed by:** [Wrenfield Data](https://apify.com/wrenfield-data) (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

from $1.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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 - Wappalyzer & BuiltWith Alternative

**Find out what any website is built with.** Paste a list of websites or domains and get, for each one, its **CMS**, **ecommerce platform**, **analytics**, **ad pixels**, **marketing automation**, **payment processors**, **live chat**, **CDN**, **hosting**, **JavaScript frameworks** and more, out of **7,600+ technologies**. DNS checks add the domain's **email provider** (Google Workspace, Microsoft 365...) and the **SaaS tools allowed to send its email** (HubSpot, Salesforce, Zendesk, SendGrid...). You get **one clean row per website**, ready for your CRM, Clay, n8n, Make, Zapier or an AI agent.

- 🔎 **Wappalyzer-compatible detection**: uses the open-source Wappalyzer fingerprint format (7,600+ technologies in 100+ categories). Matches headers, cookies, meta tags, script URLs, inline scripts, HTML, DOM selectors, DNS records and the TLS certificate. It also returns **versions** where the site shows them (e.g. `WordPress 6.8`).
- 📬 **Signals other detectors miss**: `emailProvider` and `emailSecurityGateway` from MX records, `emailSendingServices` from SPF, `dnsProvider`, `sslIssuer`, and services that verified the domain (Google, Facebook, Atlassian, DocuSign...).
- 🎯 **Lead lists by technology**: set **Only websites using** to e.g. `Shopify` + `Klaviyo` and get only the matching sites. Non-matching sites are **not charged**.
- 💸 **Pay only for websites analysed**: a flat price per website with at least one technology detected. Dead domains, blocked sites and invalid inputs return a **free** row that says why.
- 🧮 **Lead scoring built in**: `paidSaasCount` and `techSpendScore` estimate how much a company spends on SaaS, using pricing tiers from the fingerprints.
- ⚡ **Fast and light**: plain HTTP with a real-browser TLS fingerprint, no headless browser. In our cloud tests, 3-20 websites took 5-11 s, and 1,000 random domains took about 6.5 minutes (1 GB memory, 40 in parallel).

💸 **$2.50 per 1,000 websites** with at least one technology detected. Dead or blocked sites are free. Try it on Apify's free plan ($5 of monthly credit, no credit card).

#### Sample output

| Domain | Technologies | CMS | Web server | CDN |
|---|---|---|---|---|
| wordpress.org | 14 | WordPress, WordPress Block Editor | Nginx | – |
| apify.com | 22 | – | – | Amazon CloudFront, Amazon S3 |
| allbirds.com | 16 | – | – | Cloudflare |

<sub>Real rows from the prefilled example run (Oct 19, 2026), 5 of 54+ fields shown. Export as JSON, CSV, Excel or HTML, or read them through the API.</sub>

### What data do you get?

| Field group | Fields |
|---|---|
| Summary | `domain`, `url`, `status`, `technologyCount`, `technologies` (all names), `technologiesByCategory` |
| Flat categories (arrays) | `cms`, `ecommerce`, `ecommerceAddOns`, `paymentProcessors`, `analytics`, `tagManagers`, `advertising`, `marketingAutomation`, `emailServices`, `crm`, `liveChat`, `abTesting`, `reviews`, `cookieConsent`, `javascriptFrameworks`, `javascriptLibraries`, `uiFrameworks`, `webFrameworks`, `programmingLanguages`, `webServers`, `cdn`, `hosting`, `security`, `searchAndAI`, `bookingAndScheduling`, `forms`, `recruiting`, `seo` |
| Email & infrastructure | `emailProvider`, `emailSecurityGateway`, `emailSendingServices`, `dnsProvider`, `sslIssuer`, `sslValidUntil`, `dnsRecords` (`mx`, `ns`, `spf`, `txtVerifications`, `cname`) |
| Lead scoring | `paidSaasCount`, `techSpendScore` |
| Details | `technologyDetails`: `name`, `version`, `confidence`, `categories`, `groups`, `website`, `description`, `saas`, `openSource`, `pricing`, `cpe`, `detectedBy` |
| Page | `title`, `description`, `language`, `httpStatus` |
| Run info | `status`, `error`, `errorType`, `pagesScanned`, `scannedUrls`, `pagesFailed`, `proxyUsed`, `redirectedFrom`, `sourceName`, `sourceIndex`, `scrapedAt` |

### How to use

1. Paste **websites or domains** into **Websites / domains**, one per line: `acme.com`, `https://www.acme.com`, `acme.com/pricing`. Email addresses also work (their domain is used).
2. **Or enrich a dataset**: put the ID of a dataset from another Actor (for example Google Maps Scraper, [Website Contact Scraper](https://apify.com/wrenfield-data/website-contact-scraper) or [Company Name to Domain Finder](https://apify.com/wrenfield-data/company-name-to-domain)) into **Enrich an existing dataset**. The website field is detected automatically (`website`, `url`, `domain`...).
3. Optional: **Only websites using** (e.g. `Shopify`, `HubSpot`), **Pages per website** (1-5), **Minimum confidence**.
4. Click **Start**. Download the results as JSON, CSV or Excel. The **All categories** view is flat and CSV-ready. You can also call the Actor through the API or MCP.

### Input example

```json
{
    "urls": ["apify.com", "wordpress.org", "allbirds.com", "gymshark.com"],
    "maxPagesPerWebsite": 1,
    "checkDnsAndTls": true,
    "minConfidence": 50,
    "onlyWithTechnologies": []
}
```

### Output example

A row from a cloud test run (some fields trimmed):

```json
{
    "input": "levainbakery.com",
    "domain": "levainbakery.com",
    "url": "https://levainbakery.com/",
    "status": "ok",
    "technologyCount": 26,
    "technologies": [
        "Cart Functionality",
        "Shopify",
        "Apple iCloud Mail",
        "Microsoft 365",
        "Amazon Web Services",
        "Apple Pay",
        "Amazon S3",
        "Amazon SES",
        "Anthropic",
        "Appstle",
        "Attentive",
        "Black Crow",
        "Cloudflare",
        "Cloudflare DNS",
        "GlobalSign",
        "HSTS",
        "Klaviyo",
        "Klaviyo Reviews",
        "Let's Encrypt",
        "Mailgun",
        "parallax.js",
        "Priority Hints",
        "Sendgrid",
        "Yotpo Reviews",
        "HTTP/3",
        "Open Graph"
    ],
    "cms": [],
    "ecommerce": [
        "Cart Functionality",
        "Shopify"
    ],
    "ecommerceAddOns": [
        "Appstle"
    ],
    "paymentProcessors": [
        "Apple Pay"
    ],
    "analytics": [],
    "marketingAutomation": [
        "Black Crow",
        "Klaviyo",
        "Attentive"
    ],
    "emailServices": [
        "Microsoft 365",
        "Amazon SES",
        "Mailgun",
        "Sendgrid"
    ],
    "reviews": [
        "Klaviyo Reviews",
        "Yotpo Reviews"
    ],
    "cdn": [
        "Amazon S3",
        "Cloudflare"
    ],
    "hosting": [
        "Amazon Web Services",
        "Cloudflare DNS"
    ],
    "emailProvider": null,
    "emailSecurityGateway": "SpamTitan",
    "emailSendingServices": [
        "Amazon SES",
        "SendGrid",
        "Microsoft 365"
    ],
    "dnsProvider": "Cloudflare",
    "sslIssuer": "Let's Encrypt",
    "paidSaasCount": 6,
    "techSpendScore": 8,
    "technologyDetails": [
        {
            "name": "Shopify",
            "version": null,
            "confidence": 100,
            "categories": [
                "Ecommerce"
            ],
            "groups": [
                "Sales"
            ],
            "website": "https://shopify.com",
            "saas": true,
            "openSource": null,
            "pricing": [
                "low",
                "recurring"
            ],
            "cpe": null,
            "detectedBy": [
                "inlineScript",
                "meta",
                "scriptSrc"
            ]
        },
        {
            "name": "Klaviyo",
            "version": null,
            "confidence": 100,
            "categories": [
                "Marketing automation"
            ],
            "groups": [
                "Marketing"
            ],
            "website": "https://www.klaviyo.com/",
            "saas": true,
            "openSource": null,
            "pricing": [
                "mid",
                "recurring"
            ],
            "cpe": null,
            "detectedBy": [
                "scriptSrc"
            ]
        }
    ],
    "dnsRecords": {
        "mx": [
            "cloud12.spamtitan.com",
            "cloud11.spamtitan.com"
        ],
        "spf": "v=spf1 include:amazonses.com include:sendgrid.net ip4:158.106.221.10 include:spf.protectio...",
        "txtVerifications": [
            "apple",
            "globalsign",
            "google"
        ]
    },
    "pagesScanned": 3
}
```

A website that fails returns a **free** row:

```json
{"input": "notarealdomain-xyz123.com", "domain": "notarealdomain-xyz123.com", "status": "error", "errorType": "dns_not_found", "error": "Domain does not resolve (DNS lookup failed). Not charged.", "technologyCount": 0, "technologies": []}
```

| `status` | Meaning | Charged? |
|---|---|---|
| `ok` | The website was analysed and at least one technology was detected | Yes |
| `no_technologies` | The website loaded but no known technology was found | No |
| `filtered_out` | None of the **Only websites using** technologies was found (only output if you enable it) | No |
| `error` | DNS failure, timeout, blocked, HTTP error, not an HTML site (`errorType` says which) | No |
| `invalid_input` | Not a website (e.g. a Facebook page URL, an IP address) | No |

### How it works

1. **Fetch**: it tries `https://domain`, then `www.` and then `http://`, and follows redirects (you get `redirectedFrom` if the site moved to another domain). With **Pages per website** above 1, it also scans pages from different sections of the site (shop, pricing, blog...).
2. **Fingerprints**: every page is matched against 7,600+ open-source Wappalyzer-format fingerprints: response headers, cookies, `<meta>` tags, `<script src>` URLs, inline script content, inline CSS, HTML, DOM selectors and visible text.
3. **DNS & TLS**: MX, TXT (SPF and site verifications), NS, SOA and CNAME records, plus the TLS certificate issuer. These add email provider, email-sending SaaS, DNS host and SSL issuer, and also feed DNS-based fingerprints.
4. **Resolution**: like Wappalyzer, it applies "implies" (WordPress → PHP, MySQL), "excludes" and "requires" rules. Then it sums the confidence and keeps detections at or above your **Minimum confidence**.
5. **Blocking**: pages are fetched directly with a real-browser TLS fingerprint. A website that answers with a bot check, 403 or 429 is retried through Apify Proxy. You can also enable a residential fallback.

### Pricing

This Actor uses **pay-per-event** pricing. You pay for **`website-analyzed`**: one website analysed with at least one technology detected. The price is per website, not per page or per technology. Proxy and compute are included. Websites with nothing detected, websites filtered out by **Only websites using**, errors and invalid inputs are **free**. Check the **Pricing** tab for the current price.

You can cap spending with **Max websites analysed** or the run's **maximum cost**. The Actor stops cleanly at the limit and doesn't start websites it can't charge for.

### Related tools

Find sites that use a technology, then pull their contacts or (for Shopify stores) their full catalog.

- [Website Contact Scraper](https://apify.com/wrenfield-data/website-contact-scraper): get emails, phone numbers and social links for each domain
- [Company Name to Domain](https://apify.com/wrenfield-data/company-name-to-domain): turn a list of company names into official website domains
- [Shopify Store Scraper & Price Monitor](https://apify.com/wrenfield-data/shopify-store-scraper): full catalogs and price/stock change alerts for any Shopify store
- [Domain Authority & Traffic Checker](https://apify.com/wrenfield-data/domain-authority-traffic-checker): bulk domain authority, backlinks and organic traffic

All of these are maintained by the same developer and export flat JSON, CSV or Excel, so you can feed one tool's dataset into the next.

### FAQ

**How is this different from Wappalyzer or BuiltWith?**
Wappalyzer's and BuiltWith's APIs are sold as monthly subscriptions. This Actor uses the same open fingerprint format as Wappalyzer, so detections and names match what you know. You pay per website, with no subscription. Unlike BuiltWith it checks the **live** website at run time instead of a historical database, so results are current but don't include past technologies.

**Why wasn't technology X detected?**
The Actor doesn't run a headless browser, so tools that are only injected later by JavaScript (some chat widgets and pixels loaded through a tag manager) can be missed. It still finds them when they show up in the HTML, script URLs, inline scripts, cookies, headers or DNS. Setting **Pages per website** to 2-3 catches tools that only load on some pages. If something is consistently missing, tell us in the **Issues** tab.

**How accurate is it? What does `confidence` mean?**
Each fingerprint carries a confidence (usually 100). The confidences of all matching signals are added up, to a maximum of 100. **Minimum confidence 50** (the default) hides weak single-signal guesses. `detectedBy` shows how each technology was found (`headers`, `scriptSrc`, `dom`, `dns`, `implied`...), so you can judge for yourself.

**Can I find all websites using a technology (e.g. every Shopify store)?**
This Actor checks the websites **you** provide. It doesn't search the whole web. Feed it a list (from Google Maps Scraper, a CRM export or a domain list) and use **Only websites using** to keep only the matches. You only pay for matches.

**Why does a website list tools like Zoom, Figma, Atlassian or OpenAI?**
Those come from the domain's DNS TXT records. Companies add a verification record when they connect their domain to a SaaS account, so it's a solid sign that the company uses that tool, even though it doesn't run on the website. `detectedBy: ["dns"]` marks them, and `dnsRecords.txtVerifications` lists the raw verifications. Turn off **DNS & TLS checks** if you only want what runs on the website itself.

**Does it give versions?**
Yes, when the site exposes them (meta generator tags, script URLs like `jquery-3.7.1.min.js`, headers). `version` is `null` otherwise.

**What is `techSpendScore`?**
It's a rough lead-scoring signal. For each detected SaaS tool with a paid plan, the fingerprint's pricing tier adds a score (low = 1, mid or price-on-ask = 2, high = 3), and the scores are summed. Higher usually means a bigger marketing/tech budget. `paidSaasCount` is the number of such tools.

**What do the email fields mean?**
`emailProvider` comes from the domain's public MX records. `emailSendingServices` comes from the SPF record, which lists every service allowed to send email as the domain (a strong sign that the company uses HubSpot, Salesforce, Zendesk, Mailchimp...). No email is ever sent.

**Do I need a login, cookies or an API key?**
No. The Actor reads only the public homepage (plus optional extra pages) and public DNS, the same things a browser sees.

**What about websites behind Cloudflare or other bot protection?**
Requests use a real-browser TLS fingerprint, and blocked requests are retried through Apify Proxy. Sites that only show content after a JavaScript challenge may still fail. They return a free `error` row with `errorType: blocked`.

**Can I use it from an AI agent, n8n, Make or Zapier?**
Yes. Call it through the Apify API, the MCP server or any integration with one domain and read the first dataset row. Rows are flat, and `technologies` is a simple list.

**Where do the fingerprints come from?**
From the open-source, community-maintained Wappalyzer fingerprint set ([enthec/webappanalyzer](https://github.com/enthec/webappanalyzer), GPL-3.0), pinned to a fixed version and updated regularly. Technology names, categories and icons belong to their respective owners.

**Is it legal?**
The Actor makes one normal request to each public page you give it, plus public DNS lookups, and doesn't log in. It doesn't collect personal data. You are responsible for how you use the results.

**Something didn't work?**
Open an issue on the **Issues** tab with the run ID and the website. We usually fix things within a day.

# Actor input Schema

## `urls` (type: `array`):

Websites or bare domains, one per line: <code>acme.com</code>, <code>https://www.acme.com</code> or a specific page like <code>acme.com/pricing</code>. Duplicates are skipped. Up to 100,000 per run.

## `datasetId` (type: `string`):

ID of an Apify dataset to enrich, e.g. from Google Maps Scraper, Website Contact Scraper or Company Name to Domain Finder. Each item's website is read from the field below; <code>sourceName</code> / <code>sourceIndex</code> are added so you can join the results back.

## `datasetUrlField` (type: `string`):

Field holding the website in that dataset. Leave empty to auto-detect (<code>website</code>, <code>url</code>, <code>domain</code>, <code>companyWebsite</code>...).

## `onlyWithTechnologies` (type: `array`):

Keep only websites where at least one of these technologies is detected, e.g. <code>Shopify</code>, <code>WooCommerce</code>, <code>HubSpot</code>, <code>Klaviyo</code>. Names as in Wappalyzer, case-insensitive. Websites without a match are <b>not charged</b> and not output (unless enabled below). Great for building lead lists by technology.

## `outputFilteredOut` (type: `boolean`):

When the filter above is set, add a free <code>filtered_out</code> row for each website without a match (status only, no technologies).

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

Hide weak detections below this confidence. 50 keeps everything the fingerprints are reasonably sure about; 100 = only certain detections; 0 = everything.

## `includeTechnologyDetails` (type: `boolean`):

Add <code>technologyDetails</code>: version, confidence, categories, vendor website, SaaS / open-source flags, pricing tier and how each technology was detected.

## `checkDnsAndTls` (type: `boolean`):

Read the domain's MX, TXT (SPF + site verifications), NS, SOA and CNAME records and the TLS certificate issuer: adds email provider (Google Workspace, Microsoft 365...), email security gateway, email-sending services from SPF (HubSpot, Salesforce, SendGrid, Zendesk...), DNS provider and SSL issuer. No emails are sent.

## `maxPagesPerWebsite` (type: `integer`):

1 = homepage only (fastest, finds most technologies). 2-5 also scans pages from different sections (shop, pricing, blog...) to catch tools only loaded there. Never more expensive per website.

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

How many websites are analysed at the same time.

## `maxResults` (type: `integer`):

Stop after this many paid results (websites with at least one technology detected). Leave empty for no limit. You can also cap spending with the run's maximum cost.

## `proxyMode` (type: `string`):

Most websites don't block, so pages are fetched directly and only blocked requests are retried through the proxy.

## `proxyConfiguration` (type: `object`):

Proxy used for websites that block direct requests. Apify datacenter proxy is included in the price.

## `residentialFallback` (type: `boolean`):

Retry still-blocked websites through residential IPs. Slightly higher success on heavily protected sites.

## Actor input object example

```json
{
  "urls": [
    "apify.com",
    "wordpress.org",
    "allbirds.com"
  ],
  "outputFilteredOut": false,
  "minConfidence": 50,
  "includeTechnologyDetails": true,
  "checkDnsAndTls": true,
  "maxPagesPerWebsite": 1,
  "maxConcurrency": 25,
  "proxyMode": "fallback",
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "residentialFallback": false
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `flat` (type: `string`):

No description

## `allRows` (type: `string`):

No description

## `summary` (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 = {
    "urls": [
        "apify.com",
        "wordpress.org",
        "allbirds.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("wrenfield-data/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 = {
    "urls": [
        "apify.com",
        "wordpress.org",
        "allbirds.com",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("wrenfield-data/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 '{
  "urls": [
    "apify.com",
    "wordpress.org",
    "allbirds.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call wrenfield-data/website-tech-stack-detector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,wrenfield-data/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/8FXWu4H0VubpAzCl2/builds/JgnxkC3XZudsR0lSI/openapi.json
