If you sell a Shopify app, every store not running Shopify is a wasted call. If you sell a WordPress security plugin, you want the sites on WordPress, ideally on an old version. If you are watching a competitor, the day their marketing site swaps one analytics tool for another, or moves from a hosted CMS to a framework, tells you something about what they are building next.
All of those start from the same question: given a URL, what is it built with? That question has a fairly reliable answer for most public sites, and a surprisingly unreliable one for some. This lesson is about getting the answer and knowing which kind you got.
How detection actually works
A detector does not log into anything or ask the site. It fetches the page like a browser would and matches what comes back against a database of fingerprints. A WordPress site loads scripts from /wp-content/ and /wp-includes/. A Shopify store sets recognisable cookies and loads assets from Shopify's CDN. A site behind Cloudflare returns a server: cloudflare header. Google Tag Manager leaves a specific script snippet in the HTML. Each fingerprint is a pattern on one part of the response.
Website Tech Stack Detector (techstackdetector) does exactly this and tells you which parts matched. It is a GET with a url parameter, and at 30 credits it is one of the more expensive calls in this course, which shapes how you use it.
curl "https://api.apiverve.com/v1/techstackdetector?url=https%3A%2F%2Fwordpress.org" \
-H "x-api-key: YOUR_API_KEY"Look at detectedBy on each technology, and at MySQL, which is implied: true with an empty detectedBy.
When we ran this against wordpress.org it returned 13 technologies. A few of them show the full range of evidence you will see:
| Technology | Categories | confidence | implied | detectedBy |
|---|---|---|---|---|
| WordPress | CMS, Blogs | 100 | false | html, scriptSrc, headers, meta, dom |
| Nginx | Web servers, Reverse proxies | 100 | false | headers |
| PHP | Programming languages | 100 | false | scripts |
| Google Tag Manager | Tag managers | 100 | false | html |
| MySQL | Databases | 100 | true | (empty) |
The detectedBy list is the evidence, and it is the most underused field in the response. WordPress matched on five independent signals; it would take a deliberate effort to fake that. Nginx matched on one response header. MySQL matched on nothing at all: it is implied, because WordPress requires a MySQL-compatible database. Nobody saw MySQL. The fingerprint database knows that where there is WordPress there is a MySQL or MariaDB server somewhere, and it reports that inference.
Now run it against a site with almost nothing to fingerprint:
curl "https://api.apiverve.com/v1/techstackdetector?url=https%3A%2F%2Fexample.com" \
-H "x-api-key: YOUR_API_KEY"Three results: Cloudflare, Cloudflare DNS and HTTP/3. No CMS, no framework.
example.com returns three technologies: Cloudflare (detected from headers and dns), Cloudflare DNS (from dns) and HTTP/3. That is not a failure. It is a static page behind a CDN, and the honest answer is that the CDN is all a visitor can see.
Reading confidence, implied and version
Three fields decide how much weight a detection deserves.
confidence runs from 0 to 100. Some fingerprints are definitive (a header that only one product sets); others are suggestive (a CSS class name that one framework popularised and others copied). A fingerprint that matches weakly produces a lower number. For anything that triggers an action, like adding a lead to a campaign, set a threshold and stick to it. Starting at 75 and tuning from your own false positives is reasonable.
implied means "inferred, not observed". Inferences are usually right, but they are a different kind of claim. If your sales copy says "we noticed you run MySQL", and the inference came from WordPress on a host that runs MariaDB, the prospect knows you guessed. Filter out implied technologies whenever the result will be quoted back to a human.
version is a premium field, and even on plans that include it, it is often null. In the run above, WordPress came back with a version and the block editor did not. A version only appears when the page reveals it, and well-run sites hide them on purpose. Never build a segment like "sites on an outdated version" and treat the absence of a version as "unknown, include anyway": you would be emailing every security-conscious site you found. A cpe identifier (also premium) is there for matching against vulnerability databases when a version is known.
A detection comes back with `confidence: 100`, `implied: true` and an empty `detectedBy`. What does that tell you?
Answer the check above to continue.
Competitive analysis: track changes, not snapshots
A single detection of a competitor is trivia. A series of them is a signal. Store the set of slug values per run and diff consecutive runs; that is all the logic you need.
// Node 18+, ES module
const KEY = process.env.APIVERVE_API_KEY;
export async function stackSlugs(url) {
const qs = new URLSearchParams({ url });
const res = await fetch(`https://api.apiverve.com/v1/techstackdetector?${qs}`, {
headers: { 'x-api-key': KEY },
signal: AbortSignal.timeout(45000),
});
const body = await res.json();
if (body.status !== 'ok') throw new Error(body.error);
return new Set(
body.data.technologies.filter((t) => !t.implied && t.confidence >= 75).map((t) => t.slug)
);
}
export function diff(previous, current) {
return {
added: [...current].filter((s) => !previous.has(s)),
removed: [...previous].filter((s) => !current.has(s)),
};
}Run it weekly per competitor, persist the slug set, and alert on any non-empty diff. A new payment provider, a switched analytics tool or a migration to a new frontend framework appears as a two-line change. Be sceptical of single-run flickers: a technology loaded by a tag manager can appear and disappear depending on what a visitor was served, so require a change to persist across two runs before you announce it to anyone.
Use it responsibly
Everything a detector reports is public: it is what any browser receives. That makes it fair to use for research. It does not make it fair to use carelessly. Keep a few lines in mind:
- Do not present inferences as facts to the prospect. "Looks like you run Shopify" with evidence is fine; claims about versions or vulnerabilities in a cold email read as a threat.
- Respect the sites you look at. Weekly checks of a few competitors are research. Daily runs across thousands of domains you have no relationship with is crawling, and needs the same restraint as any crawler.
- Remember what the data is not. It describes a website, not a company. A company's marketing site might be run by an agency on a stack the company itself never touches.
The next lesson moves from the page to the domain itself: who registered it, when, where its DNS points and whether its certificate is healthy. Continue with domain intelligence.