# Tech Stack Detector: CMS, framework, CDN & analytics (`aiqlabs/tech-stack-detector`) Actor

Detect what any website is built with - CMS, e-commerce platform, framework, web server, CDN, analytics, ad pixels, payments, support chat and consent tools - with the exact evidence for every match. Respects robots.txt. No API keys.

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

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Tech Stack Detector: CMS, framework, CDN & analytics

Give it a list of websites. Get back what each one is built with — **CMS,
e-commerce platform, framework, web server, CDN, hosting, analytics, ad pixels,
payment provider, support chat and consent tool** — and, for every single match,
**the exact evidence that proved it**.

No API keys. Nothing to configure. Respects `robots.txt` by default.

### Why the evidence matters

Most detectors hand you a label. This one hands you the label *and* the proof:

```json
"technologies": [
  { "name": "WordPress",      "category": "CMS",         "confidence": "high", "via": "meta",   "evidence": "meta generator: WordPress 6.5.2" },
  { "name": "Cloudflare",     "category": "CDN",         "confidence": "high", "via": "header", "evidence": "header cf-ray: 8f2c1a-NRT" },
  { "name": "Stripe",         "category": "Payments",    "confidence": "high", "via": "script", "evidence": "asset URL: js.stripe.com" },
  { "name": "Laravel",        "category": "Framework",   "confidence": "high", "via": "cookie", "evidence": "cookie name: laravel_session" }
]
```

If a result looks wrong, you can check it in seconds instead of trusting a black box.
`confidence` is `high` when the signal is effectively unique to that technology and
`low` when it could plausibly appear for another reason.

### Output per site

| Group | Fields |
|---|---|
| Verdict | `status` (`ok` / `http_error` / `blocked_by_robots` / `unreachable`), `technologyCount`, `highConfidenceCount` |
| Flat columns | `cms`, `ecommerce`, `framework`, `webServer`, `cdn`, `hosting`, `customerSupport`, `consentManagement` |
| Lists | `analytics[]`, `advertising[]`, `payments[]`, `technologyNames[]`, `byCategory{}` |
| Detail | `technologies[]` with `name`, `category`, `confidence`, `via`, `evidence` |
| Page | `httpStatus`, `finalUrl`, `pageTitle`, `metaGenerator`, `assetUrlCount`, `htmlBytes` |

The flat columns exist so the CSV export drops straight into a spreadsheet;
`technologies[]` is there when you want to audit the reasoning.

### Typical uses

- **Qualify a prospect list** — find every site on Shopify, or every site still on
  a legacy CMS, before you write the first email.
- **Competitive teardown** — see which analytics, ad pixels and support tools a set
  of competitors actually run.
- **Portfolio audit** — check that every site you manage has the consent tool and
  the analytics you think it has.
- **Partner / vendor due diligence** — confirm the stack a supplier claims to use.

### Input

```json
{
  "domains": ["apify.com", "https://wordpress.org/about/", "shopify.com"],
  "respectRobots": true,
  "includeEvidence": true,
  "maxConcurrency": 8
}
```

- `domains` accepts bare domains **or** full URLs. A single entry may hold many
  sites separated by spaces, commas or newlines, so pasting a spreadsheet column works.
- `respectRobots` (default **on**) reads `robots.txt` first and skips the site if this
  crawler is disallowed, reporting `blocked_by_robots` with the rule that blocked it.
- `includeEvidence` off returns just name/category/confidence, for smaller datasets.

### What it detects

Around 100 technologies across 18 categories:

**CMS** WordPress · Drupal · Joomla · Ghost · Contentful · Sanity · AEM · Sitecore · HubSpot CMS · Webflow · Wix · Squarespace · TYPO3
**E-commerce** Shopify · WooCommerce · Magento · BigCommerce · PrestaShop · Salesforce Commerce Cloud · Ecwid · BASE · STORES
**Framework** Next.js · Nuxt · React · Vue · Angular · Svelte · Astro · Gatsby · Remix · Rails · Laravel · Django · ASP.NET · Express
**Infrastructure** Cloudflare · Fastly · Akamai · CloudFront · Vercel · Netlify · GitHub Pages · Nginx · Apache · IIS · LiteSpeed · Caddy
**Analytics** GA4 · GTM · Plausible · Fathom · Matomo · Hotjar · Clarity · Mixpanel · Amplitude · Segment · Adobe · PostHog
**Advertising** Google Ads · Meta Pixel · X Pixel · LinkedIn Insight · TikTok Pixel · Yahoo! JAPAN Ads · Criteo
**Payments** Stripe · PayPal · Square · Adyen
**Support** Intercom · Zendesk · Crisp · Drift · Tawk.to · Freshchat
**Consent / security** OneTrust · Cookiebot · Usercentrics · reCAPTCHA · hCaptcha · Turnstile

### How it works, and what it does not do

- **One request per site.** It fetches `robots.txt` and the homepage — nothing else.
  It does not crawl, does not follow internal links, and does not run JavaScript.
- **It reads cookie names, never cookie values.** No cookie contents are stored or reported.
- **It only looks at what the server volunteers**: response headers, the HTML it
  returns, and the URLs of assets that HTML references. Nothing is bypassed.
- **Because JavaScript is not executed**, a technology injected purely at runtime by
  another script may be missed. What is reported is what the initial response proves.

### Performance

Sites run through a fixed-size worker pool, so memory stays flat regardless of list
length, and HTML is capped per site. A typical site resolves in well under a second.

***

Built by [Ai-Q Labs](https://apify.com/aiqlabs). See also
[Bulk Domain Checker](https://apify.com/aiqlabs/bulk-domain-checker) for the DNS,
SSL and WHOIS layer of the same picture.

# Actor input Schema

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

Sites to inspect. Full URLs are accepted and reduced to the domain. One entry may contain several sites separated by spaces, commas or newlines, so pasting a spreadsheet column works.

## `respectRobots` (type: `boolean`):

Read robots.txt first and skip the site if this crawler is disallowed. Leave on unless you own the site.

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

Return the header, cookie name, asset URL or HTML fragment that proved each technology, so results can be verified.

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

How many sites to inspect at the same time.

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

Give up on a site after this many seconds.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "wordpress.org"
  ],
  "respectRobots": true,
  "includeEvidence": true,
  "maxConcurrency": 8,
  "requestTimeoutSecs": 15
}
```

# Actor output Schema

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

No description

## `csv` (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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("aiqlabs/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",
    ] }

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

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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"
  ]
}' |
apify call aiqlabs/tech-stack-detector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=aiqlabs/tech-stack-detector",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/3wz3r4WFwpHbxV6Ed/builds/HMBpuUsPPGRAoGNjH/openapi.json
