# Website Technology Checker: Tech Stack & CMS Detector (`plainrows/website-tech-stack`) Actor

Wappalyzer & BuiltWith alternative: find the tech stack of any list of websites: CMS, ecommerce platform, analytics, tag managers, CDN, hosting, frameworks, payments, live chat and email provider, with versions. Bulk domains in, one spreadsheet-ready row per site. Pay only per site analysed.

- **URL**: https://apify.com/plainrows/website-tech-stack.md
- **Developed by:** [PlainRows](https://apify.com/plainrows) (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 $0.60 / 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.
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 Technology Checker: Tech Stack & CMS Detector

Find out **what any website is built with**: CMS, ecommerce platform, analytics, tag manager, CDN, hosting, JavaScript frameworks, payment providers, live chat, marketing tools and **email provider**, with versions when the site shows them, plus the **e-mails, phone links and social profiles shown on the homepage**. Paste a list of domains, get **one spreadsheet-ready row per website**, like a bulk BuiltWith or Wappalyzer lookup.

Each homepage is loaded live over HTTP (no browser, no proxy, no login) and matched against **7,600+ open-source technology fingerprints**: about 150 websites per minute in our tests. **You only pay for websites actually analysed**: sites that are down, blocked or do not exist are free.

### Typical uses

- **Lead generation and sales prospecting**: find every Shopify, WooCommerce or Magento store in a list, or every company on HubSpot, Salesforce or Microsoft 365, with the e-mail, phone and LinkedIn page their homepage shows.
- **Agencies**: qualify prospects by CMS (WordPress, Webflow, Wix, Squarespace), page builder or analytics setup before a pitch.
- **Competitive and market research**: measure the market share of a CMS, a payment provider or a chat tool across thousands of sites.
- **SaaS go-to-market**: build lists of sites using a competitor's product (e.g. Intercom, Klaviyo, Optimizely).
- **Security and IT inventory**: see which web servers, frameworks and versions your own sites expose.
- **Automations and AI agents**: enrich a CRM or a Google Sheet with the tech stack of each account.

### What you get for each website

| Field | Description |
|---|---|
| `domain`, `finalUrl`, `statusCode` | The site, its homepage URL after redirects and the HTTP status |
| `technologyCount`, `technologyNames` | How many technologies were found, and their names in one comma-separated cell |
| `cms`, `ecommerce`, `analytics`, `tagManagers`, `advertising`, `marketingAutomation`, `crm`, `email`, `liveChat`, `abTesting`, `paymentProcessors`, `cdn`, `hosting`, `webServers`, `jsFrameworks`, `webFrameworks`, `programmingLanguages`, `cookieConsent`, `security` | One column per category (comma-separated names, `null` when none): filter your spreadsheet on `ecommerce = Shopify` in one click |
| `technologies` | Full list: `name`, `categories`, `version` (`null` when not shown), `confidence` (0-100), `detectedFrom` (html, script, header, cookie, meta, dns, url, robots or implied) and the vendor `website` |
| `title`, `metaDescription`, `language` | Homepage title, meta description and declared language |
| `contactEmail`, `contactEmails`, `contactPhones` | E-mails shown on the homepage or in its links (the site's own domain first, max 10; addresses hidden in the page code and people's details in structured data are ignored) and phone links. `email` is a different column: the e-mail provider (e.g. Google Workspace) |
| `facebookUrl`, `instagramUrl`, `linkedinUrl`, `xUrl`, `youtubeUrl`, `tiktokUrl` | Social profiles the homepage links to (share buttons, posts and personal Facebook / LinkedIn profile links ignored) |
| `contactOptOut` | `true` when the homepage objects to solicitation: the contact columns are then left empty (see [Personal data and GDPR](#personal-data-and-gdpr)) |
| `server`, `poweredBy` | `Server` and `X-Powered-By` response headers |
| `found`, `error`, `errorMessage` | `found: false` when the homepage could not be loaded, with the reason (`DNS_NOT_FOUND`, `TIMEOUT`, `HTTP_ERROR`, `BLOCKED_BY_BOT_PROTECTION`, `ROBOTS_TXT_DISALLOWED`, `NOTHING_DETECTED` for an empty or parked page...) |
| `detectedAt` | When the site was analysed (UTC) |

Every row has the same columns, so the dataset exports cleanly to CSV, Excel or Google Sheets. Nothing is guessed: a technology is listed only when one of its fingerprints matched.

### Input

```json
{
  "domains": ["shopify.com", "wordpress.org", "https://www.allbirds.com/collections/mens"],
  "minConfidence": 0
}
```

- **domains**: domains or URLs, up to 10,000 per run. `www.`, paths and duplicates are removed; the homepage is analysed.
- **minConfidence** (optional): hide detections below this confidence (0 shows everything, as Wappalyzer does; most detections are 100).

### Output example

Real row from a run on 2026-10-07 for `allbirds.com` (`technologies` shortened to 3 of its 14 entries; contact fields computed on 2026-10-08 from the same homepage):

```json
{
  "domain": "allbirds.com",
  "found": true,
  "finalUrl": "https://www.allbirds.com/",
  "statusCode": 200,
  "title": "Allbirds: Comfortable, Sustainable Shoes & Apparel",
  "metaDescription": "Allbirds: The world’s most comfortable shoes, flats, and clothing made with natural materials like merino wool and eucalyptus. FREE shipping & returns.",
  "language": "en-US",
  "server": "cloudflare",
  "poweredBy": null,
  "contactEmail": "help@allbirds.com",
  "contactEmails": ["help@allbirds.com"],
  "contactPhones": [],
  "facebookUrl": "https://www.facebook.com/weareallbirds",
  "instagramUrl": "https://www.instagram.com/allbirds",
  "linkedinUrl": null,
  "xUrl": "https://x.com/allbirds",
  "youtubeUrl": "https://www.youtube.com/channel/UCnGErLCau5qNJ0Xwe6uEyTw",
  "tiktokUrl": "https://www.tiktok.com/@weareallbirds",
  "contactOptOut": false,
  "technologyCount": 14,
  "technologyNames": "Shopify, Microsoft 365, Apple Pay, PayPal, Cloudflare, Cursor, DocuSign, Google Tag Manager, HSTS, HTTP/3, Miro, Open Graph, Priority Hints, Swiper",
  "cms": null,
  "ecommerce": "Shopify",
  "analytics": null,
  "tagManagers": "Google Tag Manager",
  "advertising": null,
  "marketingAutomation": null,
  "crm": null,
  "email": "Microsoft 365",
  "liveChat": null,
  "abTesting": null,
  "paymentProcessors": "Apple Pay, PayPal",
  "cdn": "Cloudflare",
  "hosting": null,
  "webServers": null,
  "jsFrameworks": null,
  "webFrameworks": null,
  "programmingLanguages": null,
  "cookieConsent": null,
  "security": "HSTS",
  "technologies": [
    {
      "name": "Shopify",
      "categories": [
        "Ecommerce"
      ],
      "version": null,
      "confidence": 100,
      "detectedFrom": [
        "html",
        "meta",
        "script"
      ],
      "website": "https://shopify.com"
    },
    {
      "name": "Microsoft 365",
      "categories": [
        "Webmail",
        "Email"
      ],
      "version": null,
      "confidence": 100,
      "detectedFrom": [
        "dns"
      ],
      "website": "https://www.microsoft.com/microsoft-365"
    },
    {
      "name": "Apple Pay",
      "categories": [
        "Payment processors"
      ],
      "version": null,
      "confidence": 100,
      "detectedFrom": [
        "html"
      ],
      "website": "https://www.apple.com/apple-pay"
    }
  ],
  "error": null,
  "errorMessage": null,
  "detectedAt": "2026-10-07T15:22:14.502Z",
  "schemaVersion": "1.0"
}
```

### Pricing

Pay per website analysed, no subscription, no proxy costs, plus a tiny start fee per run ($0.0005). See the **Pricing** tab for current prices: one event per **website analysed**, cheaper on higher Apify plans. All columns, versions and DNS-based detections are included in that price. Websites that cannot be loaded are free; if a run keeps hitting them (for example a list of dead domains), it stops early and says so, so check the list and run the rest again.

Websites that cannot be analysed are **free**: no DNS, timeouts, HTTP errors, bot-protection pages, robots.txt refusals, invalid or duplicate domains. The run never spends more than the maximum cost you set.

**Free Apify plan:** each run analyses up to 10 websites, so you can check the output. A paid Apify plan removes this limit.

### Use it from code, automations or AI agents

**API (one call, results returned directly):**

```bash
curl -X POST "https://api.apify.com/v2/acts/plainrows~website-tech-stack/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domains": ["shopify.com", "wordpress.org"]}'
```

**n8n, Make, Zapier:** use the Apify integration, pick `plainrows/website-tech-stack`, and map the dataset items to Google Sheets, HubSpot, Airtable or your database.

**AI agents (MCP):** add `https://mcp.apify.com?tools=plainrows/website-tech-stack` to Claude, Cursor or any MCP client. The agent gets a typed tool and pays per website.

### How detection works (and its limits)

- The homepage is fetched like a polite crawler (`Mozilla/5.0 (compatible; PlainRows/1.0; +https://apify.com/plainrows)`), following redirects, with a 15-second timeout and a 2 MB size cap. **robots.txt is respected**: a site that forbids automated visits of its homepage is skipped (free).
- Fingerprints are matched on the **response headers, cookies, HTML, meta tags, script URLs, inline scripts and styles, page text, robots.txt and the URL**, plus **DNS records** (MX, TXT, NS, SOA, CNAME): that is how e-mail providers (Google Workspace, Microsoft 365...) and verified SaaS accounts are found.
- Rules that need a real browser are not used: JavaScript variables set by external scripts, CSS selectors on content built by JavaScript, network requests made after loading. Tools injected only by JavaScript (for example Google Analytics loaded through Google Tag Manager) can therefore be missed; the tag manager itself is found.
- Sites protected by aggressive bot protection (Cloudflare challenges, DataDome, PerimeterX, AWS WAF) or that block crawlers return a free `BLOCKED_BY_BOT_PROTECTION` or `HTTP_ERROR` row. On a test list of 99 very large brand websites, 79 were analysed; the 20 others were mostly big retailers and media sites behind bot protection.
- Versions are shown only when the site exposes them (meta generator, script file names, headers).

### What this is not

- Not BuiltWith or Wappalyzer, and not affiliated with them: no historical data, no technology spend. It reports what each homepage shows today.
- It analyses the homepage only, not every page of the site: an e-mail shown only on a contact page is not found.
- Not a people finder: contact columns hold only what the business publishes on its homepage (see below).

### Personal data and GDPR

Contact columns contain only what each business publishes on its own homepage: no guessed addresses, nothing bought or looked up elsewhere. Personal social profiles (LinkedIn `/in/` pages, personal Facebook profiles) are dropped, and team or staff pages are never read. When the homepage explicitly objects to solicitation (for example "Widerspruch gegen Werbe-E-Mails", "no unsolicited sales calls", "pas de démarchage"), no e-mail, phone or social profile is returned for that site and `contactOptOut` is `true`. A published business e-mail can still name a person: you are responsible for using the data lawfully (GDPR, ePrivacy and anti-spam rules, for example a documented legitimate interest for B2B outreach and an easy way to object). To have a website excluded, open an issue in the **Issues** tab of this Actor on Apify Store.

### Credits and license

Technology fingerprints come from the open-source [webappanalyzer](https://github.com/enthec/webappanalyzer) project (a continuation of the original Wappalyzer fingerprints), licensed under the GNU GPL-3.0. Thanks to its maintainers and contributors. The patterns are used unchanged (fields not needed for detection, such as descriptions and icons, are left out), plus small PlainRows changes (extra Next.js patterns, a stricter Apple iCloud Mail rule); the detection code follows the same matching rules (patterns, confidence, versions, implies and excludes).

### Run summary

Each run stores a summary in the key-value store (`OUTPUT`): websites analysed, websites that could not be loaded and why (`failuresByReason`), duplicates and invalid domains, and anything skipped because of the free-plan or budget limit.

### FAQ

**How do I find out what a website is built with?**
Paste one or many domains (up to 10,000 per run) and run: one row per website with its CMS, ecommerce platform, analytics, CDN, hosting, frameworks, payment and marketing tools, and email provider.

**Is this BuiltWith or Wappalyzer?**
No, and not affiliated with them. It detects technologies from each homepage today, like a bulk Wappalyzer lookup; there is no historical data or technology spend.

**Does it scan the whole site?**
No: the homepage only.

**Can I find all Shopify or WordPress sites?**
No: you bring the list of domains, it tells you what each one uses. Filter the results by technology afterwards.

**Does it return e-mails?**
Yes, the ones the homepage shows (`contactEmail`, `contactEmails`), with phone links and business social profiles, at no extra cost (homepage only). Sites that object to solicitation get empty contact columns (`contactOptOut: true`).

### More PlainRows tools

Same pay-per-result pricing, same clean JSON, built to chain together in n8n, Make, Zapier or AI agents.

- **SEO and keywords:** [Keyword Search Volume, CPC & Difficulty](https://apify.com/plainrows/keyword-search-volume) · [Keyword Ideas Generator](https://apify.com/plainrows/keyword-ideas-generator) · [Google Autocomplete & People Also Ask](https://apify.com/plainrows/google-autocomplete-questions) · [Google Trends Explorer](https://apify.com/plainrows/google-trends-explorer) · [Website Organic Traffic & Top Keywords](https://apify.com/plainrows/domain-seo-overview) · [Bulk Domain Authority Checker](https://apify.com/plainrows/domain-authority-checker) · [Backlink Checker](https://apify.com/plainrows/backlink-checker) · [Broken Link Checker](https://apify.com/plainrows/broken-link-checker) · [AI Search Visibility Tracker (ChatGPT, Gemini, AI Mode)](https://apify.com/plainrows/ai-search-brand-visibility)
- **Leads and companies:** [Google Maps Scraper](https://apify.com/plainrows/google-maps-businesses) · [ATS Jobs Scraper (Greenhouse, Lever, Ashby, SmartRecruiters)](https://apify.com/plainrows/ats-job-postings) · [Google Jobs Scraper](https://apify.com/plainrows/google-jobs-scraper) · [Google Ads Transparency Scraper](https://apify.com/plainrows/google-ads-transparency) · [Company Registry Lookup (SIRENE, LEI, Brreg)](https://apify.com/plainrows/company-registry-lookup) · [Public Tenders Search (EU TED & UK)](https://apify.com/plainrows/public-tenders-search)
- **E-commerce and travel:** [Amazon Product Search Scraper](https://apify.com/plainrows/amazon-product-search) · [Google Shopping Prices Scraper](https://apify.com/plainrows/google-shopping-prices) · [Google Hotels Prices Scraper](https://apify.com/plainrows/google-hotels-prices)
- **Content and media:** [Google News Scraper](https://apify.com/plainrows/google-news-scraper) · [YouTube Search Scraper](https://apify.com/plainrows/youtube-search-scraper) · [Google Images Scraper](https://apify.com/plainrows/google-images-scraper) · [Website Screenshot API](https://apify.com/plainrows/website-screenshot) · [App Reviews Scraper (Google Play & App Store)](https://apify.com/plainrows/app-reviews-scraper)

**Compared with other APIs:** [Wappalyzer API alternative](https://nadaho.github.io/plainrows/wappalyzer-api-alternative/)

### Support

Missing a technology, or a wrong detection? Open an issue on this page with the domain. Issues are read and answered.

# Actor input Schema

## `domains` (type: `array`):

Domains or URLs, one per line: "shopify.com", "https://www.example.org/page". The homepage of each site is analysed ("www." and paths are ignored). Up to 10,000 per run; duplicates are removed.

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

Hide technologies detected with a lower confidence (0 = show all, like Wappalyzer; 100 = only certain detections). It does not change the price.

## Actor input object example

```json
{
  "domains": [
    "shopify.com",
    "wordpress.org",
    "nextjs.org"
  ],
  "minConfidence": 0
}
```

# 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 = {
    "domains": [
        "shopify.com",
        "wordpress.org",
        "nextjs.org"
    ]
};

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

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

```

## MCP server setup

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