# Tech Stack & Infrastructure Lookup (`catalyst_prime/tech-stack-lookup`) Actor

Bulk domain to technology and infrastructure lookup: detected tech stack plus DNS, CDN, TLS certificate issuer and mail provider.

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

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## Tech Stack & Infrastructure Lookup

Bulk domain lookup. For each domain you get the detected technology stack (CMS, analytics,
frameworks, etc.) plus four things most tech-stack tools don't report: **DNS records, CDN,
TLS certificate issuer, and mail provider.**

No headless browser, no residential proxy, one HTTP GET plus a handful of DNS/TLS lookups per
domain. Built to run in 256 MB and finish in seconds.

### Input

Give it one or more domains via `urls` (a JSON array, a single string, or a comma/newline
separated list of domains). If you're switching from another tech-detection tool, you can also
use whichever of these field names your existing input already uses. This Actor accepts all of
them as aliases for the same thing: `startUrls`, `domains`, `websites`, `targetUrls`, `url`.
Supply domains in any one of them, or mix several; they are combined and deduplicated.

| Field | Type | Default | Description |
|---|---|---|---|
| `urls` | array of strings | none | Domains or URLs to look up. Supply this or any one alias below. |
| `startUrls` | array | none | Alias of `urls`. Accepts plain strings or `{"url": "..."}` objects. |
| `domains` | array | none | Alias of `urls`. |
| `websites` | array | none | Alias of `urls`. |
| `targetUrls` | array | none | Alias of `urls`. |
| `url` | string | none | Alias of `urls` for a single domain. |
| `categories_filter` | array of strings | none (all categories) | Only report technologies in these categories, e.g. `["CMS", "Analytics"]`. |
| `include_versions` | boolean | `true` | Include the detected version number, when found. |
| `include_confidence` | boolean | `true` | Include a 0-100 confidence score per technology. |
| `timeout_seconds` | integer | `15` | Per-domain page-load timeout, clamped to 3-60. |

### Output

One dataset item per input domain:

```json
{
  "url": "https://stripe.com",
  "domain": "stripe.com",
  "technologies": [
    { "name": "Nginx", "categories": ["Web servers", "Reverse proxies"], "confidence": 85 }
  ],
  "techNames": ["Amazon S3", "Amazon Web Services", "HSTS", "Nginx"],
  "techCount": 4,
  "dns": {
    "a": ["198.137.150.231", "198.202.176.231"],
    "ns": ["ns-1087.awsdns-07.org", "ns-423.awsdns-52.com"]
  },
  "cdn": "Cloudflare",
  "tls": {
    "issuer": "DigiCert Global G3 TLS ECC SHA384 2020 CA1",
    "subject": "stripe.com",
    "notAfter": "2026-11-12T23:59:59Z",
    "daysUntilExpiry": 49
  },
  "mail": {
    "records": ["aspmx.l.google.com", "alt1.aspmx.l.google.com"],
    "provider": "Google Workspace"
  },
  "httpStatus": 200,
  "charged": false
}
```

`cdn` is omitted when no CDN was detected. `tls`/`dns`/`mail` always appear, each with its own
`error` field when that particular lookup failed. A domain that can't be reached still gets a
full row showing what *could* be resolved, so nothing is silently dropped. `charged` reports
whether this row's lookup was billed (see Pricing).

### Compatibility

This Actor's input schema mirrors the market's existing tech-detection tool so you can swap
tools without editing a saved input. What's new here: DNS records, CDN, TLS certificate issuer,
and mail provider, none of which the incumbent reports.

### Pricing

**Free.** This Actor has no price set, so every run costs you only your own Apify platform
usage (about $0.00002 of compute per domain, measured over a 10-domain run). The `charged`
field in each output row stays `false` while the Actor is free.

The code does support pay-per-event billing on a single `domain-lookup` event, priced per
successfully processed domain, if a price is ever set on the Apify Console. A domain that fails
entirely (unreachable, no DNS, no TLS, no mail records) would not be charged. Nothing is
hardcoded in the Actor: it reads its own current price from the platform at startup and runs
unmetered when there isn't one.

### Notes on the technology confidence score

The detection engine ([`wappalyzergo`](https://github.com/projectdiscovery/wappalyzergo)) does
not expose a numeric confidence score through its public API: it uses one internally to decide
whether a match counts at all, then discards it. When `include_confidence` is on, this Actor
reports a coarse two-tier estimate instead of pretending to replicate a score it doesn't have:
`100` when a version number was extracted (implies a specific, high-precision pattern match),
`85` otherwise.

# Actor input Schema

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

List of domains or URLs to look up. Bare domains (example.com) are accepted as-is.

## `startUrls` (type: `array`):

Alias of 'urls' for compatibility with tools that use this field name. Accepts plain strings or {"url": "..."} objects.

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

Alias of 'urls' for compatibility with tools that use this field name.

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

Alias of 'urls' for compatibility with tools that use this field name.

## `targetUrls` (type: `array`):

Alias of 'urls' for compatibility with tools that use this field name.

## `url` (type: `string`):

Alias of 'urls' for a single domain/URL.

## `categories_filter` (type: `array`):

Only report detected technologies in these categories (e.g. "CMS", "Analytics"). Leave empty to report every category.

## `include_versions` (type: `boolean`):

Include the detected version number for each technology, when one was found.

## `include_confidence` (type: `boolean`):

Include a confidence score (0-100) for each detected technology.

## `timeout_seconds` (type: `integer`):

How long to wait for each domain's page to load before giving up. Clamped to 3-60.

## Actor input object example

```json
{
  "urls": [
    "apify.com"
  ],
  "include_versions": true,
  "include_confidence": true,
  "timeout_seconds": 15
}
```

# Actor output Schema

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

The full set of lookup results, one item per input domain.

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

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

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

```

## MCP server setup

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

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/20Wv6tk7ZIMUzLnfl/builds/nfGo4hcdnUJ0YNg1W/openapi.json
