# Tech Stack Lookup API - Detect Website Technologies (`nabeelbaghoor/tech-stack-lookup-api`) Actor

Detect the technologies behind any website: CMS, ecommerce platform, analytics, ads, payments, frameworks and more, with versions, categories and last confirmed dates. Optionally add company details, verified emails, phone numbers, social profiles and traffic signals. Bring your own key.

- **URL**: https://apify.com/nabeelbaghoor/tech-stack-lookup-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Business, Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 website technology profile returneds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Tech Stack Lookup API - Detect Website Technologies

Find out what any website runs, and get the company behind it in the same row: CMS, ecommerce platform, analytics, advertising, payments, frameworks and thousands more, with versions and last confirmed dates.

### What it does

- **Identifies the stack, with versions.** Each technology comes back with a machine readable slug, a display name, its categories, the versions detected and the date it was last confirmed on the site.
- **Carries a CPE identifier.** Where the provider has one, each technology includes its Common Platform Enumeration name, which is what you join against a CVE feed to turn a technology list into a vulnerability list.
- **Adds the company, on request.** Company name, industry, description, locations, size, type and founding year, so a URL becomes an account rather than a hostname.
- **Adds contact details, on request.** Phone numbers, email addresses, verified and safe to send email addresses and WhatsApp numbers found on the site's own contact page.
- **Adds social handles, on request.** LinkedIn, X, Facebook, Instagram, GitHub, TikTok, YouTube and Pinterest.
- **Adds signals, locale and security, on request.** An estimated technology spend band and a traffic level, the site's canonical country, region and languages, and its TLS certificate details with SPF and DMARC presence.
- **Waits out a crawl instead of writing a site off.** A website the provider has never indexed starts a crawl and answers with nothing. Repeating the request inside the hour is free, so this actor keeps a waiting list and comes back for those sites rather than reporting them as empty.
- **Chooses a scan shape that actually works.** A deep scan takes ten sites per request. A shallow scan answers in the same request but takes one site at a time. A live deep scan needs a callback endpoint on your own server, so the run falls back to a live shallow scan and says so rather than returning empty rows.
- **Reads history as well as the present.** Age filters with monthly grouping return results month by month, which is how you see when something was added or dropped.
- **Keeps the misses.** A site with no detected technologies still produces a row saying so, and it is not charged for.

### Input

#### Look up a list of websites

```json
{
  "urls": ["https://shopify.com", "example.com", "https://notion.so"],
  "maxResults": 100
}
```

#### Enrich with company and contact details

```json
{
  "urls": ["https://example.com"],
  "sets": ["company", "contact", "social", "signals"]
}
```

#### Get the freshest possible answer for one site

```json
{
  "urls": ["https://example.com"],
  "live": true,
  "maxAgeMonths": 1
}
```

### Example output

One row per website.

```json
{
  "url": "https://example.com",
  "domain": "example.com",
  "found": true,
  "technologyCount": 24,
  "technologies": ["Craft CMS", "Cloudflare", "Google Analytics"],
  "technologyDetails": [
    {
      "slug": "craft-cms",
      "name": "Craft CMS",
      "cpe": "cpe:2.3:a:craftcms:craft_cms:*:*:*:*:*:*:*:*",
      "categories": ["CMS"],
      "categorySlugs": ["cms"],
      "versions": ["3.0.0"],
      "confirmedAt": "2021-02-08T22:40:37.000Z"
    }
  ],
  "categories": ["CMS", "CDN", "Analytics"],
  "trafficRank": 1000,
  "crawlPending": false,
  "companyName": "Example Inc.",
  "industry": "Design",
  "companySize": 240,
  "verifiedEmail": ["hello@example.com"],
  "linkedin": ["company/example"],
  "technologySpend": "medium",
  "ipCountry": "US"
}
```

### Frequently asked questions

#### What technologies can it detect?

Content management systems, ecommerce platforms, analytics and tag managers, advertising and tracking pixels, payment processors, marketing automation, CDNs, hosting providers, web servers, JavaScript frameworks and libraries, widgets, live chat, and many more. Each detection carries the categories it belongs to, so results can be grouped without a lookup table of your own.

#### Why did a website come back with no technologies?

Usually because the provider has not indexed it yet. When that happens the response says a crawl has been started, and the answer is ready minutes later. This actor keeps those sites on a waiting list and asks again, because repeating the request inside the hour costs nothing. If a site is still crawling when the run ends, its row says so, and running the same input again will pick the result up.

#### What is the difference between a deep scan and a shallow scan?

A deep scan follows internal links and indexes several pages, which finds more technologies, and it accepts ten websites per request. A shallow scan looks at the homepage only, answers within the same request, and takes one website at a time. Deep is the default because it is more complete; shallow is the one to pick when you need an answer in the same call.

#### Can I force a live scan?

Yes, and it is worth knowing what happens. A live scan combined with a deep scan is only completed through a callback URL on a server you control, which an actor run cannot host, so this actor runs a live shallow scan instead and says so in the log. That returns fresh results for the homepage within the same request.

#### Can I get email addresses and phone numbers?

Yes, by adding the contact field set. It returns phone numbers, email addresses, verified and reachable email addresses, safe to send email addresses and WhatsApp numbers, all found on the website's own pages. Add the company and social sets alongside it to get the full account picture in one row.

#### Can I use this to find security exposure?

Partly, and honestly the useful part is the CPE identifier. Every technology carries its Common Platform Enumeration name where one exists, which is the identifier CVE databases are keyed on, so a stack becomes a list of things to check. The security field set adds TLS certificate details and whether the domain publishes SPF and DMARC records.

#### How do I see when a site adopted or dropped something?

Turn off merging of monthly results and set an age window with the minimum and maximum age fields. The provider then returns results grouped by month, up to twelve months per request, so a technology appearing or disappearing is visible rather than inferred.

#### Do I need my own API key?

Yes. This actor is bring your own key: it calls the technology lookup API using your own account key, so you keep your own credit balance, your own rate limits and your own agreement with the provider. The provider requires a business plan for this API.

#### How much does a run cost?

Charging is per row, and only websites that came back with technologies are charged. Websites the provider identified nothing on, websites still being crawled and refused requests are all free. Note that the provider also spends its own credits per URL, one for a normal lookup and five for a live deep scan, separately from what is charged here.

#### What are the rate limits?

The provider allows ten requests a second with up to ten URLs in each. This actor paces itself at 120 requests a minute by default and is capped at 300, which leaves headroom on an account that is also serving your own application.

### Keyword map

tech stack lookup API, website technology detection, technographics API, what CMS does a site use, ecommerce platform detection, detect Shopify, detect WordPress, technology fingerprinting API, CPE identifier lookup, CVE exposure from tech stack, website enrichment API, company data from domain, verified email from website, social profiles from website, technology spend estimate, traffic level signal, lead qualification by technology, competitor stack monitoring, SaaS install base research, domain to technology profile

# Actor input Schema

## `apiKey` (type: `string`):

Your own account's API key for this provider, created in its dashboard. Bring your own key: nothing is shared between runs and the key is never written to the dataset.

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

Websites to look up, one per line. A bare domain works and is given a scheme for you, so a column pasted out of a CRM is fine. Ten websites go into each request on the default deep scan.

## `sets` (type: `array`):

Additional field sets to return alongside the technologies. Company adds name, industry, size, type and founding year. Contact adds phone numbers, emails, verified emails and WhatsApp numbers. Social adds LinkedIn, X, Facebook, Instagram, GitHub, TikTok, YouTube and Pinterest handles. Signals adds an estimated technology spend band and a traffic level.

## `live` (type: `boolean`):

Scan the website now instead of reading the provider's cached record. Slower, more expensive in credits, and used with a shallow scan because a live deep scan is only completed through a callback URL on a server of your own, which an actor run cannot host.

## `recursive` (type: `boolean`):

Follow internal links to index several pages of a site, which finds more technologies. On by default and the only mode that takes ten websites per request. Turning it off scans the homepage only, one website at a time, and always answers within the same request.

## `denoise` (type: `boolean`):

Leave out detections the provider is not confident about. On by default. Turning it off returns more technologies per site and more false positives with them.

## `maxAgeMonths` (type: `integer`):

Only return technologies verified within this many months. The provider defaults to 2. Use 1 for the freshest and fewest results, or a higher number for more results that are likelier to include technologies a site has since dropped.

## `minAgeMonths` (type: `integer`):

Only return technologies verified at least this many months ago. Used with a higher maximum age and monthly grouping turned on, this is how you read a site's history rather than its present.

## `squash` (type: `boolean`):

Merge results from several months into one set, which is what you want for a current snapshot. Turning it off groups results by month, which is how you see when a technology appeared or disappeared.

## `crawlRetries` (type: `integer`):

A website the provider has never indexed starts a crawl and answers with no technologies. Repeating the request inside the hour is free, and the crawl usually finishes within minutes, so this run comes back for those websites this many times before writing them off.

## `crawlWaitMinutes` (type: `integer`):

How long to wait before asking again for websites that are still being crawled. The provider suggests five minutes, and a crawl can take up to fifteen.

## `skipEmptyResults` (type: `boolean`):

Leave websites with no detected technologies out of the dataset. They are never charged for either way, so this is about the shape of your output.

## `maxResults` (type: `integer`):

Stop after this many rows. One website produces one row, so this is a ceiling on the websites a run will store.

## `requestsPerMinute` (type: `integer`):

How fast this actor calls the provider. The documented limit is ten requests a second, so this is capped at 300 a minute, which leaves headroom on an account that is also serving your own application.

## Actor input object example

```json
{
  "urls": [
    "https://shopify.com"
  ],
  "sets": [],
  "live": false,
  "recursive": true,
  "denoise": true,
  "squash": true,
  "crawlRetries": 2,
  "crawlWaitMinutes": 5,
  "skipEmptyResults": false,
  "maxResults": 100,
  "requestsPerMinute": 120
}
```

# Actor output Schema

## `websites` (type: `string`):

One row per website, alongside the URL it was requested from.

# 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": [
        "https://shopify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/tech-stack-lookup-api").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": ["https://shopify.com"] }

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/tech-stack-lookup-api").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": [
    "https://shopify.com"
  ]
}' |
apify call nabeelbaghoor/tech-stack-lookup-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/tech-stack-lookup-api"
        }
    }
}

```

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/8YMfNNtPwf3pf88m5/builds/EgpihyhS7809M2Wq6/openapi.json
