# Website Tech Stack Detector: What Technologies a Site Uses (`lepidata/tech-stack`) Actor

Website technology data: find what any site is built with (CMS, Shopify/e-commerce, frameworks, analytics, CDN, server). 6,500+ fingerprints, bulk domains, no browser, robots.txt respected. Lead lists by technology. Failed sites are free.

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

## Pricing

from $1.50 / 1,000 site analyzeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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: What Technologies a Site Uses

Find out what a website is built with. Give it a list of sites and get back the CMS, e-commerce platform, JavaScript frameworks, analytics and tag managers, CDN, web server, programming language and more, with versions where the site shows them. It reads page code only, with no browser, using 6,500+ technology fingerprints that work without one. That keeps it fast and cheap.

### Common uses

- **An alternative to BuiltWith and Wappalyzer** (not affiliated with either): look up the tech stack of thousands of domains in bulk, pay per site.
- **Lead lists by technology**: find which prospects run Shopify, WordPress, HubSpot or Google Analytics.
- **Competitor and agency research**: check a site's CMS, e-commerce platform, framework, CDN and analytics.

### Example inputs

Paste any of these into the JSON input tab:

**Quick check (2 sites)**

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

**E-commerce stores**

```json
{"urls": ["https://www.allbirds.com", "https://www.brooklinen.com", "https://www.kyliecosmetics.com"]}
```

**Docs and developer sites**

```json
{"urls": ["https://vercel.com", "https://react.dev", "https://www.python.org"]}
```

### What you get

One row per site:

| Field | Meaning |
|---|---|
| `url` | The site as you entered it |
| `finalUrl` | The page that was analyzed, after redirects |
| `status` | HTTP status of that page |
| `technologies` | `[{ name, categories, version?, confidence }]`, highest confidence first |
| `error` | `null` on normal rows; the reason on free error rows |
| `duplicateOf` | Only on free `duplicate-host` rows: the earlier URL on the same host |

```json
{ "url": "https://example-shop.com", "finalUrl": "https://example-shop.com/", "status": 200,
  "technologies": [ { "name": "Shopify", "categories": ["Ecommerce"], "confidence": 100 },
                    { "name": "Cloudflare", "categories": ["CDN"], "confidence": 100 } ], "error": null }
```

### Pricing

**$1.50 per 1,000 sites analyzed** (pay per event `site`). Sites that could not be analyzed are **free**: robots.txt says no, the address is unsafe or unreachable, the server answered with an error, or the page is not HTML. Set a maximum charge per run in Apify and the Actor stops cleanly when it is reached; nothing past the limit is charged.

Free-plan accounts get up to 20 sites per run to try it out; the run ends with one free row explaining the limit. Paid Apify plans get full results.

Each site is fetched once per run, with one request at a time to any one site; repeat URLs for the same site come back as a free `duplicate-host` row. For checking public sites, not for load testing or probing systems you don't own.

### How it works

- Reads **one page per site** (the URL you give, following up to 5 redirects). No browser and no JavaScript is run, and no extra pages are crawled.
- "Same site" means the same host: `example.com`, `https://www.example.com/` and `https://example.com/about` count as one (case, a leading `www.`, a trailing dot and the default port are ignored). The first URL you list for it is the one analyzed.
- Looks at the HTML (meta tags, script and stylesheet addresses, inline scripts, page structure), response headers, and the **names** of cookies the site sets. Cookie values are never read or stored.
- **robots.txt is checked** for every site (and every redirect target). If it disallows the page, or can't be read, the site is skipped as a free row. `Crawl-delay` is honored.
- Only public websites: private, internal and cloud-metadata addresses, unusual address forms and non-web ports are refused.
- Each page is capped at 2 MB and 20 seconds.

### Limits

The fingerprint list covers 7,600+ technologies. About 6,500 of them have fingerprints this scan reads (headers, cookies, HTML, meta tags, script links and inline scripts). About 900 can only be found by a browser running the page's JavaScript, and about 150 depend on DNS lookups or are only inferred from other technologies; this Actor checks neither. It also finds some tools less often than a browser would, such as analytics and ad tags that a tag manager loads after the page opens. Server-side tools that leave no trace in HTML or headers can't be seen by anyone from outside. Confidence below 100 means the evidence is weaker (for example one generic header).

### FAQ

**What does it access?** For each URL you list, it reads that one public page's HTML and headers (following up to 5 redirects) and the site's robots.txt. Nothing behind a login, and no JavaScript is run.

**Anything I should watch out for?** Check that your own use fits each site's terms, and don't use the results to send unsolicited messages.

**How often should I run it?** Stacks change slowly; monthly is usually enough for lead lists, weekly for competitor monitoring.

**Can I get every page of a site?** No. Each host is checked once per run, on the first URL you list for it; other URLs on the same host come back as free `duplicate-host` rows.

### Credits

Technology fingerprints come from the open-source [webappanalyzer](https://github.com/enthec/webappanalyzer) project (GPL-3.0), originally from Wappalyzer.

# Actor input Schema

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

Website URLs or bare domains (example.com gets https://). One page is read per entry: the URL as given, after up to 5 redirects. Only public http/https sites; private, internal and unusual addresses are refused with a free error row. Up to 5,000 per run.

## Actor input object example

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

# Actor output Schema

## `sites` (type: `string`):

All rows from this run.

# 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://www.shopify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lepidata/tech-stack").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://www.shopify.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lepidata/tech-stack").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://www.shopify.com"
  ]
}' |
apify call lepidata/tech-stack --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lepidata/tech-stack"
        }
    }
}
```

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/gzJZRsWIfefdJzleX/builds/h1HelJgjFHdKaI1Ze/openapi.json
