Tech Stack Enrichment - Website Technology Scanner, DNS + HTML
Pricing
$3.00 / 1,000 website scanneds
Tech Stack Enrichment - Website Technology Scanner, DNS + HTML
293 technology detections on 10 sites against 69 from a rival Actor, ahead on all 10. Bulk tech stack lookup from the page and DNS: 428 technologies in 46 categories with confidence and evidence. Technographic data, Wappalyzer alternative, no API key. Detects frameworks and hosting.
Pricing
$3.00 / 1,000 website scanneds
Rating
0.0
(0)
Developer
Snow Leo Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
17 hours ago
Last modified
Categories
Share
Tech Stack Detector: Wappalyzer & BuiltWith Alternative
Point this Actor at a website and it tells you what the site is built on and what the company runs behind it. No API key, no browser, no proxy. A bare domain is enough.
Most technology detectors read the page and stop there. This one reads the page and the DNS layer, and the DNS layer is where the tools a company actually pays for leave their traces: the mail host, the single sign-on provider, the e-signature service, the DMARC monitor, the design and project tools that each needed a domain-verification record to be switched on. None of that ever appears in HTML.
How much difference the second layer makes
Ten well-known sites, scanned by this Actor and by the strongest Actor in this
niche on the same day. The rival run is
nexgendata/wappalyzer-replacement, run id fUuGC6bZibqELAwaX, 12 September
2026; its output is kept in tools/rival_run.json so the comparison can be
repeated without paying for the run again. Our side is reproduced by
python3 tools/measure.py.
| Site | This Actor | of that, from DNS | Rival |
|---|---|---|---|
| stripe.com | 34 | 25 | 11 |
| shopify.com | 38 | 28 | 3 |
| vuejs.org | 11 | 3 | 3 |
| www.nytimes.com | 39 | 30 | 18 |
| wordpress.org | 14 | 4 | 2 |
| www.hubspot.com | 41 | 32 | 4 |
| basecamp.com | 20 | 14 | 6 |
| www.zendesk.com | 40 | 28 | 3 |
| gitlab.com | 38 | 26 | 15 |
| news.ycombinator.com | 18 | 13 | 4 |
| total | 293 | 203 | 69 |
293 detections against 69 — ahead on all 10 sites, behind on 0 of them. On nytimes.com specifically: 39 against 18, and among the extra ones are Notion, DocuSign, Dropbox, Zoom, Miro, Atlassian, Jamf, Segment, Wiz, OneTrust and Klaviyo. A page-only scanner cannot see a single one of them, because the New York Times does not advertise its internal tooling in its homepage markup.
What it looks at
Six layers, each with its own confidence, and every detection carries the exact evidence it came from so you can check it by hand:
- Response headers (confidence 100) —
server,x-powered-by,x-shopify-stage,cf-ray,x-vercel-idand the rest. - DNS records (confidence 100) — MX, NS, SPF includes, TXT domain-verification tokens, CAA and DMARC, read over DNS-over-HTTPS from Google with Cloudflare as the fallback resolver.
- Cookies (95) — every
Set-Cookieline, not just the last one._shopify_y,wordpress_,__cf_bm,laravel_session. - The meta generator tag (95) — usually the only place a CMS states its version honestly.
- The TLS certificate (95) — one extra handshake names the certificate authority, the protocol version and the expiry date.
- Script and stylesheet URLs (90) and the page body (85).
- Implication (60) — WooCommerce means WordPress means PHP. Labelled as implied, never mixed in with direct evidence.
The tables hold 428 distinct technologies across 46 categories: 248 page-level fingerprints and 207 DNS-level vendors, with 27 names that both layers can find.
Monitor mode: pay for changes, not for the same answer
Switch on Monitor mode and the Actor remembers every domain between runs in
a named key-value store. On the next run a site only produces a row if its
technology set is new or has changed, and the row then carries
technologies_added and technologies_removed — the actual names, not just a
flag.
That turns a list of domains into a watchlist: a competitor migrating from Magento to Shopify, a prospect installing Intercom, a client moving mail from Google Workspace to Microsoft 365. Put it on a schedule and a quiet week costs you nothing in rows.
If nothing changed, the run finishes successfully with an empty dataset and
says so in words — empty_reason: nothing-changed — rather than leaving you to
guess.
An empty result always has a name
A green run that delivers nothing is the worst thing an Actor can do to you, so this one never does it silently. Every empty outcome has its own named reason in the REPORT record and a matching warning in the log. There are 12 of them:
no-urls-given, input-dataset-unreadable, all-urls-invalid, dns-technology-filter-without-dns-layer,
require-contradicts-exclude, min-confidence-above-maximum,
category-filter-matches-nothing, charge-limit-reached, filtered-out,
nothing-changed, nothing-detected, all-sites-unreachable.
The first 8 of them are decided from your input before a single request is sent. If you ask to keep only sites using Google Workspace and switch the DNS layer off, that is a guaranteed zero — Google Workspace is only ever visible in DNS — and you are told immediately instead of after a thousand pages have been downloaded on your budget.
Input
Everything is optional except the list of websites, and the list itself is accepted in whatever shape you already have it.
- Websites — bare domains (
stripe.com), full URLs,{"url": ...}objects, or one long comma/newline separated string. An email address is reduced to its domain. The same list is read from any ofurls,startUrls,domains,websites,targetUrls,url,domainandwebsite, so output from another Actor can be pasted in without renaming a column. - Input dataset ID and Website field name — take the list straight out of another Actor's dataset instead of typing it.
- Detect DNS-layer technologies — on by default. This is the layer that makes the difference above.
- Read the TLS certificate — on by default.
- Probe known DKIM selectors — off by default. Asks for 16 well-known selectors to prove which mail sender actually signs the domain's email; on a list of a thousand domains that is sixteen thousand extra lookups, which is why it is off unless you want it.
- Only these categories — keep only CMS, or Ecommerce, or Payment Processors, and so on. A category name that does not exist is reported back with the list of the ones that do, instead of quietly emptying your run.
- Only sites using / Exclude sites using — filter the site list itself.
Matching is by substring, so
shopifyalso keeps Shopify Plus and Shopify Hydrogen. This is the lead-generation mode: feed in ten thousand domains, get back the ones on WooCommerce. - Minimum confidence — 90 keeps only hard evidence and drops everything inferred from the page body.
- Monitor mode: only report changes and also emit unchanged sites.
- Include confidence / versions / evidence / security headers / all response headers — each can be switched off.
- Compact output — for AI agents and for anything that pays per token. Measured on one nytimes.com row: 11 120 bytes full, 1 910 bytes compact.
- Drop empty fields — for loading straight into a database.
- Parallel sites, HTTP timeout, Maximum rows.
Output
One row per website. The full row carries the url, the final url after
redirects, the domain, the HTTP status, the response time, the scan
timestamp (checked_at), the page title,
description and language, the meta generator, the server header, the security
headers, the TLS issuer and expiry, the full DNS picture (mx, ns, spf,
dmarc, caa, the TXT record count and the zone that was actually queried),
and then the technologies themselves:
technologies— a list of.{name, category, layer, version, confidence, evidence}tech_names,tech_count— the flat list and its size.categories,category_list— grouped by category.page_tech_countanddns_tech_count— how many came from each side, so you can see at a glance where the answer came from.- In monitor mode:
change_type(NEW / UPDATED / UNCHANGED),technologies_added,technologies_removed.
The last record of every run is a REPORT: how many sites were requested, scanned, answered and unreachable, how many DNS lookups were made, how many detections came from each layer, what each filter dropped, which input values were not addresses and why, and per-host failures.
Where a site answers nothing
A site behind a challenge page still tells you something. A 403 from Cloudflare
arrives with the same server, cf-ray and __cf_bm cookie as a successful
response, so the row still names the protection in front of the site, and the
DNS layer answers regardless of whether the site is up at all. A domain that is
simply dead — no HTTP answer and no DNS records — produces no row at all
and is counted as blank_rows in the REPORT, because a row that says nothing
is a row you would have been charged for.
Honest limitations
Things the strongest rival in this niche, or the commercial services this Actor is an alternative to, do that this one does not:
- Database size. Wappalyzer's own catalogue and the Actors that embed it claim 7 000+ technologies. This Actor knows 428. The 428 are the ones that appear on real commercial sites, and on the ten-site comparison above the bigger catalogue still lost 69 to 293 — but if you need the long tail of obscure libraries, that is a real difference.
- No JavaScript execution. The page is read as the server sends it. A technology that is only loaded by a later client-side script, and leaves no trace in the initial HTML, headers or cookies, will be missed. This is the price of running without a browser, and it is also why a scan costs a fraction of a browser-based one.
- No historical data. BuiltWith sells the history of a site's stack over years. This Actor tells you what is true now; monitor mode builds the history from the day you start watching, not before.
- No traffic, spend or company-size estimates. Technologies only.
- Public suffix handling is an approximation. The zone queried in DNS is
derived from the hostname with a practical rule (two labels, three for known
compound endings such as
co.ukandcom.au) rather than the full public suffix list. On an unusual suffix the DNS layer stays silent rather than reporting something wrong; the zone that was queried is in every row underdns.zone, so you can see what happened. - DKIM proof is opt-in, not exhaustive. 16 well-known selectors are probed when you ask for it. A vendor using a private selector name is not found this way.
FAQ
Do I need an API key or a proxy? No. Standard library HTTP and DNS-over-HTTPS only. That is also why the run cost is low.
What do I put in the input — URLs or domains?
Either. stripe.com, https://stripe.com/pricing, {"url": "stripe.com"} and
sales@stripe.com all resolve to the same scan.
Can it take its list from another Actor? Yes — put that Actor's dataset id into Input dataset ID and name the field holding the address. A missing or unreadable dataset does not kill the run; it is reported and any websites you typed by hand are still scanned.
How do I find every site on my list that uses WooCommerce?
Put woocommerce into Only sites using. Only matching sites produce rows,
and the REPORT tells you how many were dropped by that filter.
Why does a row have technologies I cannot find in the page source?
Because they came from DNS. Look at the layer field of each detection —
dns means the evidence is an MX, NS, SPF, TXT, CAA or DMARC record, and the
evidence field shows the record itself.
Does the DNS layer work for a subdomain?
The DNS layer queries the registered domain, not the hostname you typed:
records live on example.com, not on www.example.com. Measured:
www.nytimes.com has zero TXT records, nytimes.com has 45. The zone actually
queried is in dns.zone.
Why is a technology listed with confidence 60? It was implied by another one rather than found directly — WooCommerce implies WordPress implies PHP. Set Minimum confidence to 90 to drop everything inferred.
Why is version null so often?
Because most technologies never state a version anywhere a scanner can read. A
version is filled in only when the header, script URL or generator tag really
contains one. An invented version is worse than no version.
Can it tell me when a site's stack changes? That is monitor mode. Turn on Monitor mode: only report changes, put the Actor on a schedule, and you get a row only when something actually moved, with the added and removed names spelled out.
Why did my run return nothing?
Look at empty_reason in the REPORT record — there are eleven named reasons
and each one comes with a sentence in the log explaining exactly what to
change.
How fast is it? 8 sites are scanned in parallel by default (the timeout per request is 20 seconds), each host rate-limited on its own. A scan is one page fetch, one TLS handshake and five DNS queries per site.
Is scraping this legal? Everything read here is what any browser and any DNS resolver receive when they ask for a public website: the page a server sends to anyone, its response headers, and the public DNS records of the domain. No login, no paywall, no personal data.