# Tech Stack Detector: Website Technology & SaaS Lookup (`datatools_studio/tech-stack-detector`) Actor

Detect the tech stack behind any list of websites: CMS, ecommerce platform, analytics and ad pixels, marketing and chat tools, frameworks, CDN, hosting and email provider. A BuiltWith and Wappalyzer alternative. Pay per website with findings; websites that fail are not charged.

- **URL**: https://apify.com/datatools_studio/tech-stack-detector.md
- **Developed by:** [mohamad](https://apify.com/datatools_studio) (community)
- **Categories:** Lead generation, Developer tools, SEO tools
- **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

### What does Website Tech Stack & SaaS Detector do?

Give it a list of websites and it tells you what each one runs on: the CMS or ecommerce platform, analytics and ad pixels, chat and marketing tools, JavaScript frameworks, CDN and hosting. It also reads each domain's public DNS records to find the **email provider**, the **services allowed to send email** for the company, its **SPF and DMARC policies**, and **SaaS tools the company verified its domain with** (for example Atlassian, HubSpot or DocuSign).

- **Pay per website with results**, plus Apify's small start fee per run. Websites that fail (domain does not exist, site down, nothing found) cost nothing extra.
- **7,600+ technologies** recognised, each with category, confidence, version when visible, and the evidence it was found by.
- **Email and DNS insights** that page-only tools miss.
- **Change monitoring**: run it on a schedule and get the technologies each site added or removed since the last run.
- **Full or compact output.** Compact gives one short row per website, ready for spreadsheets, CRMs and AI agents.

### What can you use it for?

- **Lead lists by technology**: find the stores on Shopify that use Klaviyo, or the sites on WordPress without a cookie banner tool.
- **Sales enrichment**: add the tech stack and email provider to the companies in your CRM.
- **Competitor and market research**: see which tools your market uses and how that changes over time.
- **Agency prospecting**: spot sites on old versions or missing analytics.
- **Email security checks** for your own domains or clients: SPF, DMARC policy and DMARC reporting service per domain.

### How to use it

1. Paste your websites into **Websites**, one per line (`example.com` or a full URL). Up to 100,000 per run; duplicates are skipped. With the default settings a run checks about 10,000 websites an hour.
2. Pick **Full** or **Compact** output. Optionally keep only some categories, for example `Ecommerce` or `Analytics`.
3. Click **Start**. Download the results as CSV, Excel or JSON, or read them through the Apify API.

### Input

| Field | What it does | Default |
| --- | --- | --- |
| Websites | Domains or URLs to check | (required) |
| Output format | `full` (every detail) or `compact` (one short row) | `full` |
| Minimum confidence | Report only technologies at or above this confidence, 1 to 100 | 50 |
| Only these categories | Keep only these categories or groups | all |
| Check DNS records | Email provider, sending services, SPF, DMARC and DNS-based SaaS | on |
| Report changes since the last run | Compare with this website's previous result | off |
| Storage name for change monitoring | Named key-value store in your account that keeps the last result | `tech-stack-monitor` |
| Respect robots.txt | Skip homepages that robots.txt asks tools not to load (DNS checks still run) | on |
| Parallel requests | Websites checked at the same time, 1 to 100 | 20 |
| Page timeout | Seconds to wait for a homepage, 5 to 120 | 20 |

### Output

One row per website. Example in compact format (a made-up site):

```json
{
  "domain": "example.com",
  "status": "ok",
  "technologyNames": ["Atlassian Cloud", "Cloudflare", "Facebook Pixel", "Google Analytics", "Google Tag Manager",
    "Google Workspace", "HubSpot", "jQuery", "MySQL", "PHP", "WordPress"],
  "technologiesByCategory": { "Analytics": ["Facebook Pixel", "Google Analytics"], "CMS": ["WordPress"], "CDN": ["Cloudflare"] },
  "emailProvider": "Google Workspace",
  "emailSendingServices": ["Google Workspace", "MailChimp"],
  "technologiesFromDns": ["Atlassian Cloud", "Google Workspace", "HubSpot"],
  "errorCode": null
}
```

The full format adds, for each technology, its categories, version, confidence, website, SaaS and open-source flags, and the evidence it was found by:

```json
{
  "name": "Cloudflare",
  "categories": ["CDN"],
  "version": null,
  "confidence": 100,
  "website": "https://www.cloudflare.com",
  "detectedVia": ["headers"],
  "evidence": ["header:server", "header:cf-ray"]
}
```

It also adds the email setup (inbox provider, MX hosts, sending services, SPF and DMARC policies, DMARC report services), DNS facts (nameservers, CNAME targets), site facts (title, description, language, generator tag, company social profiles), robots.txt status, and the time of the check. The dataset has ready-made views: Overview, Technologies, Email and DNS, Status details and Changes.

**Status of each row**

- `ok`: the homepage and DNS were analysed.
- `partial`: some data, but the page was blocked, returned an error, or was skipped (for example because of robots.txt). The `statusDetail` and `error` fields say what happened.
- `failed`: nothing could be checked. Not charged.

### How much does it cost?

You pay a small fee for each website that returns at least one finding (a technology or an email setup), plus Apify's small fee for starting a run. Websites that fail, and partial rows with no findings, are not charged. See the **Pricing** tab for current prices.

### Limitations

- **One page per website.** The tool reads the homepage (or the exact URL you give) plus DNS. Tools used only on other pages are not seen.
- **No browser.** Pages are read without running JavaScript. Install snippets written in the page are read, so many analytics, chat and ad tags are still found, but tags added only inside a tag manager (such as a Google Tag Manager container) and apps that build the whole page in the browser can be missed.
- **Bot protection.** Some sites block automated visits. Those rows come back as `partial` with the error code `BLOCKED`, usually still with DNS findings.
- **Fingerprints are evidence, not proof.** Each result has a confidence score and evidence. Raise **Minimum confidence** if you want fewer, surer results.
- **robots.txt is followed by the standard (RFC 9309).** When a website's robots.txt answers with a server error or not at all, its homepage is not loaded (DNS checks still run), and `statusDetail` says so. You can turn **Respect robots.txt** off for websites you own or may test.
- Only public websites: private and internal network addresses are refused, including when a website redirects to one.

### Privacy and data

The tool reads only public web pages and public DNS records. It returns no email addresses and no personal profiles: DMARC report addresses are reduced to the service name, and only company social profile links (not personal ones) are kept. It never logs in, fills forms or bypasses access controls, and it respects robots.txt by default. You are responsible for using the results lawfully, for example under GDPR when you contact companies.

### Use it from code or AI agents

Run it through the [Apify API](https://docs.apify.com/api/v2) or the Apify clients for JavaScript and Python, or connect it to Make, Zapier, n8n and other tools through Apify integrations. Compact output keeps each row short for AI agents and spreadsheets.

### Support

Found a wrong or missing detection? Open an issue on the **Issues** tab with the website and what you expected; we add fixes to our own fingerprint additions. This Actor is built and maintained with the help of AI (Claude), and replies to issues are AI-assisted.

### Credits

Technology fingerprints come from the community-maintained [webappanalyzer](https://github.com/enthec/webappanalyzer) project (GPL-3.0), plus our own additions. The changelog lists the version in use.

# Changelog

This Actor's version history is a separate document: https://apify.com/datatools_studio/tech-stack-detector/changelog.md

# Actor input Schema

## `websites` (type: `array`):

Domains or URLs to check, one per line, for example <code>example.com</code> or <code>https://shop.example.com</code>. Each website is checked through its homepage (or the exact URL you give) and its public DNS records. Up to 100,000 per run; duplicates are skipped.

## `outputFormat` (type: `string`):

<b>Full</b> gives every detail: versions, confidence, evidence, categories, email setup and DNS facts. <b>Compact</b> gives one short row per website (technology names, categories and email provider), handy for spreadsheets and AI agents.

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

Only report technologies detected with at least this confidence (1 to 100). Lower values find more, with more false positives.

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

Leave empty to get everything. Otherwise only technologies in these categories or groups are returned, for example Ecommerce, Analytics, CMS or Marketing automation.

## `includeDns` (type: `boolean`):

Read public DNS records (MX, TXT, SPF, DMARC, NS, CNAME) to find the email provider, email sending services and SaaS tools that verified the domain. Turn off for a faster, page-only check.

## `monitorChanges` (type: `boolean`):

Remember each website's technologies in a named key-value store in your own account, and add the technologies added or removed since your previous run. Useful with a schedule.

## `monitorStoreName` (type: `string`):

Name of the key-value store (in your account) that keeps the last result of each website. Use different names to keep separate watch lists. The Actor creates this storage on the first run and can only use storages it created itself.

## `respectRobotsTxt` (type: `boolean`):

Skip the homepage of websites whose robots.txt asks automated tools not to load it. DNS checks still run for those websites.

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

How many websites to check at the same time.

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

How long to wait for a homepage before giving up.

## Actor input object example

```json
{
  "websites": [
    "apify.com",
    "wordpress.org",
    "shopify.com"
  ],
  "outputFormat": "full",
  "minConfidence": 50,
  "includeDns": true,
  "monitorChanges": false,
  "monitorStoreName": "tech-stack-monitor",
  "respectRobotsTxt": true,
  "maxConcurrency": 20,
  "requestTimeoutSecs": 20
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "websites": [
        "apify.com",
        "wordpress.org",
        "shopify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("datatools_studio/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 = { "websites": [
        "apify.com",
        "wordpress.org",
        "shopify.com",
    ] }

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

```

## MCP server setup

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