Bulk tech stack lookup: check thousands of domains at once
Browser extensions such as Wappalyzer and BuiltWith tell you what one website runs. When you have a spreadsheet of 500 or 50,000 domains (a lead list, a portfolio, a market), you need a batch job instead. This guide shows a free do-it-yourself method, what the paid APIs cost, and how to run the whole list through Bulk Tech Stack Lookup, an Apify actor that returns one row per domain with the tech stack plus DNS, email-security, TLS and AI-crawler data.
Run it on Apify Opens the actor's page on apify.com. A free Apify account is needed to run it.
Only need one site right now? Try the free website tech stack checker: it runs on this site with no sign-up.
Your options at a glance
Prices for the paid services were checked on 2026-10-03 and change often; treat them as a rough guide.
| Option | Good for | Cost | Catch |
|---|---|---|---|
| Wappalyzer or BuiltWith browser extension | Checking one site by hand | Free | One site at a time; no export of a list |
| Wappalyzer API | Developers who need its exact detections | From $250 a month | Monthly commitment |
| BuiltWith plans | Large lead lists by technology, history | From $295 a month | Monthly commitment |
httpx -tech-detect (open source) | Developers comfortable on the command line | Free | Tech only: no DNS, email or TLS grading; you run and maintain it |
| Bulk Tech Stack Lookup on Apify | Lists of any size, no code, CSV/Excel out | Free to run now; planned $3 per 1,000 successful lookups | Homepage only, no JavaScript rendering (see limits) |
The extension sees more than any batch tool on a single site, because it runs JavaScript in your browser and watches inner pages. Batch tools trade that depth for speed: a raw homepage fetch plus DNS takes well under a second per domain, so a list of thousands finishes in minutes.
Do it yourself with free command-line tools
If you are happy in a terminal, ProjectDiscovery's open-source httpx detects technologies with the open Wappalyzer-format fingerprints. Put one domain per line in domains.txt:
httpx -l domains.txt -tech-detect -follow-redirects -json -silent > tech.jsonl
Each line of tech.jsonl is a JSON object with a tech array. Our test on 2026-10-12 (httpx 1.12.0) returned this for wordpress.org:
"tech": ["Google Tag Manager", "Gutenberg", "HSTS", "MySQL", "Nginx", "PHP",
"WordPress Block Editor", "WordPress Site Editor", "WordPress:7.2"]
Without -follow-redirects, sites that redirect (shopify.com answers 301) only show the redirect's technologies. For the email and certificate side, standard tools work one domain at a time:
dig +short MX example.com # email provider
dig +short TXT example.com | grep spf1 # SPF and its include: services
dig +short TXT _dmarc.example.com # DMARC policy: p=none, quarantine or reject
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -issuer -enddate # certificate issuer and expiry
This gets you far for a few hundred domains. What you end up building yourself: merging four tools into one row per domain, following SPF include: chains to count DNS lookups (the limit is 10), grading DMARC and security headers, retrying flaky sites, reading robots.txt and llms.txt, and keeping fingerprints up to date.
Run a bulk lookup without code
- Open Bulk Tech Stack Lookup on Apify and sign in (a free account works).
- Paste your list into Domains or URLs. Domains, full URLs and even email addresses are accepted; only the domain part is used and duplicates are removed.
- Leave the checks on, or switch off the ones you do not need (faster, not cheaper).
- Click Start. About 20 domains are checked in parallel by default.
- Open the Output tab and export CSV or Excel, or pick one of the four views.
The same run as JSON input:
{
"domains": [
"apify.com",
"https://www.shopify.com",
"ops@stripe.com",
"wordpress.org"
],
"maxConcurrency": 20,
"minConfidence": 50
}
One row from a real run on 2026-10-03, shortened:
{
"domain": "wordpress.org",
"status": "ok",
"cms": "WordPress",
"technologyNames": ["WordPress", "WordPress Block Editor", "Gutenberg", "MySQL", "PHP", "Nginx",
"Google Font API", "Google Tag Manager", "HSTS", "Let's Encrypt", "Open Graph", "RSS"],
"emailSecurityGrade": "A",
"securityHeadersGrade": "E",
"tlsDaysUntilExpiry": 79,
"hasLlmsTxt": true,
"dns": {
"mx": ["smtp1-dca.wordpress.org", "smtp2-dca.wordpress.org"],
"spf": {"policy": "fail", "includes": ["helpscoutemail.com"], "dnsLookupCount": 1},
"dmarc": {"policy": "reject", "pct": 100, "reportingVendors": ["dmarcian"]},
"sendingServices": ["Help Scout"]
},
"tls": {"issuer": "Let's Encrypt", "notAfter": "2026-12-22T19:43:57+00:00", "lifetimeDays": 90}
}Worked example: what 56 well-known sites run
We ran a list of 59 inputs (big SaaS, ecommerce, developer and news sites, plus a few Bulgarian sites and deliberately broken entries) on 2026-10-03. 56 domains answered, 1 did not exist and 2 inputs were invalid. Among the 56:
| Question | Answer from the run |
|---|---|
| Email provider | Google Workspace 24, Microsoft 365 3, Proofpoint 2, others or self-hosted the rest |
| DMARC policy | reject 24, quarantine 15, p=none 8, no DMARC record 9 |
| Email security grade | A 22, B 16, C 4, D 6, E 2, F 6 |
| CDN | Cloudflare 17, Amazon CloudFront 6, Netlify 3, Fastly 2, Google Cloud CDN 2, Akamai 1, none detected 25 |
| CMS detected on the homepage | 22 of 56 (WordPress 3; Next.js, Contentful, Astro and Sanity 2 each); 34 custom or not visible without JavaScript |
| Security headers grade | A 12, B 13, C 9, D 7, E 5, F 10 |
| Publishes llms.txt | 17 |
| Blocks all AI training crawlers in robots.txt | 2 |
Two lessons for reading your own results:
- "Expires soon" is a weak signal on its own. Three healthy sites had 20 to 28 days left, on certificates with lifetimes of 90, 199 and 317 days. Lifetimes keep shrinking under CA/Browser Forum rules (200 days maximum since March 2026), and big sites renew automatically, often late. Stronger signals are
tls.valid = falseor a negativetlsDaysUntilExpiry; the one expired certificate in this list was badssl.com's deliberate test certificate. - A blank CMS is not "no CMS". Headless and custom front ends often leave no trace in the raw HTML. Combine
cmswithtechnologyNamesandhostingbefore you segment.
That run used the actor's earlier browser-like User-Agent. Since 2026-10-04 it identifies itself honestly and honours robots.txt, so a few of these sites would now come back as blocked_by_site or disallowed_by_robots_txt (free rows, with DNS, email and TLS data but no tech stack).
Turn the rows into prospect lists
Export the Overview view (flat columns) or the Email & DNS security view to a spreadsheet and filter:
| You sell | Filter |
|---|---|
| Email deliverability or DMARC services | dns.dmarc.policy is none or empty, or dns.spf.exceedsLookupLimit is true |
| Klaviyo-style Shopify apps | technologyNames contains Shopify and not your competitor |
| WordPress care plans or speed work | cms = WordPress and cdn empty |
| Web security audits | securityHeadersGrade is E or F |
| Microsoft 365 migrations or add-ons | emailProvider = Microsoft 365 |
| AI-policy or SEO consulting | blocksAiTraining true, or hasLlmsTxt false |
Schedule the same list weekly and compare runs to catch changes: a new CMS version, a DMARC policy moving to reject, or a certificate that stopped renewing.
What each row contains
| Field | What it holds |
|---|---|
domain, finalUrl, status, error | Input domain, where the homepage ended up, and the outcome |
cms, cdn, hosting, technologyNames | Flat summary columns for spreadsheets |
technologies[] | Each detection with version, confidence, categories, how it was detected and CPE |
emailProvider, dnsProvider, emailSecurityGrade | From MX, NS, SPF, DMARC, MTA-STS and BIMI |
dns | A/AAAA/NS/MX, SPF policy, includes and lookup count, DMARC policy and reporting vendor, CAA, SaaS verification records |
tls | Valid, issuer, validity dates, days until expiry, lifetime, SANs, protocol, key type |
securityHeaders | Score 0 to 100, A to F grade, present and missing headers, HSTS and CSP details, version leaks |
aiCrawlers | Blocked and allowed AI bots, Content-Signal directives, llms.txt and llms-full.txt |
wellKnown | security.txt presence and expiry, ads.txt sellers, sitemaps from robots.txt |
page, http | Title, meta description, language, canonical, Open Graph, JSON-LD types; status, redirects, response time, server |
Honest limits
- Homepage only, no JavaScript. Tools that load after client-side rendering or only on inner pages (a checkout script, a chat widget on /contact) can be missed. Wappalyzer's
jsandxhrrules are skipped for the same reason. - DNS verification is not usage.
detectedBy: ["dns:TXT"]means the company verified the domain with that SaaS (Atlassian, OpenAI, DocuSign…). It does not prove the tool runs on the site. - Bot-protected sites are not bypassed. The actor sends an honest User-Agent, follows robots.txt and uses no proxy. Sites that answer 403, keep answering 429 or serve a challenge page come back as
blocked_by_site, with DNS, email and TLS data but no tech stack. - Fingerprints are community-maintained. Detection uses the open webappanalyzer set (7,000+ technologies, pinned to a version for reproducible results). Rare or brand-new tools may be missing.
- No personal data. It reads headers, HTML, public DNS and certificates. It does not collect names, emails or phone numbers; security.txt is reported as present or absent only.
All input fields
Generated from the actor's live input schema (build 1.0.3).
| Field | Type | Default | What it does |
|---|---|---|---|
Domains or URLs requireddomains | array | Domains, URLs or even email addresses (only the domain part is used). Duplicates are removed. Example: apify.com, https://www.shopify.com, ops@stripe.com. | |
| What to check | |||
Detect technologiesdetectTechnologies | boolean | true | Detect CMS, ecommerce platform, frameworks, analytics, CDN, hosting, marketing tools and 7,000+ other technologies from the homepage, headers, cookies, DNS and certificate. |
DNS & email securitycheckDns | boolean | true | Email provider (MX), DNS provider (NS), sending services from SPF, SPF lookup count, DMARC policy and reporting vendor, MTA-STS, BIMI, CAA and SaaS domain-verification records. |
TLS certificatecheckTls | boolean | true | Certificate issuer, expiry date, days until expiry, validity, hostname match, protocol and key type. |
Security headerscheckSecurityHeaders | boolean | true | Score and grade for HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy and COOP, plus server version leaks. |
AI crawler policy (robots.txt, llms.txt)checkAiPolicy | boolean | true | Which AI crawlers (GPTBot, ClaudeBot, Google-Extended, PerplexityBot, CCBot and more) robots.txt blocks, Content-Signal directives, and whether llms.txt / llms-full.txt exist. |
security.txt, ads.txt, sitemapscheckWellKnown | boolean | true | Presence and expiry of /.well-known/security.txt (contact values are not stored), ads.txt seller counts and ad systems, and sitemap URLs declared in robots.txt. |
| Detection settings | |||
Minimum technology confidenceminConfidence | integer | 50 | Only report technologies detected with at least this confidence (0-100). |
Use the full open fingerprint databaseuseOpenFingerprints | boolean | true | Load the community-maintained enthec/webappanalyzer fingerprints (7,000+ technologies) at the start of the run. If off, or if the download fails, a built-in set of about 60 common technologies is used. |
Fingerprint database versionfingerprintsVersion | string | eea872af449e207e055398f7369d11ee48c8ea03 | Git commit, tag or branch of enthec/webappanalyzer to load. Pinned by default for reproducible results; use "main" for the newest rules. |
| Performance & network | |||
Max concurrencymaxConcurrency | integer | 20 | How many domains are checked in parallel. |
Request timeout (seconds)requestTimeoutSecs | integer | 15 | Timeout for each HTTP request, TLS handshake and DNS lookup. |
Max retriesmaxRetries | integer | 2 | Retries for network errors, HTTP 429 and 5xx responses (with exponential backoff). |
DNS resolversdnsResolvers | array | ["1.1.1.1","8.8.8.8","1.0.0.1","8.8.4.4"] | Public resolvers used for DNS checks. Leave empty to use the system resolver. |
Include raw response headersincludeRawHeaders | boolean | false | Add the homepage's HTTP response headers (without Set-Cookie) to each result. |
Call it from code
Start a run and get the results in one HTTP request with the Apify API (your token is under Console, Settings, API & Integrations):
curl -X POST "https://api.apify.com/v2/acts/adamhaleworks~bulk-tech-stack-lookup/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"domains":["apify.com","wordpress.org"]}'The run's Output tab offers 4 ready-made views; every view exports to CSV, Excel, JSON or XML:
- Overview:
domain,status,finalUrl,title,cms,cdn,hosting,emailProvider,dnsProvider,emailSecurityGrade,securityHeadersGrade,tlsDaysUntilExpiry,blocksAiTraining,hasLlmsTxt,technologyNames,error - Email & DNS security:
domain,emailProvider,dns.sendingServices,emailSecurityGrade,dns.spf.policy,dns.spf.dnsLookupCount,dns.spf.exceedsLookupLimit,dns.dmarc.policy,dns.dmarc.reportingVendors,dns.hasMtaSts,dns.hasBimi,dns.caaIssuers,dns.saasVerifications - TLS & headers:
domain,tls.valid,tls.issuer,tls.notAfter,tls.daysUntilExpiry,tls.lifetimeDays,tls.hostnameMatches,tls.protocol,securityHeaders.score,securityHeaders.grade,securityHeaders.missing,securityHeaders.versionLeaks,wellKnown.securityTxt.found - AI crawler policy:
domain,aiCrawlers.robotsTxtFound,aiCrawlers.blocksAllAiTraining,aiCrawlers.blockedBots,aiCrawlers.namedBots,aiCrawlers.contentSignals,aiCrawlers.llmsTxt.found,aiCrawlers.llmsFullTxt.found
What it costs
Free to run right now. The actor charges no fee of its own today. Apify bills only the compute a run uses against your account's platform credit, and the free Apify plan includes $5 of usage every month. For scale: building all five of our actors and test-running each once on its default input used $0.03 of credit in total (2026-10-12).
Planned: pay-per-event pricing of $0.003 per successful domain lookup ($3 per 1,000) once the account's payout setup is finished. This page and the Apify page will show the change, and Apify notifies existing users before a price change takes effect.
Once pricing is switched on, only rows with status: ok are charged. Dead domains, unreachable sites, blocked or robots.txt-disallowed sites and invalid inputs are written to the dataset for free, so cleaning a lead list costs nothing for the dead entries.
FAQ
Is this a free Wappalyzer alternative?
For bulk lists, yes for now: the actor charges no fee of its own today and the free Apify plan's monthly credit covers small runs. Pay-per-event pricing of $3 per 1,000 successful lookups is planned. It is not affiliated with Wappalyzer or BuiltWith.
Why does it find fewer technologies than the browser extension?
The extension runs JavaScript and sees every page you visit. The actor fetches the raw homepage only, which is what makes thousands of domains per run cheap and fast. It adds DNS, email security, TLS and AI-crawler data that the extension does not show.
Can I paste email addresses instead of domains?
Yes. Only the domain part is used, so a CRM export of contact emails works. Duplicate domains are removed.
Does it work for subdomains?
Yes. shop.example.com is fetched as given, while email and DNS records are read from the registrable domain, example.com.
How do I block it from my own website?
It identifies itself as bulk-tech-stack-lookup in its User-Agent. Add a robots.txt group for that name with Disallow: /, or answer its requests with 403. It records the refusal and fetches nothing else from your site in that run.
Try it on your own data
Bulk tech stack lookup for any list of domains, a Wappalyzer and BuiltWith alternative: CMS, ecommerce platform, frameworks, analytics, CDN and hosting, plus email provider, SPF/DMARC grade, TLS certificate expiry, security headers grade, AI crawler policy and llms.txt. No browser, fast and cheap.
Open Bulk Tech Stack Lookup (Wappalyzer Alternative) Opens the actor's page on apify.com. A free Apify account is needed to run it.