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

Detect the technologies behind any list of websites: CMS, e-commerce platform, analytics, tag managers, ad pixels, CDN, hosting, frameworks, payments and email provider. 3,500+ signatures on HTML, headers, cookies, scripts and DNS. No browser, robots.txt respected.

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

## Pricing

from $2.00 / 1,000 websites

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

## Tech Stack Detector: Wappalyzer & BuiltWith Alternative (Bulk)

Give it a list of websites and get one row per site with the **technologies it runs on**:

- **CMS and site builders**: WordPress, Drupal, Joomla, Webflow, Wix, Squarespace, HubSpot CMS, Ghost, TYPO3, AEM, Sitecore...
- **E-commerce platform**: Shopify, WooCommerce, Magento / Adobe Commerce, BigCommerce, PrestaShop, Salesforce Commerce Cloud, VTEX, Tiendanube / Nuvemshop, Wix Stores... plus a simple `hasEcommerce` flag
- **Analytics, tag managers and ad pixels**: Google Analytics, Google Tag Manager, Meta (Facebook) Pixel, LinkedIn Insight, TikTok Pixel, Hotjar, Microsoft Clarity, Segment, Mixpanel...
- **Marketing automation, CRM and live chat**: HubSpot, Marketo, Pardot, Klaviyo, Mailchimp, Intercom, Drift, Zendesk, tawk.to...
- **Payments**: Stripe, PayPal, Klarna, Afterpay, Mercado Pago...
- **Frameworks and libraries**: React, Next.js, Vue, Nuxt, Angular, Svelte, jQuery, Bootstrap, Tailwind...
- **Hosting, CDN and servers**: Cloudflare, Fastly, Akamai, CloudFront, Vercel, Netlify, AWS, Nginx, Apache, IIS...
- **Email provider and SaaS from DNS**: Google Workspace, Microsoft 365, Zoho Mail, SendGrid, Amazon SES, Mailgun, Atlassian, DocuSign, Salesforce...
- Versions when the site exposes them (e.g. `WordPress 6.4.2`, `jQuery 3.7.1`)

**3,500+ technology signatures** are checked against the HTML, HTTP headers, cookies, `<meta>` tags, script URLs, CSS selectors of the page and the domain's DNS records. Plain HTTP requests, **no browser**: fast and cheap at scale.

### What does Tech Stack Detector do?

Tech Stack Detector finds the technologies behind a list of websites: CMS (WordPress, Shopify...), e-commerce platform, analytics, tag managers, ad pixels, CDN, hosting, JavaScript frameworks, payment providers and email provider, using 3,500+ open Wappalyzer signatures on HTML, headers, cookies, scripts and DNS. Use it for technographic lead generation and competitor research.

### How to use Tech Stack Detector

1. Click **Try for free** on this page (a free Apify account is enough to start).
2. Fill in the input (see the examples below) or keep the prefilled example.
3. Click **Start** and wait for the run to finish.
4. Download the results from the **Output** tab as JSON, CSV, Excel or HTML, or read them with the Apify API.
5. Optional: create a **Schedule** to run it daily or weekly, and connect a webhook or an integration (Make, Zapier, n8n, Slack).

### Use cases

- **B2B sales prospecting**: find every Shopify / WooCommerce / Magento store in a list, or every company using HubSpot, Salesforce or a competitor's product
- **Lead qualification and CRM enrichment**: add CMS, e-commerce platform, analytics and email provider to each account
- **Agencies**: audit a prospect's stack before the first call (CMS, tracking pixels, consent tool, CDN)
- **Market research**: technology adoption across a market, a country or a competitor list
- **Change monitoring**: schedule weekly runs and get alerted when a prospect adds or removes a technology (a migration is a buying signal)

### Input

```json
{
  "urls": ["wordpress.org", "www.allbirds.com", "https://vercel.com/"],
  "maxPagesPerSite": 1,
  "checkDns": true,
  "onlySitesUsing": [],
  "compareWithPreviousRun": false
}
```

- **Websites**: domains, URLs or work emails, one per line. Duplicates and invalid lines are removed.
- **Dataset** or **CSV file URL**: check the websites of another Actor's output (Google Maps, lead lists...) or a spreadsheet (Google Sheets links work). Say which column has the website with **URL field**, and copy columns like `name` or `id` into the output with **Fields to keep**.
- **Pages per site**: 1 = home page only. Up to 5 also checks a few internal pages (shop, blog, pricing, contact). Same price.
- **Only output sites using**: a lead-gen filter, e.g. `Shopify`, `Klaviyo`.
- **Track changes between runs**: adds `changes.added` / `changes.removed` compared with the previous run of the same monitor name.

### Output (one row per site, shortened)

```json
{
  "input": "www.allbirds.com",
  "domain": "allbirds.com",
  "url": "https://www.allbirds.com/",
  "finalUrl": "https://www.allbirds.com/",
  "status": "ok",
  "httpStatus": 200,
  "technologyCount": 12,
  "technologyNames": ["Shopify", "PayPal", "Google Tag Manager", "Cloudflare", "Microsoft 365", "..."],
  "technologies": [
    { "name": "Shopify", "version": null, "confidence": 100, "categories": ["Ecommerce"], "website": "http://shopify.com", "cpe": null }
  ],
  "cms": [],
  "ecommerce": ["Shopify"],
  "hasEcommerce": true,
  "analytics": [],
  "tagManagers": ["Google Tag Manager"],
  "advertising": [],
  "marketingAutomation": [],
  "liveChat": [],
  "paymentProcessors": ["PayPal"],
  "javascriptFrameworks": [],
  "cdn": ["Cloudflare"],
  "hosting": [],
  "webServers": [],
  "emailProvider": ["Microsoft 365"],
  "pagesAnalyzed": ["https://www.allbirds.com/"],
  "dnsChecked": true,
  "changes": null,
  "source": null,
  "error": null,
  "checkedAt": "2026-10-26T21:56:36.914Z"
}
```

Every row has the same keys. Sites that could not be checked come back with `status: "failed"` (or `"blocked_by_robots"`) and an `error` in plain English, and are **not charged**. A `RUN_SUMMARY` record in the key-value store counts sites, failures and the most common technologies.

### Pricing

Pay per event: **USD 0.002 per site checked** (USD 2 per 1,000 sites), whatever the number of pages per site. Failed sites, sites blocked by robots.txt, invalid lines and duplicates are free. With "Only output sites using", sites that do not match are still charged because they were analysed. Your "max charge per run" is respected: the Actor never checks more sites than you are willing to pay for.

### How it works and limits

- One plain HTTP request per page with an identifiable user agent (`TechStackDetectorBot`). **robots.txt is checked on every request and redirect**: sites that disallow it are skipped, not bypassed. At most 1 request per second per site.
- No browser, so technologies that can only be seen by running the page's JavaScript (some single-page apps, tags injected by a tag manager, JavaScript global variables) can be missed. Sites behind a bot challenge (some WAFs) return little or nothing.
- Detection is signature-based: a technology is reported when its fingerprint is present, which is reliable for platforms and tags but cannot see back-end tools that leave no trace.
- Only public, technical data about websites. No personal data is collected.

### Credits and licence of the signatures

Technology signatures and the matching engine come from **Wappalyzer 6.10.54** (npm package `wappalyzer`, released under the **MIT licence**; copyright Elbert Alias). The licence text is included in the Actor source at `vendor/wappalyzer/LICENSE`. A few extra signatures and false-positive fixes were added by us. This Actor is not affiliated with or endorsed by Wappalyzer.

### Cost examples

Prices at the current pay-per-event rate: USD 2.00 per 1,000 websites analysed (failed sites, robots.txt blocks and duplicates are free). You can set a maximum charge per run in the run options.

| Job | Approximate cost |
|---|---|
| Test run: the 3 example sites (measured: 3 s) | about $0.006 |
| 500 lead domains from a CSV | about $1.00 |
| 10,000 domains for market research | about $20.00 |
| Weekly monitor of 50 competitor sites (changes detected) | about $0.10 per run |

### Use it from your code, an integration or an AI agent

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("latamdatatools/tech-stack-detector").call(run_input={
  "urls": [
    "wordpress.org",
    "www.allbirds.com",
    "vercel.com"
  ],
  "maxPagesPerSite": 1,
  "checkDns": True
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["domain"], item["cms"], item["technologyNames"])
```

**JavaScript / Node.js** (`npm install apify-client`):

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('latamdatatools/tech-stack-detector').call({
  urls: [
    'wordpress.org',
    'www.allbirds.com',
    'vercel.com'
  ],
  maxPagesPerSite: 1,
  checkDns: true
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((i) => [i.domain, i.technologyNames]));
```

**No code:**

- **Schedules:** save your input as a Task and run it daily or weekly from Apify Console (Schedules).
- **Integrations:** send the results to Google Sheets, Slack, email, Make, Zapier, n8n or Airbyte from the Integrations tab, or call your own webhook when a run finishes.
- **AI agents:** add it as a tool in Claude, Cursor, VS Code and other MCP clients through the Apify MCP server (`https://mcp.apify.com`), so the agent can look up what a company website is built with.

### FAQ

**Can I check 10,000 sites?** Yes. Raise "Sites checked in parallel" (up to 20) for faster runs; each site still gets at most 1 request per second.

**Why is a technology I know the site uses missing?** It may be loaded only by JavaScript after the page renders, live on a page that was not checked (try "Pages per site" 3-5), or the site may block automated requests.

**Can I get only Shopify stores?** Put `Shopify` in "Only output sites using".

# Actor input Schema

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

One domain or URL per line (e.g. shopify.com, https://www.bbc.co.uk/). Work emails are accepted too (the domain is used). Duplicates and invalid lines are removed.

## `datasetId` (type: `string`):

Optional: check the websites stored in an Apify dataset, e.g. the output of a Google Maps or lead scraper. Use "URL field" to say which field holds the website.

## `csvUrl` (type: `string`):

Optional: a public URL of a CSV file with a header row (comma, semicolon, tab or | separated, up to 50 MB). Google Sheets links work if the sheet is shared as "Anyone with the link".

## `urlField` (type: `string`):

Field / CSV column that holds the website or domain, e.g. url, website, domain, company.website (dot notation for nested fields).

## `keepFields` (type: `array`):

Optional: copy these fields of each dataset record / CSV row into the output (under "source"), e.g. name, id, so you can join the results back.

## `maxPagesPerSite` (type: `integer`):

1 = home page only (fastest). Up to 5: also checks a few internal pages (shop, blog, pricing, contact) to catch technologies that are not on the home page. Same price per site.

## `checkDns` (type: `boolean`):

Read MX, TXT, NS and CNAME records to detect the email provider (Google Workspace, Microsoft 365, Zoho...), email senders (SendGrid, Amazon SES, Mailchimp...) and verified SaaS (Atlassian, DocuSign, Salesforce...).

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

Hide detections with a lower confidence score. Most detections are 100; weak single hints score 25-75.

## `onlySitesUsing` (type: `array`):

Optional lead-gen filter, e.g. Shopify, WooCommerce, HubSpot (technology names, case-insensitive). Other sites are left out of the results but still count as checked, because they were analysed.

## `compareWithPreviousRun` (type: `boolean`):

Store the technologies of each site and, on the next run, add "changes" with the technologies added and removed since the previous run (e.g. a prospect moved from Magento to Shopify). Use it with a schedule.

## `monitorName` (type: `string`):

Keeps separate histories for different lists. Letters, numbers and dashes.

## `maxConcurrency` (type: `integer`):

Each site gets at most 1 request per second; parallelism is across different sites.

## `requestTimeoutSecs` (type: `integer`):

Per request.

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

Upper limit of sites to check in one run. 0 = no limit (up to 100,000). Your max charge per run is respected too.

## Actor input object example

```json
{
  "urls": [
    "wordpress.org",
    "www.allbirds.com",
    "vercel.com"
  ],
  "urlField": "url",
  "maxPagesPerSite": 1,
  "checkDns": true,
  "minConfidence": 50,
  "compareWithPreviousRun": false,
  "monitorName": "default",
  "maxConcurrency": 5,
  "requestTimeoutSecs": 20,
  "maxSites": 0
}
```

# Actor output Schema

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

No description

## `runSummary` (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": [
        "wordpress.org",
        "www.allbirds.com",
        "vercel.com"
    ]
};

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

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

```

## MCP server setup

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