# Website Tech Stack Detector: CMS, SaaS Tools & Email Provider (`metallic_pastry/website-tech-stack-detector`) Actor

See what any website runs on: CMS, shop platform, frameworks, analytics, ad pixels, CRM and chat tools, CDN and hosting, plus email provider, SaaS tools verified in DNS, TLS expiry, AI crawler rules and stack changes between runs. Evidence for every match.

- **URL**: https://apify.com/metallic_pastry/website-tech-stack-detector.md
- **Developed by:** [Simon Liarsgård](https://apify.com/metallic_pastry) (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

from $3.00 / 1,000 website reports

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

Give it a list of domains and get back what each site is built with: the CMS or shop platform, frameworks, analytics and ad pixels, marketing, CRM and chat tools, consent banner, CDN and hosting. It also reads the domain's public DNS, which a page scan can't see: who handles the company's email, which services send mail on its behalf, and which SaaS tools the company has verified ownership with (Atlassian, DocuSign, Slack, Zoom and so on).

Every detected technology comes with the evidence it was found by, such as the script URL, the response header or the DNS record. You can check any result by hand.

### What you can use it for

- **Lead lists.** Find the shops on Shopify or WooCommerce, the companies on Microsoft 365 rather than Google Workspace, or the sites that run HubSpot. Put the names you care about in *Technologies to flag* and filter on `watchedTechnologiesFound`.
- **Switch signals.** Run it on a schedule. With change tracking on, each report lists the technologies added or removed since the previous run, so you hear when a prospect drops a competitor or adds a new chat tool.
- **Agency and sales research.** See a site's stack before a call: framework, hosting, consent tool, analytics and tag setup.
- **Email deliverability checks.** See each domain's MX provider, SPF senders and DMARC policy side by side.
- **AI crawler policy.** See which AI crawlers (GPTBot, ClaudeBot, Google-Extended, CCBot and others) a site's robots.txt keeps out.

### Input

| Field | What it does |
|---|---|
| Websites | Domains or URLs, one per line. An email address works too; its domain is used. |
| Technologies to flag | Optional names to look for, for example `Shopify`, `HubSpot`, `Microsoft 365`. |
| Check DNS and TLS | On by default. Adds the email provider, email senders, SaaS tools verified in DNS, DNS provider and the TLS certificate. |
| Track changes between runs | On by default. Remembers each domain's stack and reports what changed. |
| Change tracking key | Keeps a separate history for each list you watch. |
| Max websites / Websites in parallel | Limits for big lists. |

```json
{
    "websites": ["allbirds.com", "oatly.com", "klarna.com"],
    "watchTechnologies": ["Shopify", "HubSpot"]
}
```

### Output

One row per website. The **Overview** view has the main platform in each category. The **Technologies** view has one row per technology with its version and evidence. **Email, DNS and social** covers the mail setup, TLS certificate, AI crawler rules and the site's own social profiles. **Detail** has everything.

```json
{
    "website": "allbirds.com",
    "status": "ok",
    "technologyCount": 11,
    "ecommerce": "Shopify",
    "analytics": ["Microsoft Clarity"],
    "consent": "OneTrust",
    "cdn": ["Cloudflare"],
    "emailProvider": "Microsoft 365",
    "saasVerified": ["Google Search Console", "DocuSign", "Apple Business", "Miro"],
    "watchedTechnologiesFound": ["Shopify", "Microsoft 365"],
    "technologies": [
        { "name": "Shopify", "category": "ecommerce", "version": null, "source": "header:powered-by", "evidence": "Shopify" },
        { "name": "Microsoft 365", "category": "email-provider", "version": null, "source": "mx", "evidence": "allbirds-com.mail.protection.outlook.com" }
    ],
    "tls": { "issuer": "Let's Encrypt", "daysUntilExpiry": 68, "trusted": true },
    "aiCrawlers": { "robotsTxt": true, "blocked": [] },
    "changes": { "previousCheckAt": "2026-10-30T03:28:03.890Z", "added": [], "removed": [] }
}
```

This is a shortened row from a real run in October 2026. Your results reflect each site at the time of your run.

### What it detects

About 266 technologies in 36 categories, written and tested by hand rather than copied from a public list. Matches are kept strict on purpose, because a false positive in a lead list costs more than a miss.

- **Site:** WordPress, Drupal, TYPO3, Contentful, Sanity, Storyblok, Webflow, Wix, Squarespace, Framer, Shopify, WooCommerce, Magento, Salesforce Commerce Cloud, Shopware, Next.js, Nuxt, Astro, React, Vue.js, Angular and more.
- **Marketing and sales:** Google Analytics and Tag Manager, Meta, LinkedIn, TikTok and Google Ads pixels, HubSpot, Marketo, Pardot, Klaviyo, Intercom, Drift, Zendesk, 6sense, Leadfeeder and more.
- **Infrastructure:** Cloudflare, Fastly, Akamai, CloudFront, Vercel, Netlify, WP Engine, Nginx, Apache, PHP, ASP.NET.
- **From DNS:** Google Workspace, Microsoft 365 and other mail providers, Mimecast and Proofpoint gateways, SendGrid, Mailgun, Amazon SES and other senders, about 30 SaaS verification records and the DNS provider.

### Pricing

You pay per website report, at $0.003 per analysed website ($3 per 1,000), plus a tiny start fee. You don't pay for:

- invalid input or domains that don't exist;
- websites whose homepage is blocked, unreachable or not HTML (you still get the DNS part of the report for free);
- errors.

Set a maximum charge on the run if you want a hard ceiling. The Actor stops cleanly when it's reached.

### How it works and what it respects

For each domain the Actor reads robots.txt, fetches the homepage once, runs DNS lookups and opens one TLS connection. That's about the same as a single visit in a browser. It identifies itself as `TechStackDetector` in the user agent. If a site's robots.txt disallows that agent (or all agents) from the page, the homepage is not fetched and only the DNS part is reported, at no charge. It never logs in, submits forms or follows links deeper into a site. Cookie values are never stored; only cookie names are used for matching.

### Limits

- Only the page you give (usually the homepage) is read. Tools that load only on checkout or after login won't show up.
- Tools injected later by a tag manager may not appear in the HTML. The tag manager itself is still reported.
- Sites behind strict bot protection sometimes answer with a challenge page. Those come back as `partial` and are free.

### Support

Missing a technology you need, or found a wrong match? Open an issue on the Actor page with the domain and what you expected, and it will usually be added in the next version.

# Changelog

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

# Actor input Schema

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

Domains or URLs to check, one per line, for example "allbirds.com" or "https://www.oatly.com/en". An email address works too; its domain is used. Duplicates are removed.

## `watchTechnologies` (type: `array`):

Optional. Names to look for, such as "Shopify", "HubSpot" or "Microsoft 365". Matches are listed in watchedTechnologiesFound so you can filter a lead list in one step.

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

Look up MX, SPF, DMARC, TXT and NS records and the TLS certificate. This finds the email provider, email senders, SaaS tools verified on the domain and the DNS provider.

## `trackChanges` (type: `boolean`):

Remember each domain's stack and report technologies added or removed since the previous run. Useful on a schedule.

## `stateKey` (type: `string`):

Keeps separate change history per list. Use a different key for each watchlist. Letters, digits, - and \_.

## `maxWebsites` (type: `integer`):

Stop after this many websites. Websites over the limit are skipped and not charged.

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

How many websites to check at the same time.

## Actor input object example

```json
{
  "websites": [
    "allbirds.com",
    "oatly.com",
    "klarna.com"
  ],
  "includeDns": true,
  "trackChanges": true,
  "stateKey": "default",
  "maxWebsites": 1000,
  "concurrency": 5
}
```

# Actor output Schema

## `overview` (type: `string`):

Default dataset, Overview view: main platform per category, email provider, SaaS tools in DNS and changes.

## `technologies` (type: `string`):

Default dataset, Technologies view: one row per detected technology with category, version and evidence.

## `detail` (type: `string`):

Default dataset, Detail view: every field per website.

## `runSummary` (type: `string`):

RUN_SUMMARY record in the default key-value store: analysed, partial, free and charged counts and the most common technologies.

# 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": [
        "allbirds.com",
        "oatly.com",
        "klarna.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("metallic_pastry/website-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": [
        "allbirds.com",
        "oatly.com",
        "klarna.com",
    ] }

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

```

## MCP server setup

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