# Website Tech Stack Detector & Company Profile (`maliksaid/website-tech-stack`) Actor

Detect the tech stack of any website: CMS, ecommerce platform, analytics, tag managers, payments, CDN and hosting, each with evidence. Adds company profile fields from the homepage: title, description, logo, social links and contact page.

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

## Pricing

from $4.00 / 1,000 domain profiles

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 Technology Detector & Company Profile

Website Technology Detector finds the tech stack of any website from its homepage. Give it a list of domains. For each domain it returns the CMS, ecommerce platform, analytics, tag managers, payments, CDN and hosting it detects. Every technology comes with evidence: the header, script, meta tag or HTML that matched.

Each row also holds company profile fields from the same homepage: page title, meta description, logo, company social pages, contact page URL and JSON-LD organisation details. Use it for lead lists, sales research, competitor research and SEO audits.

It is a BuiltWith and Wappalyzer alternative built on open fingerprints. It reads one robots.txt file and one homepage per domain, with no browser.

### Website technology data you get

One row per domain. The main fields:

| Field | What it holds |
|---|---|
| `domain`, `finalUrl`, `statusCode` | The domain and its homepage after redirects |
| `title`, `description`, `language`, `siteName` | Homepage title, meta description, language and Open Graph site name |
| `cms`, `ecommerce`, `analytics`, `tagManagers`, `payments` | Detected technologies, grouped for spreadsheets |
| `cdn`, `hosting`, `webServers`, `frameworks`, `marketing` | More groups |
| `liveChat`, `crm`, `cookieConsent`, `security`, `abTesting`, `reviews`, `pageBuilders`, `emailTools` | More groups for lead lists |
| `technologies` | Every technology with categories, version, confidence (0 to 100) and up to 3 evidence lines |
| `technologyNames`, `technologyCount` | All technology names in one list |
| `logoUrl`, `faviconUrl` | Company logo and favicon |
| `linkedinUrl`, `twitterUrl`, `facebookUrl`, `instagramUrl`, `youtubeUrl`, `githubUrl`, `tiktokUrl` | Company social pages linked from the homepage |
| `contactPageUrl`, `aboutPageUrl`, `careersPageUrl` | Pages on the same site |
| `organization` | JSON-LD organisation name, legal name, logo, founding date, address locality and country, and `sameAs` links |
| `server`, `poweredBy`, `generator` | Server headers and the generator meta tag |
| `stackHash` | Short hash of the technology list. It changes when the stack changes |

The Actor saves company-level data only. It never saves email addresses, phone numbers or names of people. LinkedIn personal profiles are skipped.

### Example output

A real row for allbirds.com, shortened:

```json
{
    "domain": "allbirds.com",
    "finalUrl": "https://www.allbirds.com/",
    "statusCode": 200,
    "title": "Allbirds: Comfortable, Sustainable Shoes & Apparel",
    "siteName": "Allbirds",
    "ecommerce": ["Shopify"],
    "tagManagers": ["Google Tag Manager"],
    "payments": ["Apple Pay"],
    "cdn": ["Cloudflare"],
    "instagramUrl": "https://www.instagram.com/allbirds",
    "tiktokUrl": "https://www.tiktok.com/@weareallbirds",
    "server": "cloudflare",
    "technologyCount": 9,
    "technologies": [
        {
            "name": "Cloudflare",
            "categories": ["CDN"],
            "version": null,
            "confidence": 100,
            "website": "https://www.cloudflare.com",
            "evidence": ["header server \"cloudflare\"", "header cf-cache-status", "header cf-ray"]
        },
        {
            "name": "Shopify",
            "categories": ["Ecommerce"],
            "version": null,
            "confidence": 100,
            "website": "https://shopify.com",
            "evidence": ["meta shopify-digital-wallet"]
        }
    ],
    "stackHash": "2203e6c8efdf",
    "fingerprintsVersion": "2026-10-19"
}
```

### How to detect the tech stack of a list of websites

1. Paste your domains into **Domains or website URLs**, one per line. `example.com`, `www.example.com` and full URLs all work.
2. Set **Maximum domains to save**. Set 0 for no limit.
3. Run the Actor. Open the **Overview** table, or the **Technologies with evidence** view for one row per technology.
4. Domains the Actor could not read are listed in the `FAILED_DOMAINS` record of the run's key-value store, with the reason.

#### Find sites that use one technology

Fill **Only keep domains using these technologies**, for example `Shopify` or `WordPress`. A category name such as `Ecommerce` also works. Other domains are dropped and not charged.

#### Track tech stack changes

Turn on **Monitor mode** and schedule the Actor with the same domain list. A domain is saved again only when its technology list changes.

### Input

```json
{
    "domains": ["wordpress.org", "www.mozilla.org", "books.toscrape.com"],
    "onlyWithTechnologies": [],
    "monitorMode": false,
    "maxItems": 100
}
```

### Pricing

Pay per event:

- $0.02 per run start.
- $0.004 per domain row saved, which is $4 per 1,000 domains.

Domains that are skipped (robots.txt, errors, bot checks) are not charged. A run of 200 domains costs about $0.82.

### How the detection works

The Actor uses the open webappanalyzer fingerprints, which continue the Wappalyzer fingerprint set. They cover about 7,600 technologies. It checks response headers, cookie names, meta tags, script URLs, inline scripts, HTML, DOM selectors, inline CSS and robots.txt.

It runs without a browser. So technologies that only show up after JavaScript runs can be missed. The `confidence` field shows how sure each match is. The `evidence` field shows what matched, so you can check it.

### Data sources and use

- The Actor reads robots.txt before each homepage and skips any homepage it disallows. A redirect to another host is checked against that host's robots.txt too.
- It does not try to pass CAPTCHAs or bot checks. Such pages are skipped and listed.
- It sends at most one robots.txt request and one homepage request per domain. A network error gets one retry.
- Only list sites you have a right to check. You are responsible for how you use the data.
- Fingerprint data: github.com/enthec/webappanalyzer, licensed GPL-3.0.

### Run time and memory

The default input of 3 domains finishes in a few seconds. A test run of 40 domains took 16 seconds on Apify at 512 MB. The Actor reads more homepages at once when you give it more memory. Keep at least 512 MB for long lists. At that speed, about 5,000 domains should fit in the default 1-hour timeout. This is an estimate.

### FAQ

#### Is this a BuiltWith or Wappalyzer alternative?

Yes. It uses the same kind of fingerprints as Wappalyzer and returns one row per domain with evidence for each technology. It does not query BuiltWith or Wappalyzer.

#### Can I find sites that use a live chat or a CRM?

Yes. Each row has `liveChat` and `crm` columns. To keep only matching sites, set **Only with technologies** to a category, for example `["Live chat"]` or `["CRM"]`, or to a product such as `["Intercom"]`.

#### Does it find emails or phone numbers?

No. It returns company-level fields only. Use the `contactPageUrl` field to find the company's contact page.

#### Why was a domain skipped?

Open the `FAILED_DOMAINS` record. Common reasons: robots.txt disallows the homepage, the site answered 403, or it shows a bot check.

#### Can an AI agent use it?

Yes. The input is a plain list of domains and the output is flat JSON.

### Support

Open an issue on the Actor's Issues tab. Tell us the domain and what you expected to see.

# Actor input Schema

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

One domain or URL per line, for example example.com or https://www.example.com. The Actor reads the homepage of each one. Duplicates are removed.

## `onlyWithTechnologies` (type: `array`):

Keep a domain only if it uses at least one of these technologies or categories, for example Shopify, WordPress or Ecommerce. Leave empty to keep every domain.

## `monitorMode` (type: `boolean`):

Save a domain only when its technology list differs from earlier monitor-mode runs with the same state key. Schedule the Actor with this on to track stack changes.

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

Name of the memory that monitor mode uses. Use a different key for each separate domain list.

## `maxItems` (type: `integer`):

Stop after saving this many domain rows. Set 0 for no limit.

## Actor input object example

```json
{
  "domains": [
    "wordpress.org",
    "www.mozilla.org",
    "books.toscrape.com"
  ],
  "onlyWithTechnologies": [],
  "monitorMode": false,
  "stateKey": "default",
  "maxItems": 100
}
```

# Actor output Schema

## `results` (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": [
        "wordpress.org",
        "www.mozilla.org",
        "books.toscrape.com"
    ],
    "maxItems": 100
};

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

# Run the Actor and wait for it to finish
run = client.actor("maliksaid/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": [
    "wordpress.org",
    "www.mozilla.org",
    "books.toscrape.com"
  ],
  "maxItems": 100
}' |
apify call maliksaid/website-tech-stack --silent --output-dataset

```

## MCP server setup

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