# Tech Stack Detector - Website Technology Lookup (`roundish_wildlife/website-tech-stack-detector`) Actor

Find out which technologies any website uses: CMS, ecommerce platform, frameworks, analytics, marketing tools, payments, CDN and hosting. 3,500+ fingerprints, bulk URLs, emails and social links for lead lists. $0.004 per analysed URL, failed URLs are free.

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

## Pricing

from $4.00 / 1,000 website 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

## Tech Stack Detector - Website Technology Lookup

Find out **which technologies any website is built with**, in bulk, for **$0.004 per website**. Paste a list of URLs or domains and get one clean row per site with its CMS, ecommerce platform, JavaScript frameworks, analytics and marketing tools, payment providers, CDN, hosting, web server and programming language, including versions where the site exposes them.

- 🔍 **3,500+ technology fingerprints** across 100+ categories (WordPress, Shopify, Wix, Webflow, Next.js, React, Google Analytics 4, Meta/Facebook Pixel, Klaviyo, HubSpot, Stripe, Cloudflare, Vercel and thousands more)
- ⚡ **Fast and light**: plain HTTP, no headless browser. Hundreds of sites per minute on 256 MB of memory
- 🛡️ **Reliable**: automatic `www.` / `http://` / expired-certificate fallbacks, one retry for flaky connections and an optional proxy retry for sites that block bots. One broken site never breaks your run
- 💸 **Failed websites are free**: you are only charged for websites that were actually analysed
- 📇 **Lead data included**: page title, description, language, email addresses and social profiles from the homepage

### What can you use it for?

- **Lead generation**: build lists of stores running Shopify, WooCommerce or Magento, or companies using a competitor's tool (for example everyone with Intercom or Drift), and get their emails and social profiles in the same run.
- **Sales prospecting and qualification**: enrich your CRM accounts with their tech stack before outreach. "Uses HubSpot + Stripe + Next.js" tells you a lot about budget, maturity and fit.
- **Competitor research**: see which analytics, A/B testing, chat, payment and hosting tools your competitors rely on, and spot changes over time with scheduled runs.
- **Market research**: measure the market share of platforms or tools across a list of thousands of sites (the run summary already counts the top technologies).
- **Agencies and developers**: audit a client's site in seconds, find the CMS before a migration quote, or find every site still on an old jQuery or PHP version.
- **Security and IT asset inventory**: list servers, frameworks and versions exposed by your own domains.

### How it works

1. Each website's page is fetched once over plain HTTP (no browser), following redirects.
2. The response **headers, cookies, HTML, meta tags, script URLs, inline scripts, styles, page text and (optionally) robots.txt** are matched against an open-source fingerprint database of 3,500+ technologies, plus our own curated fingerprints for modern stacks (Next.js, Nuxt, SvelteKit, Astro, Remix, GA4, Segment, Plausible, Hotjar, Intercom and more).
3. Related technologies are resolved automatically: WordPress implies PHP and MySQL, Next.js implies React and Node.js, and plugins such as WooCommerce are only reported when WordPress is present.
4. You get one dataset row per website, and a run summary with the most common technologies.

**If a site fails**, the Actor tries harder before giving up: for a bare domain it also tries `www.` and `http://`, it accepts sites with expired or self-signed certificates, retries once after a dropped connection, and (if you enable a proxy) retries once through Apify Proxy when the site blocks the request. Whatever still fails gets a row with a clear `error` message, and **is not charged**.

### Input

Only one of `startUrls` or `domains` is needed. Everything else has sensible defaults.

| Field | Default | Description |
|---|---|---|
| `startUrls` | - | Full URLs (`https://www.example.com/shop`). You can upload a CSV/TXT file in the Console |
| `domains` | - | Plain domains, one per line (`shopify.com`, `example.co.uk`) |
| `extractContacts` | `true` | Emails and social profile links from the page |
| `includeEvidence` | `false` | Adds an `evidence` list per technology explaining why it was detected |
| `minConfidence` | `0` | Hide detections below this confidence (0-100) |
| `fetchRobotsTxt` | `false` | Use `/robots.txt` as an extra signal |
| `maxConcurrency` | `10` | Websites analysed in parallel (1-50) |
| `requestTimeoutSecs` | `20` | Per-site timeout |
| `followRedirects` | `true` | Analyse the final page after redirects |
| `proxyConfiguration` | off | Used **only as a retry** for sites that block or cannot be reached directly |

#### Example input

```json
{
    "domains": ["allbirds.com", "gymshark.com", "vercel.com", "wordpress.org"],
    "startUrls": [{ "url": "https://www.example.com/shop" }],
    "extractContacts": true,
    "includeEvidence": false,
    "maxConcurrency": 20
}
```

### Output

One row per website. Example (shortened to 4 of 7 technologies, with `includeEvidence: true`):

```json
{
    "url": "https://fjordcandles.example/",
    "input": "fjordcandles.example",
    "domain": "fjordcandles.example",
    "finalUrl": "https://www.fjordcandles.example/",
    "statusCode": 200,
    "success": true,
    "technologyCount": 7,
    "technologyNames": ["Shopify", "Cloudflare", "Google Tag Manager", "Hotjar", "Klaviyo", "TikTok Pixel", "Open Graph"],
    "technologies": [
        {
            "name": "Shopify",
            "category": "Ecommerce",
            "categories": ["Ecommerce"],
            "version": null,
            "confidence": 100,
            "website": "http://shopify.com",
            "evidence": ["header x-shopid: 12345678", "header powered-by: Shopify"]
        },
        {
            "name": "Cloudflare",
            "category": "CDN",
            "categories": ["CDN"],
            "version": null,
            "confidence": 100,
            "website": "http://www.cloudflare.com",
            "evidence": ["header server: cloudflare", "header cf-ray: 8a1b2c3d4e5f6a7b-ARN"]
        },
        {
            "name": "Google Tag Manager",
            "category": "Tag managers",
            "categories": ["Tag managers"],
            "version": null,
            "confidence": 100,
            "website": "http://www.google.com/tagmanager",
            "evidence": ["inline script googletagmanager.com/gtm.js"]
        },
        {
            "name": "Hotjar",
            "category": "Analytics",
            "categories": ["Analytics"],
            "version": null,
            "confidence": 100,
            "website": "https://www.hotjar.com",
            "evidence": ["inline script static.hotjar.com/c/hotjar-"]
        }
    ],
    "categories": {
        "Analytics": ["Hotjar", "TikTok Pixel"],
        "CDN": ["Cloudflare"],
        "Ecommerce": ["Shopify"],
        "Marketing automation": ["Klaviyo"],
        "Miscellaneous": ["Open Graph"],
        "Tag managers": ["Google Tag Manager"]
    },
    "title": "Fjord Candles",
    "metaDescription": "Hand-poured soy candles inspired by Norwegian fjords.",
    "language": "en",
    "emails": [],
    "socialLinks": {
        "instagram": "https://www.instagram.com/fjordcandles",
        "tiktok": "https://www.tiktok.com/@fjordcandles",
        "pinterest": "https://www.pinterest.com/fjordcandles/"
    },
    "server": "cloudflare",
    "responseTimeMs": 412,
    "fetchedVia": "direct",
    "error": null,
    "analyzedAt": "2026-10-09T20:30:15Z"
}
```

- `technologies` are sorted from the most defining categories (CMS, ecommerce) to the most generic. `category` is the main category; `categories` lists all of them.
- `version` is filled when the site exposes it (for example `WordPress 6.4.3`, `PHP 8.2.10`, `Angular 17.1.2`, `Google Analytics` → `GA4`).
- `confidence` is 0-100. Most detections are 100; technologies inferred from another one ("implied") inherit its confidence.
- Failed websites have `success: false` and an `error` such as `DNS lookup failed (domain does not resolve)`, `Timed out after 20 s` or `HTTP 403 Forbidden. The site blocked the request; enable a proxy in the input to retry through Apify Proxy.` If the site answered with an error page, technologies visible in its headers (for example Cloudflare) are still listed.
- The dataset has three views in the Console: **Overview**, **Technologies by category** and **Leads (contacts)**. Export to CSV, Excel, JSON or connect it to Make, Zapier, n8n, Google Sheets or your CRM.

A run summary is saved as `OUTPUT` in the key-value store: number of websites analysed and failed, events charged, the 25 most common technologies, and the list of errors.

### Pricing

This Actor uses **pay-per-event** pricing:

| Event | Price | When |
|---|---|---|
| `url-analyzed` | **$0.004** ($4 per 1,000 websites) | A website was fetched and analysed successfully |
| Actor start | Apify default | Once per run |

- 100 websites = **$0.40**
- 1,000 websites = **$4**
- 10,000 websites = **$40**

That is up to **25x cheaper** than other tech-stack lookup Actors that charge around $0.10 per URL. You are **not charged** for websites that fail (DNS errors, timeouts, blocked requests, non-HTML responses), for duplicates in your input, or for the extra fallback and proxy retries. Set **Maximum cost per run** in the run options and the Actor stops cleanly when the budget is used up; failed websites never use up your budget.

### FAQ

**How accurate is it?**
Detection uses the same kind of fingerprints that popular browser extensions use (headers, cookies, meta tags, script URLs, HTML patterns, CSS selectors). Turn on `includeEvidence` to see exactly why each technology was reported.

**Why is a technology I know about missing?**
This Actor does not run a browser, so tools that only appear after JavaScript runs in the visitor's browser, and do not leave a trace in the HTML, headers or cookies, can be missed. Single-page apps that render everything client-side expose fewer clues. Only the page you enter is analysed (usually the homepage); tools used only on checkout or other pages are not seen.

**A site returns 403 or "blocked". What can I do?**
Enable **Proxy (fallback only)** in the input. Blocked sites are then retried once through Apify Proxy (Datacenter by default; choose RESIDENTIAL for the strictest sites). Sites that still block are not charged.

**Can I analyse thousands of websites?**
Yes. Up to 50,000 URLs per run; use `maxConcurrency` 20-50 for big lists. Split larger lists into several runs.

**Does it find emails?**
It collects email addresses and social profile links that appear on the analysed page itself (mailto links and visible text). It does not crawl other pages or guess emails.

**Can I call it from my code or no-code tools?**
Yes, through the Apify API, the Python and JavaScript clients, or integrations such as Make, Zapier, n8n and Google Sheets.

### Limits

- One page per website (the URL you enter, after redirects). Pages larger than 4 MB are truncated.
- No JavaScript execution: about 300 of the 3,500+ fingerprints can only be seen in a browser and are not detected.
- The fingerprint database is based on the last MIT-licensed release of the Wappalyzer data (January 2023) plus our own curated additions. Very new tools may be missing; tell us in the Issues tab and we will add them.
- Private and internal addresses (localhost, 10.x, 192.168.x and similar) are rejected.

### Is it legal?

The Actor reads only **public web pages and HTTP headers** that any visitor's browser receives, once per website. It does not log in or bypass paywalls. Email addresses and social links are personal data in some cases: make sure your use (for example cold outreach) complies with GDPR, CAN-SPAM and other applicable laws. Read more in Apify's post [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/).

### Credits

Technology fingerprints and categories are derived from the open-source [Wappalyzer](https://github.com/wappalyzer/wappalyzer) data, version 6.10.54, released under the MIT License (see `LICENSE-wappalyzer.txt` in the source data folder). This Actor is not affiliated with or endorsed by Wappalyzer or any of the technology vendors it detects; all product names are trademarks of their respective owners.

# Changelog

This Actor's version history is a separate document: https://apify.com/roundish_wildlife/website-tech-stack-detector/changelog.md

# Actor input Schema

## `startUrls` (type: `array`):

Full URLs to analyse, e.g. https://webflow.com. You can also upload a CSV or text file with one URL per line. The exact page you enter is analysed (usually the homepage).

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

Plain domains such as shopify.com or example.co.uk, one per line. The homepage is fetched over HTTPS; if the bare domain does not respond, the Actor automatically tries www. and http:// before giving up. Combine with 'Website URLs' freely; duplicates are removed.

## `extractContacts` (type: `boolean`):

Also collect email addresses and social profile links (Facebook, Instagram, X/Twitter, LinkedIn, YouTube, TikTok, Pinterest, GitHub, Threads) found on the analysed page. Useful for lead lists. Free.

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

Add an 'evidence' list to every technology showing why it was detected (e.g. 'header server: cloudflare' or 'meta generator=WordPress 6.4'). Handy for verification; makes the output larger.

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

Only report technologies detected with at least this confidence. Most detections are 100%. Raise to 50 or more to drop weaker, single-hint matches.

## `fetchRobotsTxt` (type: `boolean`):

Fetch /robots.txt as an extra signal (helps identify some CMS and shop platforms). Adds one small request per website; no extra charge.

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

How many websites are analysed in parallel. 10-20 is a good default; the Actor stays well within 256-1024 MB of memory.

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

Maximum time to wait for a website to respond. Slow sites that exceed it are reported with an error (and not charged).

## `followRedirects` (type: `boolean`):

Follow HTTP redirects (e.g. example.com -> www.example.com/en/) and analyse the final page. Turn off to analyse only the first response.

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

Every website is first fetched directly (fast and free). If a site blocks the request (e.g. 403/429) or cannot be reached, it is retried once through the proxy you choose here. Leave off unless you analyse sites behind strict bot protection.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://wordpress.org"
    },
    {
      "url": "https://webflow.com"
    }
  ],
  "domains": [
    "vercel.com",
    "squarespace.com"
  ],
  "extractContacts": true,
  "includeEvidence": false,
  "minConfidence": 0,
  "fetchRobotsTxt": false,
  "maxConcurrency": 10,
  "requestTimeoutSecs": 20,
  "followRedirects": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        {
            "url": "https://wordpress.org"
        },
        {
            "url": "https://webflow.com"
        }
    ],
    "domains": [
        "vercel.com",
        "squarespace.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("roundish_wildlife/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 = {
    "startUrls": [
        { "url": "https://wordpress.org" },
        { "url": "https://webflow.com" },
    ],
    "domains": [
        "vercel.com",
        "squarespace.com",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("roundish_wildlife/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 '{
  "startUrls": [
    {
      "url": "https://wordpress.org"
    },
    {
      "url": "https://webflow.com"
    }
  ],
  "domains": [
    "vercel.com",
    "squarespace.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call roundish_wildlife/website-tech-stack-detector --silent --output-dataset

```

## MCP server setup

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