# Domain Tech Stack Detector (`emperor1978/tech-stack-detector`) Actor

Detect the technology stack of any website. Identifies frameworks (React, Vue, Angular), CMS (WordPress, Shopify), analytics (Google Analytics), CDN (Cloudflare), and more. Analyze single domains or bulk lists. Great for competitive analysis, lead generation, and market research.

- **URL**: https://apify.com/emperor1978/tech-stack-detector.md
- **Developed by:** [The Emperor](https://apify.com/emperor1978) (community)
- **Categories:** SEO tools
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 domain 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

## Domain Tech Stack Detector

Analyze any website and discover its full technology stack in seconds. The actor fetches a page, inspects its HTML source and HTTP response headers, and returns a structured JSON record containing every detected technology grouped by category — no browser rendering required.

***

### What it detects

| Category | Technologies (sample) |
|---|---|
| Web Framework | React, Vue.js, Angular, Next.js, Nuxt.js, Svelte/SvelteKit, Django, Ruby on Rails, Laravel, Express.js, FastAPI, Spring, ASP.NET, Remix, Gatsby |
| CMS | WordPress, Shopify, Wix, Squarespace, Webflow, Ghost, Drupal, Joomla, HubSpot CMS |
| Analytics | Google Analytics GA4/UA, Plausible, Fathom, Mixpanel, Segment, Hotjar, FullStory, PostHog, Amplitude, Heap |
| CDN / Hosting | Cloudflare, AWS CloudFront, Vercel, Netlify, Fastly, Akamai, Google Cloud CDN, GitHub Pages, Render |
| JavaScript Libraries | jQuery, Lodash, Moment.js, D3.js, Three.js, Chart.js, GSAP, Axios, Alpine.js, htmx |
| CSS Frameworks | Tailwind CSS, Bootstrap, Bulma, Material UI, Chakra UI, Foundation |
| Marketing / Chat | Intercom, Drift, HubSpot Chat, Crisp, Zendesk, LiveChat, Tawk.to, Freshchat |
| Payment | Stripe, PayPal, Braintree, Square, Paddle |
| Email / Newsletter | Mailchimp, ConvertKit, SendGrid, Klaviyo, Beehiiv |
| Advertising | Google Ads, Facebook Pixel, LinkedIn Insight Tag, Twitter/X Pixel, TikTok Pixel |
| Tag Managers | Google Tag Manager, Tealium |
| Security / CAPTCHA | Google reCAPTCHA, hCaptcha, Cloudflare Turnstile |
| Search | Algolia, Elasticsearch |
| A/B Testing | Optimizely, VWO, LaunchDarkly |
| Error Monitoring | Sentry, Datadog RUM, LogRocket |
| Marketing Automation | Salesforce Marketing Cloud, Marketo, Pardot |

**80+ technology signatures** across 16 categories.

***

### Input schema

| Field | Type | Default | Description |
|---|---|---|---|
| `urls` | string\[] | **required** | Full URLs or bare domains (`example.com` is auto-prefixed with `https://`) |
| `follow_redirects` | boolean | `true` | Follow HTTP 3xx redirects and record the final URL |
| `timeout_seconds` | integer | `30` | Per-URL fetch timeout (5–120 s) |
| `include_raw_evidence` | boolean | `false` | Attach raw HTML/header snippets that triggered each match |

#### Example input

```json
{
  "urls": [
    "https://vercel.com",
    "stripe.com",
    "https://ghost.org"
  ],
  "follow_redirects": true,
  "timeout_seconds": 30,
  "include_raw_evidence": false
}
```

***

### Output format

One dataset record per URL:

```json
{
  "url": "https://vercel.com",
  "final_url": "https://vercel.com/",
  "status_code": 200,
  "technologies": [
    {
      "name": "Next.js",
      "category": "Web Framework",
      "website": "https://nextjs.org",
      "confidence": 0.99,
      "evidence": "[header] …x-powered-by: Next.js…"
    },
    {
      "name": "React",
      "category": "Web Framework",
      "website": "https://reactjs.org",
      "confidence": 0.95
    },
    {
      "name": "Vercel",
      "category": "CDN/Hosting",
      "website": "https://vercel.com",
      "confidence": 0.99
    },
    {
      "name": "Google Analytics GA4",
      "category": "Analytics",
      "website": "https://analytics.google.com",
      "confidence": 0.99
    }
  ],
  "categories": {
    "Web Framework": ["Next.js", "React"],
    "CDN/Hosting": ["Vercel"],
    "Analytics": ["Google Analytics GA4"]
  },
  "tech_count": 4,
  "analyzed_at": "2026-10-03T05:00:00Z"
}
```

When a URL fails (timeout, DNS error, etc.) the record will contain an `error` key instead of `technologies`:

```json
{
  "url": "https://not-a-real-domain.xyz",
  "final_url": "https://not-a-real-domain.xyz",
  "status_code": null,
  "error": "ConnectError: …",
  "analyzed_at": "2026-10-03T05:01:00Z"
}
```

***

### Use cases

#### Competitive analysis

Map a competitor's full tooling — which analytics platform, A/B testing tool, or chat widget they use — without guessing.

#### Lead qualification

Enrich CRM data by detecting whether a prospect runs Shopify (e-commerce), Stripe (SaaS payments), or Marketo (marketing automation) to tailor outbound messaging.

#### Market research

Scrape a list of 10 000 company homepages to understand framework adoption rates across an industry vertical.

#### Security audits

Identify outdated or known-vulnerable technology fingerprints (e.g., old jQuery versions, exposed framework headers).

#### Agency prospecting

Find WordPress or Wix sites in a niche to target website redesign or migration services.

***

### How it works

1. **URL normalisation** — bare domains are prefixed with `https://`.
2. **HTTP fetch** — httpx async client with a custom User-Agent; optional redirect following.
3. **Artefact extraction** — regex parsing pulls `<script src>`, `<link href>`, `<meta>`, and raw HTML; response headers and `Set-Cookie` values are preserved.
4. **Signature matching** — each of the 80+ `TechSignature` objects carries typed `DetectionPattern` entries. The engine compiles every regex (case-insensitive) and runs it against the appropriate artefact list.
5. **Confidence scoring** — each pattern carries a `confidence` float (0–1). The highest-confidence match for a technology wins; technologies are sorted by confidence descending.
6. **Dataset push** — one `Actor.push_data()` call per URL writes results in real time.

Detection patterns cover:

| Pattern type | What is matched |
|---|---|
| `html` | Raw HTML source of the page |
| `script_url` | Every `<script src="…">` value |
| `css_url` | Every `<link rel="stylesheet" href="…">` value |
| `header` | Response headers as `"name: value"` strings |
| `meta` | Every `<meta …>` tag string |
| `cookie` | `Set-Cookie` header values |

***

### Limitations

- **Client-side-only frameworks**: some SPAs inject `<script>` tags dynamically after JS execution. Because the actor does not run a browser, signatures rely on server-rendered HTML and static asset URLs that appear in the initial document.
- **Minification/obfuscation**: heavily obfuscated bundles may defeat name-based script-URL matching.
- **CDN confidence**: CDN/hosting detection is based on response headers which may be absent on cached or proxied responses.
- **False positives**: some patterns (especially generic HTML patterns) carry lower confidence scores to reflect their inherent ambiguity. Always treat results as signals, not ground truth.
- **Rate limiting**: the actor makes one real HTTP request per URL; aggressive rate limiting or bot-protection (Cloudflare Challenge, Akamai Bot Manager) may block the fetch or return challenge pages instead of real content.

***

### Technical details

- **Runtime**: Python 3.12
- **HTTP client**: [httpx](https://www.python-httpx.org/) (async)
- **Concurrency**: up to 5 URLs fetched simultaneously (configurable via `CONCURRENCY_LIMIT` in `src/main.py`)
- **Signature count**: 80+ across 16 categories (see `src/signatures.py`)
- **Base image**: `apify/actor-python:3.12`

***

### Local development

```bash
## Install dependencies
pip install -r requirements.txt

## Run via Apify CLI (needs .actor/actor.json)
apify run

## Or run the module directly (reads input from INPUT_SCHEMA defaults)
python -m src.main
```

# Actor input Schema

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

List of full URLs or bare domains to inspect (e.g. https://example.com or example.com). Bare domains are automatically prefixed with https://.

## `follow_redirects` (type: `boolean`):

When enabled the actor follows HTTP 3xx redirects and records the final URL. Disable to inspect redirect responses directly.

## `timeout_seconds` (type: `integer`):

Maximum number of seconds to wait for each page to respond before marking it as timed out.

## `include_raw_evidence` (type: `boolean`):

When enabled, each detected technology includes the raw HTML/header fragment that triggered detection. Useful for debugging signatures but increases output size.

## Actor input object example

```json
{
  "follow_redirects": true,
  "timeout_seconds": 30,
  "include_raw_evidence": false
}
```

# Actor output Schema

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

Scraped results stored in the default dataset

# 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 = {};

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

# Run the Actor and wait for it to finish
run = client.actor("emperor1978/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 '{}' |
apify call emperor1978/tech-stack-detector --silent --output-dataset

```

## MCP server setup

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