Tech Stack Detector (Apify Actor)
Find the CMS, framework, analytics and CDN of any website list for a flat $2 per 1,000 sites, with evidence per detection. No API key, unreachable URLs free, set a max spend. Runs as an Apify Actor, callable from MCP clients via the Apify MCP server (https://mcp.apify.com/?actors=pennydata/website-tech-stack-detector).
Hosted MCP Server
npx add-mcp 'https://mcp.apify.com/?actors=pennydata/website-tech-stack-detector'Installs into Claude Code, Codex, Cursor and more
Documentation
Tech Stack Detector - Website CMS, Framework & Analytics (pennydata/website-tech-stack-detector) Actor
Tech stack detector: paste website URLs, get one row each: CMS (WordPress, Shopify...), frameworks, server/CDN, analytics, with evidence. $0.002 per site, unreachable URLs free. Click Start: the 3 prefilled sites cost $0.006.
- URL: https://apify.com/pennydata/website-tech-stack-detector.md
- Developed by: Penny Data (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 $1.40 / 1,000 url analyzeds
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 section below.
Each client library has reference documentation the quickstart does not restate: JavaScript/TypeScript (npm install apify-client) and Python (pip install apify-client).
README
Tech Stack Detector & Change Monitor - Wappalyzer Alternative
Tech stack detector: paste website URLs, click Start, and get each site's CMS, framework, analytics and CDN with the evidence for every detection. $2 per 1,000 sites ($0.002 per site), failed URLs free, no API key, one plain HTTP request per site. The 3 prefilled sites (wordpress.org, shopify.com, github.com) run as is in about 20 seconds and cost $0.006. A Wappalyzer and BuiltWith alternative: every detection lists its header, meta tag, script URL or cookie name.
Example input (the form opens with this prefill; click Start):
{"urls":[{"url":"https://wordpress.org"},{"url":"https://www.shopify.com"},{"url":"https://github.com"}]}
Sample output (real run, 2026-10-22, 3 sites, 3 url-analyzed events = $0.009):
| input | httpStatus | technologies found |
|---|---|---|
| https://wordpress.org | 200 | WordPress, Google Tag Manager, Nginx |
| https://www.shopify.com | 200 | Cloudflare |
| https://github.com | 200 | Contentful, GitHub (hosting) |
Detects WordPress, Shopify, Magento, Next.js, Cloudflare, Google Analytics and about 60 more.
Free to try: a new Apify account includes free monthly platform credit, enough to validate the output on a few dozen sites before you pay anything. This Actor has no hidden minimums: failed items are never billed.
Try it (no code)
Open the Store page and click Try for free. The input form opens with the schema prefill, three sites (https://wordpress.org, https://www.shopify.com, https://github.com), so Start runs as-is. There is no URL parameter that pre-fills custom input; paste your own URLs into urls instead.
Sample output of a real local run on 3 sites (2026-10-22, 3 rows, 3 url-analyzed events):
| input | httpStatus | technologies found |
|---|---|---|
| https://wordpress.org | 200 | WordPress, Google Tag Manager, Nginx |
| https://www.shopify.com | 200 | Cloudflare |
| https://github.com | 200 | Contentful, GitHub (hosting) |
Example output (real run, 2026-10-20)
Input https://wordpress.org, one row, one url-analyzed event:
{
"input": "https://wordpress.org",
"finalUrl": "https://wordpress.org",
"httpStatus": 200,
"totalTechnologies": 3,
"categories": {"CMS": ["WordPress"], "Tag manager": ["Google Tag Manager"], "Web server": ["Nginx"]},
"technologyNames": ["WordPress", "Google Tag Manager", "Nginx"],
"technologies": [
{ "name": "WordPress", "category": "CMS", "evidence": "meta generator \"WordPress 7.2-alpha-64584\"" },
{ "name": "Google Tag Manager", "category": "Tag manager", "evidence": "html GTM noscript iframe" },
{ "name": "Nginx", "category": "Web server", "evidence": "header server" }
],
"capturedAt": "2026-10-20T04:38:05.293Z"
}
Quickstart (one API call)
curl -X POST "https://api.apify.com/v2/acts/pennydata~website-tech-stack-detector/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"urls":[{"url":"https://wordpress.org"}]}'
Or open the Actor in the Console and click Start: the prefilled input (three sites) runs as-is. A BuiltWith / Wappalyzer alternative you pay for per URL, not per month.
How to use Website Tech Stack Detector
- Paste public URLs or bare domains into urls.
- Leave respectRobotsTxt on unless you are entitled to switch it off.
- Click Start.
- Use
technologyNamesfor quick filtering ortechnologiesfor category and evidence.
Coming from magicfingers/techstack-detector? Your existing input works unchanged (urls, navigationTimeoutSecs, maxConcurrency, checkHeaders and the other options are accepted).
Drop-in compatible with misterkhan/website-tech-stack-scanner input (startUrls) and motivational_nickel/website-technology-detector input (urls, verify_ssl).
Also accepted: startUrls (request-list objects like {"url": "https://example.com"} or plain strings), websites (list of domains or URLs), url (single URL) and domains (list), all same as urls. Every row has status (ok or error, with error text); a SUMMARY record in the key-value store counts total, ok, error and charged URLs. Only ok rows are charged.
Monitor competitor tech changes
Run the Actor on a list of competitor or prospect domains, note the run's default dataset ID, then run it again later (or on a weekly schedule) with that ID in compareToDatasetId. Every site then carries added and removed technology names versus the earlier run, so you see a new checkout platform, a dropped analytics tool or a CDN migration without comparing lists by hand. Sites missing from the earlier dataset get previousFound: false. The diff adds no extra charge.
{ "urls": ["https://example.com"], "compareToDatasetId": "<dataset ID of the previous run>" }
Pricing
Pay per event, no subscription and no compute fees on top. Price: $2 per 1,000 sites ($0.002 per URL).
| Event | When it is charged | Price |
|---|---|---|
url-analyzed | One website URL fetched successfully (HTTP below 400) and analyzed for technologies. | $0.002 |
Failed, blocked or unknown items are not billed. Paid Apify plans get volume discounts down to $0.0014 per URL. Set a maximum cost per run in the run options to cap spend.
Example input
{
"urls": [
{
"url": "https://nextjs.org"
}
],
"respectRobotsTxt": true
}
Check client sites for known-vulnerable versions (CVE exposure)
For MSPs and web agencies auditing client sites: set checkCves to true and each item gets the known CVEs for the technology versions the site itself exposes (WordPress and Drupal/Joomla via the meta generator tag, jQuery and Bootstrap via the versioned script file name, Nginx/Apache via the Server header, PHP via X-Powered-By). Lookups use the free NIST NVD CVE API 2.0 by exact CPE name, one request per product+version per run (cached), spaced to respect NVD's public rate limit. There is no extra charge: the price stays $0.002 per site.
{
"urls": ["https://www.python.org", "https://client-site.example"],
"checkCves": true
}
Added fields per item: cves (up to 25, highest CVSS first: id, cvssScore, severity, published, technology, version), cveCount (total found) and maxSeverity. Each entry in technologies also carries a version when the site states one.
{ "input": "https://www.python.org", "maxSeverity": "MEDIUM", "cveCount": 6,
"cves": [{ "id": "CVE-2020-11022", "cvssScore": 6.9, "severity": "MEDIUM", "published": "2020-04-29T22:15:11.903", "technology": "jQuery", "version": "1.8.2" }] }
Honest limits: only versions the page reveals are checked (many sites hide them); a CVE listed for a version does not prove the site is exploitable (backported patches, mitigations), so treat it as a triage list. NVD without a key allows about 5 requests per 30 s, so large lists are slower; add the optional free nvdApiKey to go about 10x faster. Data is NVD's, this actor is not affiliated with or endorsed by NIST.
Details and limits
Give it a list of public website URLs and get back the technologies each site appears to use: CMS, ecommerce platform, analytics and tag managers, CDN and hosting, web server, JS frameworks and libraries, payments, cookie-consent tools. It makes one plain HTTP request per site (no browser), so runs are fast and cheap.
What it does
- Input: a list of public
http(s)URLs (bare domains such asexample.comare accepted and fetched over https). - For each URL it fetches the page once (following up to 5 redirects) and inspects only:
- response headers (
server,x-powered-by,cf-ray,x-vercel-id, ...), - HTML meta tags (
<meta name="generator">), - script
srcURLs and well-known HTML markers (for example__NEXT_DATA__,/wp-content/), - cookie names from
Set-Cookie(names only; cookie values are never read or stored).
- response headers (
- Output per URL:
input,finalUrl,httpStatus,technologyNames(flat list),totalTechnologies(integer count),categories(object grouping names by category, e.g.{"CMS": ["WordPress"], "Analytics": ["Google Tag Manager"]}) andtechnologies(name, category, and the evidence that triggered it),capturedAt. - Lead list: the run's key-value store also holds
leads-by-tech.csv(columnstechnology, category, site url, evidence, sorted by technology) so you get every Shopify, WordPress or HubSpot site in one list, and theSUMMARYrecord hastechnologyCounts(sites per technology). - About 60 technologies are recognised, e.g. WordPress, Shopify, WooCommerce, Magento, Wix, Squarespace, Webflow, Drupal, Next.js, Nuxt, React, Vue.js, Angular, Cloudflare, CloudFront, Fastly, Vercel, Netlify, Google Analytics, Google Tag Manager, Meta Pixel, Hotjar, Stripe.
Limits and honesty notes
- Detection is based on one HTTP request to the URL you give, with no JavaScript execution. Technologies that only show up after client-side rendering, or on other pages of the site, can be missed. A site with no visible signals returns an empty list; that does not prove nothing is used.
- Detection is signature-based and can produce false positives or negatives (for example a CDN header that only reflects a proxy in front of the site, or a site that hides its headers). Treat results as strong hints, not an audit. No version numbers are reported.
- Only the first 1 MB of each page is inspected.
- robots.txt is respected by default (the wildcard
*group; switch off withrespectRobotsTxt: falseonly for sites you are entitled to analyze). The actor identifies itself with the user agentTechStackDetectorBot. - Only public
http(s)URLs: localhost, private and link-local IP ranges, and non-http schemes are rejected, and every redirect hop is re-checked. - Sites behind bot walls, logins or captchas may return an error page or a block status; no proxies, no captcha solving and no evasion are used.
- You are responsible for having the right to analyze the URLs you submit. The actor collects no personal data: only technology signals are extracted, and cookie values are discarded.
Switching from another tech-stack actor
Saved tasks and API calls written for other tech-stack actors run here with only the actor ID changed. Input names checked on 2026-10-21 against the public input schemas of the two most-used rivals, nexgendata/wappalyzer-replacement (about 1,500 users) and automation-lab/tech-stack-detector (about 390 users). This Actor is independent and not affiliated with either.
| Their input | Here |
|---|---|
urls (plain strings or objects) | urls, same |
startUrls, domains, websites, url | same names, accepted |
targetUrls | accepted as an alias of urls |
timeout_seconds | alias of timeoutSecs |
verify_ssl | accepted and ignored |
categories_filter, include_confidence, include_versions | accepted and ignored (not supported; a log line names them). Every detection already lists its evidence; filter by categories in the output |
Output fields differ (technologyNames, categories, technologies with evidence), so check your downstream mapping. Pricing is on the Pricing section above; compare it with your current actor before switching.
Use from Claude, Cursor or any MCP client
Apify's MCP server can expose this actor as a tool. Use this URL (format from the Apify MCP docs, ?tools= takes a comma-separated list of actors):
https://mcp.apify.com/?tools=pennydata/website-tech-stack-detector
Client config (mcpServers format; sign in with OAuth when the client asks):
{"mcpServers": {"apify": {
"url": "https://mcp.apify.com/?tools=pennydata/website-tech-stack-detector"
}}}
Example prompt: "Which CMS and analytics tools does example.com use?"
Related actors
- Shopify Store Leads & Contact Emails: found a Shopify site here? Turn the domain into a lead row with business email, socials and product count.
- Bulk Domain Availability & WHOIS/DNS Lookup: registrar, expiry, nameservers and MX for the same domain list.
- Website Contact Extractor: finds public contact details on the sites you profiled.
- Bulk Email Validator (No SMTP): clean the emails you collect.
FAQ
How accurate is it?
Signature-based on one HTTP request without JavaScript execution, so client-rendered or hidden technologies can be missed. Treat results as strong hints, not an audit.
Is it legal?
It requests only the URL you provide, respects robots.txt by default, stores no cookie values and no personal data.
Need a custom field, a higher volume or a different source?
Open an issue on the Actor page and describe what you need; custom variants are possible.
Is it maintained?
Yes. Reports of breakage are answered through the Issues tab, and runs that fail are not billed.
Built with AI assistance (Claude); maintained by the publisher.
Use cases
- Qualify sales leads by the CMS, ecommerce platform or analytics tool they use.
- Build agency prospect lists, for example every Shopify or WordPress site in a list.
- Competitor research: see which CDN, framework or tag manager rivals run.
- Migration audits: find sites still on a legacy platform.
I built this and earn from its runs. Written with AI assistance (Claude).
Actor input Schema
url (type: string):
Alias for a single URL; same as putting it in "urls".
domains (type: array):
Alias: list of bare domains or URLs, analyzed together with "urls".
urls (type: array):
Public http(s) pages to analyze (bare domains like example.com are accepted). Aliases: "url" (single) and "domains" (list) are also accepted.
startUrls (type: array):
Alias for "urls": request-list objects ({"url": ...}) or plain strings, analyzed together with "urls".
websites (type: array):
Alias: list of websites (bare domains or URLs), analyzed together with "urls".
targetUrls (type: array):
Alias for "urls" (same field name as other tech-stack actors): bare domains or URLs, analyzed together with "urls".
compareToDatasetId (type: string):
Optional. Dataset ID of an earlier run of this Actor. Each site then gets added[] and removed[] technologies versus that run (previousFound=false if the site was not in it). Use with a weekly schedule to monitor competitor tech changes.
checkCves (type: boolean):
For technologies whose version the site exposes (WordPress, Drupal, Joomla, jQuery, Bootstrap, Nginx, Apache, PHP), look up known CVEs in the free NIST NVD API and add cves, cveCount and maxSeverity to each item. Same price per site. Slower: NVD allows about 5 requests per 30 s without a key.
nvdApiKey (type: string):
Optional free key from nvd.nist.gov/developers/request-an-api-key; raises the NVD rate limit about 10x.
respectRobotsTxt (type: boolean):
Skip URLs disallowed for all bots in the site's robots.txt (skipped URLs are not charged).
maxConcurrency (type: integer):
Maximum number of sites analyzed in parallel (1-20).
timeoutSecs (type: integer):
Per-request timeout in seconds (5-60). Alias: "timeout_seconds".
timeout_seconds (type: integer):
Alias for "timeoutSecs".
verify_ssl (type: boolean):
Accepted so inputs saved for motivational_nickel/website-technology-detector run unchanged. Not used.
navigationTimeoutSecs (type: integer):
Alias for "timeoutSecs", accepted so inputs saved for magicfingers/techstack-detector run unchanged. "timeoutSecs" wins when both are set.
waitForSecs (type: integer):
Accepted so inputs saved for magicfingers/techstack-detector run unchanged. Not used: headers, cookies, DNS and page content are always checked.
checkHeaders (type: boolean):
Accepted so inputs saved for magicfingers/techstack-detector run unchanged. Not used: headers, cookies, DNS and page content are always checked.
checkCookies (type: boolean):
Accepted so inputs saved for magicfingers/techstack-detector run unchanged. Not used: headers, cookies, DNS and page content are always checked.
checkDns (type: boolean):
Accepted so inputs saved for magicfingers/techstack-detector run unchanged. Not used: headers, cookies, DNS and page content are always checked.
checkRobotsTxt (type: boolean):
Accepted so inputs saved for magicfingers/techstack-detector run unchanged. Not used: headers, cookies, DNS and page content are always checked.
proxyConfiguration (type: object):
Accepted so inputs saved for similar tech-stack Actors run unchanged. Not used.
Actor input object example
{
"urls": [
{
"url": "https://wordpress.org"
},
{
"url": "https://www.shopify.com"
},
{
"url": "https://github.com"
}
],
"checkCves": false,
"respectRobotsTxt": true,
"maxConcurrency": 5,
"timeoutSecs": 20
}
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
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": [
{
"url": "https://wordpress.org"
},
{
"url": "https://www.shopify.com"
},
{
"url": "https://github.com"
}
]
};
// Run the Actor and wait for it to finish
const run = await client.actor("pennydata/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
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": [
{ "url": "https://wordpress.org" },
{ "url": "https://www.shopify.com" },
{ "url": "https://github.com" },
] }
# Run the Actor and wait for it to finish
run = client.actor("pennydata/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
echo '{
"urls": [
{
"url": "https://wordpress.org"
},
{
"url": "https://www.shopify.com"
},
{
"url": "https://github.com"
}
]
}' |
apify call pennydata/website-tech-stack-detector --silent --output-dataset
MCP server setup
{
"mcpServers": {
"apify": {
"type": "http",
"url": "https://mcp.apify.com/?tools=fetch-actor-details,pennydata/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/HL497t83rI9fiLzLM/builds/iJ7fYd2thgpFWjgjo/openapi.json