# Website Tech Stack Detector: Technology Lookup for Any Domain (`opendata-feeds/website-tech-stack-detector`) Actor

Find the CMS, ecommerce platform, analytics, frameworks, CDN and 7,000+ other technologies behind any list of websites. One polite request per site, robots.txt respected, versions and categories included, change-monitor mode. $2 per 1,000 websites.

- **URL**: https://apify.com/opendata-feeds/website-tech-stack-detector.md
- **Developed by:** [OpenData Feeds](https://apify.com/opendata-feeds) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 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.

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: technology lookup for any list of domains

Give it a list of websites. Get back the technologies each one runs on: **CMS, ecommerce platform, analytics and tag managers, JavaScript frameworks, web server, CDN and hosting, payment and marketing tools**, with versions where the site reveals them.

- **7,000+ technologies** recognized, from open fingerprint rules, grouped in categories (CMS, Ecommerce, Analytics, JavaScript frameworks, CDN, and more).
- **One polite request per website.** The Actor reads the homepage the way a browser's first visit does, plus `robots.txt`. No crawling, no proxies, no login.
- **Respects robots.txt.** A site that disallows its homepage to this Actor (or to all bots) is skipped, reported, and not charged.
- **Versions, categories and a confidence score** for every technology found.
- **Change monitor.** Schedule it, and it returns (and charges for) only websites whose technology stack changed since the last run, with what was added and removed.
- **$2.00 per 1,000 websites.** Failed, blocked and unchanged websites cost nothing.

#### Who uses a tech stack lookup

- **Sales and lead-generation teams** qualifying accounts by stack ("runs WooCommerce", "uses HubSpot").
- **Agencies** finding sites on an old CMS version or a platform they migrate from.
- **SaaS companies** sizing a market of sites that use a competitor or a complementary tool.
- **Analysts and investors** tracking technology adoption across a list of companies.

#### Input

| Field | What it does |
|---|---|
| `websites` (required) | Domains or URLs: `example-shop.com`, `https://www.example-shop.com`. A bare domain is checked at its homepage over HTTPS. Duplicates are removed. |
| `maxSites` | Check only the first N websites. Default 1,000; 0 = no limit. |
| `onlyChanged` + `stateKey` | Monitor mode: return only websites seen for the first time or whose technologies changed since the last run with the same `stateKey`. |
| `minConfidence` | Drop detections below this confidence (0–100). Default 0 keeps everything. |

Example:

```json
{
  "websites": ["example-shop.com", "northwind-traders.example", "https://www.acme-robotics.example"],
  "onlyChanged": true,
  "stateKey": "weekly-prospects"
}
```

#### Output

One item per website. Example (fictional company):

```json
{
  "website": "https://example-shop.com/",
  "domain": "example-shop.com",
  "finalUrl": "https://www.example-shop.com/",
  "statusCode": 200,
  "technologyCount": 8,
  "technologyNames": [
    "Google Analytics",
    "Google Tag Manager",
    "jQuery",
    "MySQL",
    "Nginx",
    "PHP",
    "WooCommerce",
    "WordPress"
  ],
  "categories": [
    "Analytics",
    "Blogs",
    "CMS",
    "Databases",
    "Ecommerce",
    "JavaScript libraries",
    "Programming languages",
    "Reverse proxies",
    "Tag managers",
    "Web servers",
    "WordPress plugins"
  ],
  "technologies": [
    {"name": "Google Analytics", "version": "GA4", "confidence": 100, "categories": ["Analytics"], "website": "https://google.com/analytics", "detectedBy": ["scriptSrc", "scripts"]},
    {"name": "Google Tag Manager", "version": null, "confidence": 100, "categories": ["Tag managers"], "website": "https://www.google.com/tagmanager", "detectedBy": ["scriptSrc"]},
    {"name": "jQuery", "version": null, "confidence": 100, "categories": ["JavaScript libraries"], "website": "https://jquery.com", "detectedBy": ["scriptSrc"]},
    {"name": "MySQL", "version": null, "confidence": 100, "categories": ["Databases"], "website": "https://mysql.com", "detectedBy": ["implied"], "impliedBy": "WordPress"},
    {"name": "Nginx", "version": "1.25.3", "confidence": 100, "categories": ["Web servers", "Reverse proxies"], "website": "https://nginx.org/en", "detectedBy": ["headers"]},
    {"name": "PHP", "version": "8.2.12", "confidence": 100, "categories": ["Programming languages"], "website": "https://php.net", "detectedBy": ["headers"]},
    {"name": "WooCommerce", "version": "8.5.1", "confidence": 100, "categories": ["Ecommerce", "WordPress plugins"], "website": "https://woocommerce.com", "detectedBy": ["meta"]},
    {"name": "WordPress", "version": "6.4.2", "confidence": 100, "categories": ["CMS", "Blogs"], "website": "https://wordpress.org", "detectedBy": ["dom", "html", "meta", "scriptSrc"]}
  ],
  "change": {
    "status": "changed",
    "added": [
      "WooCommerce"
    ],
    "removed": [
      "Magento"
    ]
  },
  "checkedAt": "2026-10-30T10:23:20.206Z"
}
```

`detectedBy` says what gave the technology away: `headers`, `cookies`, `meta`, `scriptSrc`, `scripts`, `dom`, `html`, `css`, `text`, `url`, `robots`, or `implied` (one technology implies another, for example WordPress implies PHP). `change` is `null` unless monitor mode is on.

The output holds technology data only. The Actor never returns page text, email addresses, phone numbers or names.

Export as JSON, CSV, Excel or HTML, or call it from the API, Make, Zapier, n8n or an AI agent (MCP).

A `SUMMARY` record lists how many websites were analyzed, delivered and unchanged, and every website that failed or was skipped, with the reason (`domain not found (DNS)`, `homepage returned HTTP 403`, `blocked by robots.txt`, `timed out`, ...).

#### Pricing

**Pay per event: $0.002 per website analyzed ($2.00 per 1,000 websites).**

| You run | You pay |
|---|---|
| 100 websites, once | $0.20 |
| 5,000 prospect domains, once | $10 |
| 2,000 websites, weekly monitor, ~3% change each week | $4 for the first run, then ≈ $0.12 a week |

Websites that fail, are blocked by robots.txt, or are unchanged in monitor mode are not charged. Set **Maximum cost per run** in the run options to cap spend; the Actor checks only as many websites as your limit allows, stops cleanly, and says so in the log and `SUMMARY`. Apify's free plan includes $5 of monthly usage, enough for about 2,500 websites.

#### Limits

- **Plain HTTP, no browser.** The Actor reads the HTML, headers and cookies that the homepage returns. Technologies that only appear after JavaScript runs (some single-page apps, tags loaded by a tag manager, client-side chat widgets) can be missed. Rules that need a browser (JavaScript variables, network requests) or extra lookups (DNS, TLS certificate) are not used.
- **Homepage only.** One page per website, so tools used only on a checkout or blog subpage may not show. You can pass a specific URL instead of a domain.
- **robots.txt is respected.** Websites that disallow this Actor are skipped and listed in `SUMMARY.failed` as `blocked by robots.txt`. If `robots.txt` answers with a server error, the website is skipped too, as the robots.txt standard (RFC 9309) requires.
- **Bot protection.** Sites that answer automated requests with an error or a challenge page are reported as failed, not guessed at.
- **Confidence below 100** means a weaker signal; use `minConfidence` to filter.

#### Source and attribution

Detection uses the open-source [webappanalyzer](https://github.com/enthec/webappanalyzer) fingerprint rules by Enthec and contributors, licensed under the [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html), at a pinned version. The rules are run, unmodified, by this Actor; they are not distributed with its output. Technology names are the property of their owners, and listing a technology implies no affiliation.

The Actor identifies itself with the User-Agent `website-tech-stack-detector/0.1`, so site owners can allow or block it in `robots.txt`.

#### FAQ

**Why is a technology I know the site uses missing?** It is probably added by JavaScript after the page loads, or used only on another page. See Limits.

**Why is `version` empty?** Most sites don't reveal versions. When a meta tag, header or script URL carries one, it is reported.

**Can I check a specific page instead of the homepage?** Yes: pass the full URL.

**Something wrong or a technology missing?** Open an issue on the Issues tab with the website and what you expected. Issues are answered within 24 hours.

# Actor input Schema

## `websites` (type: `array`):

Domains or URLs (example-shop.com, https://www.example-shop.com). A bare domain is checked at its homepage over HTTPS.

## `maxSites` (type: `integer`):

Only the first N websites (after removing duplicates) are checked. 0 means no limit. Use the run's maximum-cost setting to cap spend overall.

## `onlyChanged` (type: `boolean`):

For scheduled runs: remember each website's technologies and return (and charge for) only websites seen for the first time or whose technology list changed since the last run of the same monitor.

## `stateKey` (type: `string`):

Name for the change-monitor memory, so different schedules keep separate histories.

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

Drop technologies detected with lower confidence. 0 keeps every detection; 100 keeps only certain ones.

## Actor input object example

```json
{
  "websites": [
    "wordpress.org",
    "nodejs.org"
  ],
  "maxSites": 1000,
  "onlyChanged": false,
  "stateKey": "default",
  "minConfidence": 0
}
```

# Actor output Schema

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

Websites and their technologies, one item per charged event, in the default dataset.

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

Counts for the run (found, delivered, skipped, errors, spending-limit stop) in the SUMMARY record.

# 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 = {
    "websites": [
        "wordpress.org",
        "nodejs.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("opendata-feeds/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 = { "websites": [
        "wordpress.org",
        "nodejs.org",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("opendata-feeds/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 '{
  "websites": [
    "wordpress.org",
    "nodejs.org"
  ]
}' |
apify call opendata-feeds/website-tech-stack-detector --silent --output-dataset

```

## MCP server setup

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