# Website Tech Stack Detector – Bulk CMS, Analytics & Frameworks (`openharvest/website-tech-stack`) Actor

Bulk website technology lookup: detect the CMS, e-commerce platform, analytics, tag managers, JavaScript frameworks and libraries with versions, CDN, hosting, web server and email/DNS provider for any list of domains. Evidence and confidence per technology. Pay per domain.

- **URL**: https://apify.com/openharvest/website-tech-stack.md
- **Developed by:** [Enes Bulanık](https://apify.com/openharvest) (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

$2.00 / 1,000 domain analyseds

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 – Bulk CMS, Analytics & Frameworks

Bulk website technology lookup: for each domain, get the CMS, e-commerce platform, analytics and tag managers, JavaScript frameworks and libraries (with versions), CDN, hosting, web server, email provider and DNS provider in one flat row. Every technology comes with a confidence score and the evidence behind it. Use this instead of a general web crawler when you need a lead list enriched with "what is this site built on", not page content.

**Price: $2 per 1,000 domains, with no start fee.** Unreachable, blocked and invalid domains are free.

### What data do you get?

For every domain or URL, the Actor loads the home page once (no browser) and reads the domain's DNS records. It then matches **500+ technology fingerprints** against response headers, cookie names, `<meta>` tags, script and stylesheet URLs, inline scripts, HTML and DNS records:

- **Platform**: `cms` (WordPress, Drupal, Joomla, Webflow, Wix, Squarespace, HubSpot CMS, Contentful, Ghost, AEM, Sitecore…), `ecommerce` (Shopify, WooCommerce, Magento, BigCommerce, PrestaShop, Salesforce Commerce Cloud, Shopware, VTEX, Ticimax, IdeaSoft, T-Soft…)
- **Analytics & tags**: Google Analytics / GA4, Adobe Analytics, Matomo, Plausible, Mixpanel, Amplitude, Heap, PostHog, Hotjar, Microsoft Clarity, FullStory, Google Tag Manager, Tealium, Segment…
- **Frameworks & libraries**: React, Next.js, Vue.js, Nuxt, Angular, Svelte/SvelteKit, Astro, Gatsby, Remix, Laravel, Django, Rails, ASP.NET, jQuery, Bootstrap, Tailwind CSS, with **versions** wherever the page reveals them (e.g. `WordPress 6.9.10`, `jQuery 3.7.1`, `Nginx 1.25.3`)
- **Infrastructure**: CDN (Cloudflare, CloudFront, Akamai, Fastly…), hosting (Vercel, Netlify, WP Engine, Kinsta, AWS, GitHub Pages…), web server, programming language
- **Marketing & sales stack**: HubSpot, Marketo, Klaviyo, Mailchimp, Intercom, Drift, Zendesk, Stripe, PayPal, Klarna, Meta Pixel, Google Ads, LinkedIn Insight, TikTok Pixel, OneTrust, Cookiebot, Optimizely, VWO, Trustpilot, Yotpo…
- **From DNS**: email provider (Google Workspace, Microsoft 365, Zoho, Proton…), email sending services from SPF (SendGrid, Amazon SES, Mailgun…), DNS provider, and **SaaS tools that verified the domain** (Atlassian, Slack, Stripe, OpenAI, DocuSign, Zoom…)
- **Vulnerable JS libraries**: detected library versions are checked against the open RetireJS vulnerability database, e.g. `jQuery 1.8.2 → 7 known vulnerabilities (CVE-2015-9251, CVE-2019-11358, CVE-2020-11023…), highest severity: medium`.

### Why use it?

- **No start fee, flat price.** $0.002 per domain, all categories, DNS included.
- **Confidence + evidence.** Each technology shows *why* it was detected (`meta generator: WordPress 6.6.2`, `header server: nginx`, `cookie: _shopify_y`), so you can trust the data or filter it with `minConfidence`.
- **Versions and outdated libraries** in the same row, which helps security and agency audits.
- **Spreadsheet-friendly.** Flat fields (`cms`, `ecommerce`, `analytics`, `cdn`…) plus the full `technologies` list for detail.
- **Fast.** No browser: 72 mixed domains finished in about 35–50 s in our tests.
- **Fair billing.** Sites behind bot protection (Cloudflare challenge, DataDome, AWS WAF…) are returned as free `BLOCKED` rows that still list what the headers and DNS reveal.

### Use cases

- **Lead generation and sales ops**: find every Shopify or WooCommerce store in a list, or the prospects that use a competitor's chat or analytics tool.
- **Lead enrichment for AI agents**: an agent profiling a company gets the stack in one call.
- **Agencies**: qualify prospects (old WordPress, no analytics, outdated jQuery) and audit client sites.
- **Market research**: measure CMS, CDN or framework share across thousands of domains.
- **Security hygiene**: spot outdated, known-vulnerable front-end libraries across a portfolio.

### How to use it

1. Enter domains or URLs in **Domains or URLs** (one per line, or comma-separated).
2. Leave **Include DNS-based detection** on to also get the email provider, DNS provider and verified SaaS tools.
3. Click **Start**. Export to JSON, CSV or Excel, or connect via API, Make, Zapier or webhooks.

### Input example

```json
{
    "domains": ["apify.com", "wordpress.org", "allbirds.com", "techcrunch.com", "vercel.com"],
    "includeDns": true,
    "includeEvidence": true,
    "minConfidence": 50
}
```

| Field | Description | Default |
|---|---|---|
| `domains` | Domains or URLs; the home page of each host is analysed | demo: apify.com, wordpress.org, allbirds.com |
| `includeDns` | Read MX/TXT/NS for email, DNS and SaaS detection | `true` |
| `includeEvidence` | Up to 3 evidence strings per technology | `true` |
| `minConfidence` | Hide technologies below this score (0–100) | `50` |
| `maxConcurrency` | Domains analysed in parallel (1–30) | `10` |
| `proxyConfiguration` | Optional Apify Proxy for sites that block datacenter IPs | off |

### Output

Real output for `woocommerce.com` (shortened):

```json
{
    "type": "domain",
    "domain": "woocommerce.com",
    "url": "https://woocommerce.com/",
    "httpStatus": 200,
    "pageTitle": "WooCommerce",
    "cms": "WordPress 7.1.3",
    "ecommerce": "WooCommerce 11.3.0",
    "analytics": ["Jetpack Stats"],
    "tagManagers": ["Google Tag Manager"],
    "frameworks": ["React 18.3.1"],
    "jsLibraries": ["jQuery 3.7.1"],
    "hosting": ["WordPress VIP"],
    "webServers": ["Nginx"],
    "programmingLanguages": ["PHP"],
    "monitoring": ["New Relic"],
    "emailSendingServices": ["Mandrill", "Zendesk (email)"],
    "saasVerified": ["Atlassian", "Google Search Console", "OpenAI (domain)"],
    "vulnerableLibraries": [],
    "technologyNames": ["WordPress 7.1.3", "WooCommerce 11.3.0", "Jetpack Stats", "Google Tag Manager", "React 18.3.1", "jQuery 3.7.1", "WordPress VIP", "Nginx", "PHP", "New Relic", "Font Awesome", "Wistia", "Gutenberg (block editor)", "Yoast SEO 27.3", "Mandrill", "Zendesk (email)", "Atlassian", "Google Search Console", "OpenAI (domain)"],
    "technologyCount": 19,
    "technologies": [
        {
            "name": "WordPress",
            "categories": ["CMS", "Blog"],
            "version": "7.1.3",
            "confidence": 100,
            "evidence": ["header link: <https://woocommerce.com/wp-json/>; rel=\"https://api.w.org/\"…", "meta generator: WordPress 7.1.3", "link: https://woocommerce.com/wp-json/"]
        },
        {
            "name": "Yoast SEO",
            "categories": ["SEO"],
            "version": "27.3",
            "confidence": 100,
            "evidence": ["html: <!-- This site is optimized with the Yoast SEO Premium plugin v27.3"]
        }
    ],
    "responseTimeMs": 2163,
    "checkedAt": "2026-10-08T10:52:00.473Z"
}
```

Other real results from our tests: `allbirds.com` → `ecommerce: "Shopify"`, Cloudflare, Microsoft Clarity, Shop Pay, Microsoft 365. `python.org` → `jQuery 1.8.2` flagged in `vulnerableLibraries`. `nuxt.com` → Nuxt.js, Vue.js, Tailwind CSS, Vercel.

**Free row (blocked by bot protection):**

```json
{ "type": "error", "domain": "stackoverflow.com", "errorCode": "BLOCKED", "blockedBy": "Cloudflare challenge", "error": "Blocked by bot protection (Cloudflare challenge).", "technologyNames": ["Cloudflare", "Cloudflare Bot Management", "Google Workspace", "Microsoft 365"] }
```

Error codes (never charged): `INVALID_DOMAIN`, `UNREACHABLE`, `BLOCKED`, `HTTP_ERROR` (5xx), `NO_TECHNOLOGIES_DETECTED`, `CHECK_FAILED`.

The dataset has three views: **Overview**, **Marketing & sales stack** and **All technologies**.

### Pricing

Pay per event: you pay per analysed domain, and platform usage is included. There is no custom start fee.

| Event | Price | When |
|---|---|---|
| `domain` | **$0.002** ($2 per 1,000) | Each domain row with at least one detected technology |
| Errors | **Free** | Invalid, unreachable, blocked, 5xx or nothing detected |

| Job | Cost |
|---|---|
| Default input (3 domains) | $0.006 |
| 1,000 domains | $2.00 |
| 50,000-domain lead list | $100 |

Set Apify's **Max cost per run** to cap spending. The Actor stops cleanly when it reaches that budget.

### Use with AI agents (MCP)

This Actor works as a tool for AI agents through the Apify MCP server (Claude, Cursor, VS Code, OpenAI Agents and others). Example tool input:

```json
{ "domains": ["example-store.com", "competitor.io"], "includeEvidence": false }
```

The agent gets flat fields (`cms`, `ecommerce`, `analytics`, `frameworks`, `emailProviders`, `technologyNames`) that answer "what is this company's website built on?" or "do they use HubSpot or Marketo?" without parsing HTML. Set `includeEvidence: false` to keep the response small.

### FAQ

**How accurate is it?**
Detections with `confidence: 100` come from definitive signals: a header, a generator tag, a platform cookie or a unique script URL. Lower scores come from weaker hints (generic cookie names, CSS class patterns) and are hidden by default (`minConfidence: 50`). Each row shows the evidence, so you can check any result.

**What can it miss?**
It reads the HTML the server sends. It does not run JavaScript. Tools injected later by a tag manager, or apps that render everything client-side, may not appear. It also checks only the home page, so tools used only on the checkout or blog are missed. Versions appear only when the site exposes them.

**Why is a site BLOCKED?**
Some sites (Cloudflare challenge, DataDome, Akamai, AWS WAF) refuse automated requests. You are not charged, and the row still lists the CDN, bot protection and DNS-based technologies. Enabling Apify Proxy (residential) often helps.

**Where do the fingerprints come from?**
The technology fingerprints are our own, written for this Actor. JavaScript library versions and vulnerability data come from the open-source RetireJS repository (Apache-2.0).

**Is DNS data output?**
Only the detected technologies are output, e.g. `Google Workspace` or `Atlassian`. Raw TXT records and verification tokens are not.

### Is it legal?

The Actor sends one normal GET request to each public home page and reads public DNS records. That is the same information any browser or mail server sees. It does not log in, does not crawl beyond the home page and collects **no personal data**: cookie values are never read (only cookie names) and no emails or names are extracted. Respect each website's terms of use and applicable law when you use the results. Do not use them for spam.

### Related actors

- **Bulk WHOIS Lookup – RDAP, DNS Records, SSL & Redirects**: registration, DNS, SSL and redirect data for the same domain list
- **Sitemap URL Extractor – All URLs from sitemap.xml & robots.txt**: every page URL of a site
- **Shopify & WooCommerce Products Scraper – Any Store, Schema.org**: product catalogs of the stores you found here
- **Shopify App Store Scraper – Apps, Pricing Plans & App Reviews**: the apps behind Shopify stores
- **Chrome Web Store Scraper – Extensions, Users, Ratings & Reviews**

### Support & feedback

Missing a technology or seeing a wrong detection? Open an issue in the **Issues** tab with the domain.

# Actor input Schema

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

Domains or website URLs, one per line (or comma-separated). Accepted: <code>apify.com</code>, <code>www.example.co.uk</code>, <code>https://shop.example.de/path</code>. The home page of each host is analysed. Duplicates are removed.

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

Also read the domain's MX, TXT and NS records to detect the email provider (Google Workspace, Microsoft 365...), email sending services (SendGrid, Amazon SES...), DNS provider and SaaS tools that verified the domain (Atlassian, Slack, Stripe...). Raw records are never output. Same price.

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

Add up to 3 short evidence strings per technology (e.g. <code>meta generator: WordPress 6.6.2</code>, <code>header server: nginx</code>, <code>cookie: \_shopify_y</code>) so you can verify each detection.

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

Hide technologies whose confidence score is below this value. 100 = a definitive signal (header, generator tag, unique script URL). Lower scores come from weaker hints such as generic cookie names or CSS class patterns.

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

How many domains are analysed in parallel. Each domain costs one home-page request plus three DNS lookups.

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

Usually not needed. Enable Apify Proxy (residential works best) if many domains come back as BLOCKED by bot protection (Cloudflare, Akamai, DataDome). Blocked domains are never charged.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "wordpress.org",
    "allbirds.com",
    "techcrunch.com",
    "vercel.com"
  ],
  "includeDns": true,
  "includeEvidence": true,
  "minConfidence": 50,
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped items in the default dataset (JSON, CSV, Excel and more via the dataset export).

## `files` (type: `string`):

Records saved in the default key-value store, e.g. the run summary.

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

// Run the Actor and wait for it to finish
const run = await client.actor("openharvest/website-tech-stack").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",
        "allbirds.com",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

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

```

## MCP server setup

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

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/dWWvAxLU7g9wQnkWR/builds/KRZAUIXTEcYMv1rIh/openapi.json
