# Website Tech Stack Detector & Technology Lookup (`wrightyyyy/website-technology-detector`) Actor

For sales and lead-generation teams who filter prospects by tech stack: give it company websites, get one row per site with its CMS, e-commerce platform, analytics, CRM and frameworks, ready for Google Sheets, a CRM or n8n. Pay only for sites that answer; no start fee.

- **URL**: https://apify.com/wrightyyyy/website-technology-detector.md
- **Developed by:** [Alexander Wright](https://apify.com/wrightyyyy) (community)
- **Features:** 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 url 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 & Technology Lookup

**For sales and lead-generation teams who filter prospects by their tech stack.** Give it a list of company websites and get one row per site: its CMS, e-commerce platform, analytics, tag manager, marketing automation, CRM, frameworks, web server, CDN and hosting, ready to load into Google Sheets, your CRM or n8n.

Use it to find every Shopify store in a lead list, every prospect still on WordPress, every site without analytics, or to qualify accounts before outreach.

### What 1,000 sites cost

Pay per event, **only for sites that answer**: **$0.002 per site analysed, $2.00 per 1,000 sites**. No start fee, no monthly rental.

A site is charged only when its final response is 2xx. Sites that time out, don't resolve, block the request (403) or return an error still get a row with their status, and cost nothing. Duplicates in your list (`example.com`, `https://www.example.com/`, `http://example.com`) are analysed and charged once.

In a local test run over 1,000 mid-ranked domains (Tranco ranks 10,001 to 11,000, 9 November 2026), 625 answered with a page and would have been charged: $1.25. The other 375 cost nothing.

### Does it still work?

- Apify runs this Actor every day on its default input (Shopify, WordPress and Next.js sites) and labels it **Under maintenance** if most test runs over three days fail.
- Every push to the code is tested against those three sites: WordPress must be found on wordpress.org, Next.js and React on nextjs.org, Shopify on www.shopify.com, and only sites that returned a page may be charged.
- Detection uses 7,695 technologies in 109 categories from the open [webappanalyzer](https://github.com/enthec/webappanalyzer) fingerprint set (the community continuation of Wappalyzer's fingerprints), commit of 3 November 2026, plus this Actor's own Next.js patterns (`data/local-fingerprints.json`).
- Every input has a default, so an empty input `{}` runs and returns results.

### Will I get blocked or sued?

- **One HTTP GET per site** (following redirects), to its public home page, with browser-like headers. No login, no browser automation, no proxy, no crawling beyond the home page.
- The output is technical data about websites (technology names, categories, versions). It collects no personal data, emails or contacts.
- Some sites behind bot protection refuse the request, usually with 403 (93 of the 1,000 test domains). Those get a row with their status code and are not charged; there is no retry or evasion. A challenge page served with a 2xx status is charged like any page.
- You are responsible for how you use the results and for the lists you submit.

### How do I get it into my tool?

Each run's dataset has one item per site. These flat columns load as they are:

`url, domain, finalUrl, statusCode, technologyCount, technologyNames, cms, ecommerce, analytics, tagManagers, advertising, marketingAutomation, crm, liveChat, paymentProcessors, javascriptFrameworks, webFrameworks, programmingLanguages, webServers, cdn, hosting, fetchedAt, error`

Each category column lists that site's technologies in the category, comma-separated, or is empty. `domain` is the host after redirects, without `www.`: use it to match rows to accounts in a CRM. Different inputs can redirect to the same domain (36 of the 1,000 test rows), so `url` ties a row back to the list you submitted.

- **CSV for Google Sheets, Excel or a CRM import:** export the dataset as CSV and leave out the nested `technologies` field, for example with the API:
  `https://api.apify.com/v2/datasets/<datasetId>/items?format=csv&omit=technologies&token=<your token>`
  Each site is then one row with the columns above.
- **n8n, Make or Zapier:** run the Actor with Apify's integration for that tool ([n8n](https://docs.apify.com/integrations/n8n), [Make](https://docs.apify.com/integrations/make), [Zapier](https://docs.apify.com/integrations/zapier)) and read the dataset items; use `domain` and the category columns directly.
- **JSON with full detail:** the nested `technologies` field keeps every detection with its categories, version and confidence.

### Input

| Field | Default | Description |
| --- | --- | --- |
| `urls` | the three sites above | Home pages to analyse. `example.com` is read as `https://example.com`. Duplicates are removed. |
| `categories` | `[]` (all) | Keep only detections in these categories, for example `CMS`, `Ecommerce`, `Analytics`. |
| `minConfidence` | `50` | Keep only detections at or above this confidence (0-100). |

```json
{ "urls": ["https://www.shopify.com", "https://wordpress.org", "https://nextjs.org"], "categories": [], "minConfidence": 50 }
```

### Sample dataset

From a real run of the input above (9 November 2026), as CSV without `technologies`, empty category columns left out here for width:

| domain | statusCode | technologyCount | cms | ecommerce | tagManagers | javascriptFrameworks | webFrameworks | programmingLanguages | webServers | cdn | hosting |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| nextjs.org | 200 | 8 | | | | Next.js, React | Next.js | | Next.js | | Vercel |
| shopify.com | 200 | 8 | | Cart Functionality, Shopify | | | | | | Cloudflare | |
| wordpress.org | 200 | 13 | WordPress | | Google Tag Manager | | | PHP | Nginx | | |

One item in full (technologies shortened to three of thirteen):

```json
{
  "url": "https://wordpress.org",
  "domain": "wordpress.org",
  "finalUrl": "https://wordpress.org/",
  "statusCode": 200,
  "technologyCount": 13,
  "technologyNames": "Google Font API, Google Tag Manager, Gutenberg, HSTS, MySQL, Nginx, Open Graph, PHP, Priority Hints, RSS, WordPress, WordPress Block Editor, WordPress Site Editor",
  "cms": "WordPress",
  "ecommerce": "",
  "analytics": "",
  "tagManagers": "Google Tag Manager",
  "advertising": "",
  "marketingAutomation": "",
  "crm": "",
  "liveChat": "",
  "paymentProcessors": "",
  "javascriptFrameworks": "",
  "webFrameworks": "",
  "programmingLanguages": "PHP",
  "webServers": "Nginx",
  "cdn": "",
  "hosting": "",
  "technologies": [
    { "name": "Gutenberg", "categories": ["WordPress plugins", "Editors"], "confidence": 100, "version": "24.3.1" },
    { "name": "PHP", "categories": ["Programming languages"], "confidence": 100, "version": null },
    { "name": "WordPress", "categories": ["CMS", "Blogs"], "confidence": 100, "version": "7.2" }
  ],
  "fetchedAt": "2026-11-09T14:49:18.531Z",
  "error": null
}
```

`statusCode` is the final HTTP status after redirects, or `null` with an `error` message when no response came (DNS failure, timeout, refused connection, certificate error).

### How it works

- Matches the page URL, response headers, cookies, HTML, body text, meta tags, script URLs, inline scripts, inline styles and DOM selectors against the fingerprints, then adds implied technologies (Next.js implies React, WordPress implies PHP).
- Technologies are listed by confidence, then name, with the fingerprint set's own names and categories.
- In the local test on a home connection, 1,000 domains took 7.5 minutes at 5 sites at a time. A site that never answers waits up to 10 seconds to connect and 30 seconds for a response. Run time on Apify will differ.

### Limits

- Detection reads only what the home page response exposes. A technology loaded later by JavaScript, or used only on other pages, can be missed.
- Sites that answer only to a real browser are usually reported with their 4xx status and not charged.

### Fingerprint data and licence

Technology fingerprints come from [enthec/webappanalyzer](https://github.com/enthec/webappanalyzer), licensed under the GNU General Public License v3.0. The upstream commit used and the full licence text ship with the Actor in `data/fingerprints/` (`SOURCE.json`, `LICENSE`); see `THIRD-PARTY-NOTICES.md`.

# Actor input Schema

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

Home pages to analyse; one HTTP fetch each, no browser. Duplicates (same site with or without www, http or a trailing slash) are analysed and charged once.

## `categories` (type: `array`):

Keep detections in these fingerprint categories (e.g. CMS, Ecommerce, Analytics). Empty keeps all.

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

Keep only detections at or above this confidence (0-100).

## Actor input object example

```json
{
  "urls": [
    "https://www.shopify.com",
    "https://wordpress.org",
    "https://nextjs.org"
  ],
  "categories": [],
  "minConfidence": 50
}
```

# Actor output Schema

## `results` (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 = {
    "urls": [
        "https://www.shopify.com",
        "https://wordpress.org",
        "https://nextjs.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("wrightyyyy/website-technology-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": [
        "https://www.shopify.com",
        "https://wordpress.org",
        "https://nextjs.org",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("wrightyyyy/website-technology-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": [
    "https://www.shopify.com",
    "https://wordpress.org",
    "https://nextjs.org"
  ]
}' |
apify call wrightyyyy/website-technology-detector --silent --output-dataset

```

## MCP server setup

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