Technology Fingerprinting: How a Website's Stack Gives Itself Away
A technology fingerprint is a recognizable trace a technology leaves in a web page: a script URL, a meta tag, a cookie name, a JavaScript global, a DOM structure or an HTTP header. These traces identify it without asking any server.
Why it matters
Every framework, CMS, analytics tool and library leaves traces in a page. React writes __NEXT_DATA__ to the window. WordPress stamps <meta name="generator" content="WordPress ...">. Shopify sets _shopify_s as a session cookie. These traces are fingerprints, and they're public.
Most stack detectors crawl your page, send what they saw upstream to a server, and return a report. That means the URL you asked about and everything in the page travels over the network. Scalpel Stack does the matching locally instead, right in your browser tab, so the page never leaves your machine. Understanding how fingerprints work explains both how detection catches things and why it sometimes misses them.
How it works
A fingerprint is a pattern: a list of strings, regular expressions, or CSS selectors that uniquely identify a technology. When you scan a page, Scalpel Stack extracts six types of traces from the page:
Script URLs are the src attributes of <script> tags. A library often announces itself in the path: /cdn/jquery-3.6.0.min.js, cdn.shopify.com/s/..., https://cdn.jsdelivr.net/....
Meta tags are the <meta> elements in the head. WordPress writes <meta name="generator" content="WordPress 6.4.2">. Some platforms write similar hints.
Cookies are the names already set by the page. PHPSESSID is PHP's default session cookie. wordpress_logged_in_* belongs to WordPress. _shopify_s is Shopify. The names themselves are the signal.
JavaScript globals are variables the page's own scripts write to the window object: window.jQuery, window.__NEXT_DATA__, window.Shopify. The extension probes a fixed list of paths and returns what's defined.
HTML patterns match against the page's DOM: comments like <!-- Powered by Yoast SEO -->, class names like wp-block-*, data attributes like data-react-*. It's the catch-all for traces that are not a header, script, cookie, meta tag or global.
HTTP response headers like Server, X-Powered-By, and Via reveal the software behind the site. These require a second fetch of the page's own URL, which the extension only does on your click.
Each vector has different reliability and different privacy properties. A script URL is fast and requires no extra request. A header is authoritative but needs an explicit fetch. A meta tag is easy to spoof. A JavaScript global runs only on sites that load their own scripts, not on fully static pages served by a CDN.
What does not matter
A fingerprint is inference, not omniscience. Just because you don't see a fingerprint doesn't mean the technology isn't there. A minified script bundle might strip version strings. A site behind a CDN might obscure the origin server in headers. A security-conscious site removes the <meta name="generator"> tag. That's why detections show a confidence score, not a boolean. You're weighing the evidence, not proving a fact.
Also, a matched fingerprint doesn't prove a business relationship. If detection finds jQuery on a page, it means jQuery is running. It doesn't mean jQuery was chosen, deployed, or maintained by the site's owner; it might be bundled in a third-party embed or a plugin you didn't know about.
Code example
Here's what a single page's fingerprints look like when Scalpel Stack reads them:
{
"technology": "WordPress",
"fingerprints": [
{
"vector": "meta",
"key": "generator",
"pattern": "WordPress",
"matchedText": "WordPress 6.4.2",
"version": "6.4.2"
},
{
"vector": "scriptSrc",
"key": "script",
"pattern": "/wp-includes/",
"matchedText": "https://example.com/wp-includes/js/utils.js"
},
{
"vector": "cookies",
"key": "wordpress_logged_in_*",
"pattern": "wordpress_logged_in",
"matchedText": "wordpress_logged_in_a1b2c3d4"
}
]
}
Each entry is a vector (the channel the detection came from), a key (what was looked for), the pattern that matched, the actual text from the page, and any extracted version. When you expand a detection in Scalpel Stack, you see each of these lines.
How Scalpel shows it
Open the Scalpel Stack popup on any page and every row is a fingerprint match. The tech name, count, and badge tell you what matched. Expand a row and you see the evidence list, one line per fingerprint: the vector badge, the key, the pattern, and the matched text from the page. That matched text is rendered as plain text, never as HTML, so hostile page content can't execute.
The page's fingerprint database (the set of patterns Scalpel Stack matches against) is open source and bundled inside the extension. You can inspect the rules, audit them, and they don't change between versions without your knowing it. The whole extension is GPL-3.0, which means the fingerprint data is auditable and the whole tool stays open.