# Website Tech Stack Detector - CMS, Ecommerce, Hosting (`rel8ble/website-tech-stack-detector`) Actor

Detect the technology behind any website: CMS, ecommerce platform, frameworks, analytics, CDN, hosting and email provider, with a confidence score and evidence for every match. 7,600+ fingerprints, HTTP-only, bulk lists. A cheap Wappalyzer / BuiltWith alternative.

- **URL**: https://apify.com/rel8ble/website-tech-stack-detector.md
- **Developed by:** [Giovanni Rich](https://apify.com/rel8ble) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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

This **tech stack detector** is a bulk **website technology lookup**: paste a list of domains and see what each site is built with, from the **CMS, ecommerce platform, frameworks, analytics and ad tools** to the **CDN, hosting, web server and email provider**. It works as an affordable **Wappalyzer alternative** and **BuiltWith alternative**, with no subscription or API key, and every technology comes with a **confidence score and the evidence** that matched.

It checks each site against **7,600+ technology fingerprints** (the open Wappalyzer rule set, kept up to date) plus DNS, email and TLS records. It works over plain HTTP with **no headless browser**, so a list of 1,000 sites finishes in minutes and costs very little to run.

### How to use

1. **Enter websites**: paste domains or URLs into **Websites**, one per line (`shopify.com`, `www.example.com` or `https://example.com/pricing` all work).
2. **Click Start**: every site is analyzed in parallel, usually in seconds.
3. **Download the results** as JSON, CSV, Excel or HTML from the Output tab, or call the actor through the Apify API and get the dataset back in your own code.

### What you get

- **Headline columns, ready for a spreadsheet**: `cms`, `ecommerce`, `javascriptFrameworks`, `webFrameworks`, `uiFrameworks`, `analytics`, `tagManagers`, `advertising`, `marketingAutomation`, `paymentProcessors`, `cdn`, `hosting`, `webServers`, `programmingLanguages`, `databases`, `security`, `liveChat`, `cookieCompliance`, `abTesting`.
- **Every technology with proof**: name, version (when the site exposes it), confidence 0-100, categories, and the evidence that matched: a response header, a script URL, a cookie, a meta tag, an HTML element or a DNS record. You can check any result yourself.
- **Hosting hints**: hosting and CDN providers from reverse DNS, CNAME records and response headers (AWS, Google Cloud, Azure, Vercel, Netlify, Shopify, WP Engine, Cloudflare, Fastly, Akamai...), plus IP addresses, `Server` and `X-Powered-By` headers.
- **Email and DNS**: email provider from MX records (Google Workspace, Microsoft 365, Proofpoint, Mimecast...), **email senders** the domain authorised in SPF (SendGrid, Mailchimp, HubSpot, Salesforce, Klaviyo...), and the DNS provider.
- **SaaS tools verified in DNS**: many companies verify their domain with tools like Atlassian, OpenAI, Zoom, DocuSign, Adobe or Slack. Those TXT records appear in `dnsTechnologies`, kept apart from what runs on the website.
- **TLS certificate**: issuer and expiry date.
- **Works behind bot walls**: if a site answers with a Cloudflare or Akamai challenge page, you still get what the headers, DNS and TLS reveal, and the row is flagged `blocked: true`.

### Use cases

- **Lead generation and sales prospecting**: find every Shopify, WooCommerce or HubSpot user in a list of domains, then pitch the apps, agencies or integrations that fit their stack.
- **Competitor research**: see which analytics, A/B testing, CRM and ad tools your competitors run.
- **Lead enrichment**: add tech stack columns to a CRM export or a scraped company list.
- **Market sizing**: count the platform share across thousands of sites in a niche.
- **Agency and security audits**: spot outdated CMS versions, missing HSTS, expiring certificates and forgotten trackers.

### Input

| Field | Default | Description |
|---|---|---|
| `urls` | - | Domains or URLs, one per line: `shopify.com`, `www.example.com`, `https://example.com/pricing` |
| `includeDns` | true | MX, TXT/SPF, NS, CNAME, A/PTR and TLS lookups (email provider, DNS provider, hosting hints, SaaS verifications). No extra web requests. |
| `includeEvidence` | true | Show what matched for every technology. Turn off for smaller output. |
| `minConfidence` | 0 | Drop technologies below this confidence (0-100) |
| `includeFailed` | true | Save a free row with the error for sites that could not be loaded |
| `maxConcurrency` | 20 | Sites analyzed in parallel |
| `maxRequestRetries` | 3 | Retries for timeouts, 5xx errors and bot walls |
| `requestTimeoutSecs` | 30 | Per-page timeout |
| `proxyConfiguration` | off | Not needed for most sites. Turn on Apify Proxy (RESIDENTIAL works best) if many rows come back `blocked: true`. |

Bare domains are tried over `https://` first, then `http://`. If a domain doesn't resolve, the actor also tries it with or without `www.` before giving up.

### Input example

```json
{
    "urls": ["allbirds.com", "minimalistbaker.com", "nextjs.org", "https://www.hubspot.com"],
    "includeDns": true,
    "includeEvidence": true,
    "minConfidence": 50
}
```

### Output example

One dataset item per website. This one is from a real run on `minimalistbaker.com` (the `technologies` array is shortened to 3 of 26 entries):

```json
{
    "inputUrl": "minimalistbaker.com",
    "url": "https://minimalistbaker.com/",
    "domain": "minimalistbaker.com",
    "statusCode": 200,
    "blocked": false,
    "pageTitle": "Minimalist Baker - Simple Recipes That Make You Feel Good",
    "technologyCount": 26,
    "technologyNames": ["Adobe Fonts", "Amazon Advertising", "Cloudflare", "Font Awesome", "Genesis theme", "Google Analytics", "Google Tag Manager", "HSTS", "Instagram Feed for WordPress", "jQuery", "MySQL", "Open Graph", "PHP", "Popup Maker", "RSS", "WooCommerce", "WordPress", "Yoast SEO", "..."],
    "dnsTechnologies": ["Google Workspace"],
    "cms": ["WordPress"],
    "pageBuilders": ["WordPress Block Editor"],
    "ecommerce": ["WooCommerce"],
    "javascriptFrameworks": [],
    "javascriptLibraries": ["jQuery", "Mailcheck", "mobile-detect.js", "punycode"],
    "analytics": ["Google Analytics"],
    "tagManagers": ["Google Tag Manager"],
    "advertising": ["Amazon Advertising"],
    "cdn": ["Cloudflare"],
    "programmingLanguages": ["PHP"],
    "databases": ["MySQL"],
    "security": ["HSTS"],
    "hostingProviders": ["Cloudflare"],
    "server": "cloudflare",
    "poweredBy": null,
    "tlsIssuer": "Google Trust Services / WE1",
    "tlsExpires": "2026-12-04T21:16:49.000Z",
    "emailProvider": "Google Workspace",
    "emailSenders": [],
    "dnsProvider": null,
    "ipAddresses": ["172.66.168.11", "104.20.42.232"],
    "ipv6": true,
    "reverseDns": [],
    "nameservers": ["b.minimalistbaker.com", "m.minimalistbaker.com"],
    "mxRecords": ["aspmx.l.google.com", "alt1.aspmx.l.google.com", "..."],
    "technologies": [
        {
            "name": "Cloudflare",
            "version": null,
            "confidence": 100,
            "categories": ["CDN"],
            "website": "https://www.cloudflare.com",
            "source": "website",
            "evidence": [
                { "type": "headers", "key": "server", "match": "cloudflare" },
                { "type": "headers", "key": "cf-ray", "match": "a3ff5b60c8d35414-IAD" },
                { "type": "dns", "key": "soa", "match": ".cloudflare.com" }
            ]
        },
        {
            "name": "Amazon Advertising",
            "version": null,
            "confidence": 100,
            "categories": ["Advertising"],
            "website": "https://advertising.amazon.com",
            "source": "website",
            "evidence": [{ "type": "scriptSrc", "match": ".amazon-adsystem.com" }]
        },
        {
            "name": "Adobe Fonts",
            "version": null,
            "confidence": 100,
            "categories": ["Font scripts"],
            "website": "https://fonts.adobe.com",
            "source": "website",
            "evidence": [{ "type": "dom", "key": "link[href*='use.typekit.net'], link[href*='use.typekit.com']", "match": "element present" }]
        }
    ],
    "responseTimeMs": 1639,
    "redirected": false,
    "error": null,
    "scrapedAt": "2026-09-24T05:23:24.827Z"
}
```

The dataset has three ready-made views: **Overview** (the headline stack per site), **Marketing stack** (analytics, ads, CRM, payments, SaaS tools) and **Infrastructure** (server, CDN, hosting, DNS, IP, TLS).

`source` tells you where a technology was seen: `website` (the page, its headers or cookies) or `dns` (DNS records only, for example a TXT verification record). The summary columns only use `website` matches, so a company that merely verified its domain with a tool doesn't show up as running it on the site.

#### Test results (real run: 46 domains, mixed Shopify stores, WordPress blogs, SaaS, news and big retail sites)

- 45 of 46 analyzed in 25 seconds on a laptop. The one failure was a domain that doesn't exist, returned as a free error row.
- 1 site (g2.com) sat behind a bot wall and was still analyzed from headers, DNS and TLS (22 technologies).
- All 9 Shopify stores and all 9 WordPress sites in the test were identified correctly.
- Median 11 website technologies per site (max 25).

| Field | Fill rate |
|---|---|
| technologyNames, ipAddresses | 100% |
| tlsIssuer | 98% |
| emailProvider | 96% |
| server | 84% |
| dnsProvider | 84% |
| hostingProviders | 73% |
| emailSenders (SPF) | 64% |
| cdn | 58% |
| javascriptFrameworks | 42% |
| tagManagers | 42% |
| cms | 40% (many big sites run custom code with no CMS) |
| ecommerce | 27% (only the stores) |
| analytics | 27% (see Limits) |

### Pricing

**Pay per result: $3.00 per 1,000 results** (one result = one website analyzed).

- 1,000 websites = $3.00
- 10,000 websites = $30.00

Websites that fail to load (dead domains, timeouts) are saved for your records but **never charged**. If you set a maximum cost per run, the actor stops cleanly when it reaches it. The Apify free plan includes $5 of monthly credit, enough to try it on a real list.

### Integrations

- **Make, Zapier and n8n**: run the actor from your workflows and pass the tech stack columns to your CRM or outreach tools.
- **Google Sheets**: export the dataset straight to a sheet, or schedule runs that keep a sheet up to date.
- **Apify API**: start runs and fetch results over REST, or with the JavaScript and Python API clients.
- **Webhooks**: get notified (or trigger your own endpoint) when a run finishes.
- **MCP for AI agents**: the Apify MCP server at https://mcp.apify.com lets Claude, ChatGPT, Cursor and other AI agents call this actor as a tool, for example "what CMS and analytics does this list of sites use?".

### Limits (read before large runs)

- **Homepage only.** The actor analyzes the page you give it (after redirects). A tool that only loads on the checkout or blog page won't be seen unless you pass that URL too.
- **No JavaScript execution.** Technologies that only appear after scripts run in a browser can be missed. The biggest case is **analytics tags loaded through Google Tag Manager**: the actor sees GTM, but not always the Google Analytics, Hotjar or Meta Pixel tags inside the container. Tags written directly into the page (the usual `gtag`, `fbq`, Clarity, Hotjar, TikTok and Pinterest snippets) are detected.
- **Bot walls.** Some large sites (G2, Indeed, some banks) answer automated requests with a challenge page. You still get headers, DNS and TLS data with `blocked: true`. A RESIDENTIAL proxy lets more of them through.
- **Fingerprints are signatures, not certainty.** Each technology has a confidence score and evidence. A few generic rules (for example "Cart Functionality", which only means "has a checkout link") are kept in `technologies` but left out of the summary columns. Use `minConfidence: 50` for the strictest list.
- **Hosting hints are hints.** When a site sits behind a CDN like Cloudflare, the origin host is hidden, and the actor reports the CDN.

### FAQ

**Is this a Wappalyzer or BuiltWith alternative?**
Yes. It uses the same kind of fingerprints Wappalyzer uses (7,600+ technologies across 110 categories) and adds DNS, email, SPF and TLS data. You pay per website analyzed, with no subscription or API key.

**Does it need a browser, cookies or an account?**
No. It makes plain HTTPS requests and DNS lookups, which is why it's fast and cheap.

**How accurate is it?**
Every match comes with its evidence, so you can check any result. In our test, every Shopify and WordPress site was identified correctly. Detection is weaker for tools that only load through a tag manager (see Limits).

**Can I analyze 10,000 domains?**
Yes. Put them all in `urls`. Sites are analyzed in parallel (20 at a time by default, up to 100), and each one is a different server, so large lists run quickly.

**What does `blocked: true` mean?**
The site returned a bot-protection page instead of its real homepage. The row still has everything the headers, DNS and TLS certificate reveal, but page-level tools (CMS, analytics) may be missing.

**Why is `dnsTechnologies` separate?**
A TXT record like `atlassian-domain-verification=...` shows the company uses Atlassian, but it doesn't mean Atlassian runs on the website. These are useful for sales prospecting, so they're kept, just apart from the website stack.

**Is it legal to scrape a website's tech stack?**
The actor reads only public information: the public homepage, its HTTP headers, public DNS records and the TLS certificate. It doesn't log in and doesn't collect personal data. You are still responsible for using the results in line with each site's terms of service and privacy laws such as GDPR. This is not legal advice.

**How does it avoid blocks?**
Each site gets one request with realistic Chrome desktop headers, and each website is a different server, so there is no single site to rate-limit you. Timeouts, 5xx errors and bot walls are retried with backoff (3 retries by default, up to 10) on a fresh session. With Apify Proxy turned on, each retry uses a new IP; without a proxy the actor retries a bot wall once and then keeps what the headers, DNS and TLS reveal (`blocked: true`). Bare domains fall back from https to http, and from `example.com` to `www.example.com` (or back) when a domain doesn't resolve.

**What are the limits?**
Homepage (or the exact URL you give) only, no JavaScript execution, and some big sites answer with a bot wall. Concurrency goes up to 100 sites at a time, the page timeout up to 120 seconds, and the first 3 MB of HTML is analyzed. See "Limits" above for details.

### How it works (for developers)

Each site gets one HTTP request, with browser-like headers and retries, plus DNS lookups (MX, TXT, NS, SOA, CNAME, A, PTR) and one TLS handshake. The response headers, cookies, meta tags, script URLs, inline scripts, CSS, page text and DNS records are matched against the Wappalyzer fingerprint rules. DOM rules are evaluated with cheerio instead of a browser, and a one-pass Aho-Corasick prefilter skips selectors that can't match, so analysis takes about 0.3 seconds per page. Excludes, implies (WordPress implies PHP and MySQL, for example) and parent-dependent technologies are resolved the same way Wappalyzer does.

Run it locally:

```bash
npm install
npm test                                              # detection tests
APIFY_LOCAL_STORAGE_DIR=./storage node src/main.js    # input in storage/key_value_stores/default/INPUT.json
```

Fingerprint data: the open [Wappalyzer rule set](https://github.com/enthec/webappanalyzer) (GPL-3.0) via the `simple-wappalyzer` package.

# Actor input Schema

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

Websites to analyze, one per line. "shopify.com", "www.example.com" and "https://example.com/page" all work. Bare domains are tried over https first, then http, and with or without "www." if they don't resolve. Each website analyzed is one result.

## `includeDns` (type: `boolean`):

Look up MX, TXT (SPF and verification records), NS, CNAME, A/PTR and the TLS certificate. Adds email provider, email senders (SendGrid, Mailchimp...), DNS provider, hosting hints, IPs and the SaaS tools the company verified its domain with (Atlassian, OpenAI, Zoom...). No extra web requests.

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

For every technology, show what matched (header, script URL, cookie, meta tag, HTML element, DNS record) so you can verify it. Turn off for smaller output.

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

Drop technologies below this confidence score. 0 keeps everything, 50 removes weak single-signal guesses, 100 keeps only certain matches. Example: 50.

## `includeFailed` (type: `boolean`):

Add a row with the error for websites that could not be loaded (dead domain, timeout). These rows are never charged.

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

How many websites are analyzed in parallel (1-100). Each website is a different server, so high values are safe. Example: 20.

## `maxRequestRetries` (type: `integer`):

How many times to retry a website after a timeout, 5xx error or bot wall (0-10). With a proxy each retry uses a new IP. Example: 3.

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

Give up on a slow page after this many seconds (5-120), then retry. Example: 30.

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

Not needed for most websites. Turn on Apify Proxy (RESIDENTIAL group works best) if many of your sites come back with "blocked": true.

## Actor input object example

```json
{
  "urls": [
    "allbirds.com",
    "techcrunch.com",
    "nextjs.org",
    "wix.com"
  ],
  "includeDns": true,
  "includeEvidence": true,
  "minConfidence": 0,
  "includeFailed": true,
  "maxConcurrency": 20,
  "maxRequestRetries": 3,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `websites` (type: `string`):

One row per website: CMS, ecommerce, frameworks, analytics, CDN, hosting, email provider and every detected technology with confidence and evidence.

## `summary` (type: `string`):

Counts, failures and bot walls for the run.

# 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": [
        "allbirds.com",
        "techcrunch.com",
        "nextjs.org",
        "wix.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rel8ble/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": [
        "allbirds.com",
        "techcrunch.com",
        "nextjs.org",
        "wix.com",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

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

```

## MCP server setup

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