# Tech Stack Detector - BuiltWith & Wappalyzer Alternative (`psx/tech-stack-detector`) Actor

Detect CMS, frameworks, analytics, CDN and e-commerce on any website. 7,600+ fingerprints, versions, optional JS rendering. JSON output.

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

## Pricing

Pay per event

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 - 7,500+ technologies (BuiltWith / Wappalyzer alternative)

Find out what any website is built with: CMS, e-commerce platform, JavaScript frameworks, analytics, tag managers, CDN, hosting, web servers, payment providers, email and marketing tools, and more. Matching is done against **7,600+ community-maintained technology fingerprints** (HTML, script URLs, meta tags, HTTP headers, cookies, URL patterns, DNS records and JavaScript globals), with version detection, confidence scores and "implies" resolution (e.g. Next.js implies React).

Fast HTTP-only mode by default (one GET per URL), plus an optional **headless-browser mode** (`renderJs`) that executes JavaScript so client-rendered sites and JS globals (e.g. `__NEXT_DATA__`, `React.version`) are detected too.

### Use cases

- **Lead qualification and sales prospecting** - find all companies using Shopify, HubSpot, WooCommerce or a specific CMS, and filter by category.
- **Competitor research** - see which frameworks, analytics, A/B testing and marketing tools competitors use.
- **Agencies and web consultants** - audit client or prospect sites, spot outdated versions.
- **Market research and tech-adoption trends** - run thousands of domains and aggregate.
- **AI agents and MCP** - structured JSON output, one clear record per URL; call it from an AI agent through the Apify MCP server or API to answer "what is this site built with?".

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `urls` | string\[] | required | Up to 5,000 URLs or bare domains. |
| `renderJs` | boolean | `false` | Use headless Chromium; enables JS-global detection. Slower. |
| `concurrency` | integer | `10` | Parallel requests overall (max 2 per host; browser mode capped at 5). |
| `includeCategories` | string\[] | all | Only return technologies in these categories, e.g. `["CMS", "Ecommerce", "CDN"]`. |
| `respectRobots` | boolean | `true` | Skip pages disallowed by robots.txt. |

```json
{ "urls": ["wordpress.org", "https://nextjs.org"], "renderJs": false, "includeCategories": [] }
```

### Output

One dataset item per URL:

```json
{
  "url": "https://wordpress.org/",
  "finalUrl": "https://wordpress.org/",
  "status": 200,
  "technologies": [
    { "name": "WordPress", "categories": ["CMS", "Blogs"], "version": "7.2", "confidence": 100, "evidence": ["meta:generator"] },
    { "name": "PHP", "categories": ["Programming languages"], "version": null, "confidence": 100, "evidence": ["implied-by:WordPress"] },
    { "name": "Nginx", "categories": ["Web servers", "Reverse proxies"], "version": null, "confidence": 100, "evidence": ["header:server"] }
  ],
  "headersSummary": { "server": "nginx", "poweredBy": null, "contentType": "text/html; charset=UTF-8", "via": null, "cdnHints": [], "securityHeaders": ["strict-transport-security"] },
  "dns": { "cname": [], "mx": ["..."], "ns": ["..."], "txt": ["..."] },
  "title": "Blog Tool, Publishing Platform, and CMS – WordPress.org",
  "scannedAt": "2026-10-05T19:03:57.338Z",
  "error": null
}
```

`evidence` tells you why a technology was reported (`html`, `scriptSrc`, `scripts`, `meta:<name>`, `header:<name>`, `cookie:<name>`, `url`, `dns:<type>`, `js:<path>`, `dom`, or `implied-by:<tech>`). Technologies detected only through DNS TXT/MX records (e.g. "Google Workspace", "Atlassian Cloud") mean the organisation uses that service, not that the page itself loads it. Failed, blocked or robots-disallowed URLs produce an item with `error` set and are not charged.

### Pricing (pay per event)

| Event | When charged | Price |
|---|---|---|
| `apify-actor-start` | once per run | $0.005 |
| `url-scanned` | each URL successfully analysed (failed, blocked and robots-disallowed URLs are free) | $0.0025 (= $2.50 per 1,000 URLs) |

**Why this price:** HTTP-only detection costs us almost nothing in compute, and comparable tech-detector actors in the Store charge roughly $1.50-$10 per 1,000 sites. We sit in the middle but with 7,600 fingerprints, versions, confidence, DNS hints and optional JS rendering. Example: 1,000 domains = about $2.50, 10,000 domains = about $25. No monthly rental, no minimum.

### Politeness and limits

- Honest user agent: `TechStackDetector/0.1 (+https://apify.com; Apify actor; respects robots.txt)`.
- One page request per URL (plus robots.txt, and DNS lookups), 15 s timeout, 1 retry, max 2 concurrent requests per host.
- robots.txt is respected by default.
- SSRF protection: only http/https; localhost, `.local`/`.internal` hosts and private/reserved IPs (checked after DNS resolution, at connection time, and across redirects) are refused.
- Only the landing page is analysed (no crawling). Detection is based on what that page and its HTTP response reveal; sites behind bot protection may return a challenge page (you will usually still see the CDN/WAF).
- Max 5,000 URLs per run.

### Disclaimer

Results are best-effort heuristics and can contain false positives or negatives. Use responsibly and comply with the terms of the websites you scan and applicable law. This Actor does not bypass access controls.

### Credits and license

Technology fingerprints are from [enthec/webappanalyzer](https://github.com/enthec/webappanalyzer) (a community fork of the Wappalyzer fingerprint set), licensed under **GPL-3.0**; the license text is in `data/LICENSE-webappanalyzer`. This project (matcher and Actor code) is released under GPL-3.0-only accordingly. "Wappalyzer" and "BuiltWith" are trademarks of their respective owners; this Actor is not affiliated with them.

### FAQ

**How is this different from BuiltWith or Wappalyzer?**\
It uses the open community Wappalyzer-style fingerprint set (7,600+ technologies) and returns evidence per detection. You pay per URL instead of a monthly seat, and get JSON through the API.

**Does it detect client-side rendered sites?**\
Set `renderJs` to true. Default mode is one fast HTTP GET and misses JS-only technologies.

**Can I get a list of all sites using Shopify?**\
The Actor analyses URLs you provide. It does not discover sites. Feed it your own lead list and filter output by technology name.

**Am I charged for failed URLs?**\
No. Only successfully analysed URLs trigger `url-scanned`.

**Is it legal?**\
It reads public pages with a single normal request, identifies itself, and respects robots.txt by default. You are responsible for how you use the data.

### Part of the Site Audit Suite

Run the same list of domains through every audit:

- [Website Accessibility Audit (WCAG 2.2 + EAA)](https://apify.com/psx/accessibility-eaa-audit)
- [Security Headers + TLS Audit](https://apify.com/psx/security-headers-tls-audit)
- [Broken Link Checker + On-Page SEO Audit](https://apify.com/psx/broken-link-seo-audit)
- llms.txt Generator and Sitemap + robots.txt Analyzer (coming soon)

Tip: pipe one domain list into several actors with an Apify Task or the API and join the results by `url`.

### Development

```bash
npm install
npm run update-fingerprints     # download fingerprints into data/ (committed copy is included)
npm test                        # node:test unit tests (matcher, SSRF guard, robots, helpers)

## local run: put input in storage/key_value_stores/default/INPUT.json
mkdir -p storage/key_value_stores/default
echo '{"urls":["wordpress.org","nextjs.org"],"renderJs":false}' > storage/key_value_stores/default/INPUT.json
npm start                       # results in storage/datasets/default/
## or: npx apify-cli run         # same, via the Apify CLI
```

Browser mode locally needs Playwright's Chromium (`npx playwright install chromium`). Deploy (when an Apify account exists): `npx apify-cli login && npx apify-cli push`. The Dockerfile uses `apify/actor-node-playwright-chrome:22`.

# Actor input Schema

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

Websites to analyze (up to 5000). Bare domains like example.com are accepted.

## `renderJs` (type: `boolean`):

Use a headless Chromium browser to execute JavaScript and also detect JS globals. Slower; billed as an extra 'rendered-url' event.

## `concurrency` (type: `integer`):

Maximum parallel requests overall (max 2 per host is always enforced). Browser mode is capped at 5.

## `includeCategories` (type: `array`):

Optional list of category names, e.g. CMS, Ecommerce, Analytics, CDN, JavaScript frameworks. Empty = all.

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

Skip pages disallowed by robots.txt for this bot.

## `dnsLookups` (type: `boolean`):

Also query CNAME/MX/NS/TXT records to detect hosting, email and SaaS services (2 s timeout per lookup, cached per domain). Turn off for maximum speed.

## Actor input object example

```json
{
  "urls": [
    "https://wordpress.org",
    "https://nextjs.org"
  ],
  "renderJs": false,
  "concurrency": 10,
  "respectRobots": true,
  "dnsLookups": true
}
```

# 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://wordpress.org",
        "https://nextjs.org"
    ]
};

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

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

```

## MCP server setup

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