Outrings
Web observability and evidence

How do I find out what a website is built with?

Identifying a site's stack from what it discloses — and understanding why disclosure is itself a finding.

3 min read
Short answer

Response headers, HTML fingerprints, asset paths and cookie names give most of it away. That is convenient for research and inconvenient for the site owner, because the same disclosure tells an attacker which known vulnerabilities to try first.

What sites disclose without meaning to

Response headers

curl -sI https://example.com
  • Server: — the web server and frequently its exact version.
  • X-Powered-By: — the runtime, commonly with a precise version number.
  • X-Generator: — the CMS.
  • X-Drupal-Cache, X-Shopify-Stage, X-Vercel-Id and similar — vendor-specific headers that identify the platform outright.
  • Set-Cookie: names — PHPSESSID, JSESSIONID, laravel_session, _shopify_y. Each is a reliable fingerprint.

HTML and asset paths

  • <meta name="generator"> — often the CMS and its version, stated outright.
  • Directory conventions: /wp-content/, /sites/default/files/, /_next/static/, /_nuxt/. Each maps to one platform.
  • Build artefact naming — hashed bundle filenames differ recognisably between bundlers.
  • Framework attributes left in the markup, such as data-reactroot or Angular's ng- prefixes.

Third-party requests

What a page loads is as identifying as what it says. Analytics, tag managers, chat widgets, payment SDKs, font providers and consent tools each announce themselves by domain.

Why this matters for your own site

Fingerprinting is not merely a curiosity. Version disclosure meaningfully assists an attacker.

  • A version number turns "probe everything" into "look up the known issues for this exact release and try those first".
  • It makes automated mass exploitation cheap — scanning for one header and firing a matching payload requires no skill.
  • It reveals your upgrade cadence. A version eighteen months old signals that patching is not routine.
Removing version headers is not a security control — it is the removal of an unnecessary advantage. It does not protect an unpatched system. Patch first; then stop announcing what you are running.

Reducing your own disclosure

ServerChange
nginxserver_tokens off;
ApacheServerTokens Prod and ServerSignature Off
PHPexpose_php = Off in php.ini
Expressapp.disable('x-powered-by')
AnyRemove the generator meta tag from your templates

Cookie names and asset paths are much harder to disguise and generally not worth the effort — the platform will be identifiable regardless. Version numbers are the part that carries real risk and the part that is easy to remove.

Inference has limits, and should say so

Stack detection is fundamentally heuristic. A header can be spoofed, a CDN can add or strip headers in transit, and a static export leaves few traces of what generated it. Any honest report labels these findings as inferred rather than measured, because a confident claim about someone's infrastructure based on a cookie name deserves the qualification.

What our audit reports about this

Every item below is measured directly, not inferred. Run it against your own site and the result names the exact rule or header responsible.

  • Every disclosing response header, with the value, including Server, X-Powered-By and platform-specific headers.
  • CMS, framework and server identification from headers, markup and asset paths — labelled as inferred rather than measured.
  • A complete inventory of third-party origins the page loads, which is both a fingerprint and a privacy finding.
  • Whether a version number specifically is disclosed, which is the part of fingerprinting that carries real risk.

For agents and scripts, the same measurement is at /api/v1/tech?url=yoursite.com — see the API documentation.

Related questions

Is hiding my stack worth doing?

Hiding version numbers, yes — it is a few lines of configuration and removes a free advantage. Hiding the platform entirely is largely futile and not worth engineering effort, since asset paths and cookie names give it away regardless.

Does removing headers break anything?

No. Server, X-Powered-By and generator tags are informational; nothing depends on them. Removing them is one of the few changes with a real benefit and no functional cost.

Can I trust detection results?

Treat them as strong hints rather than facts. Headers can be spoofed and CDNs rewrite them in transit, which is exactly why these findings are labelled inferred rather than measured.

Why does a CDN change what I see?

Edge servers commonly add their own headers, strip origin ones, and serve cached responses. What you observe is what the edge sends — which is the truth for visitors, even when it differs from your origin configuration.

Read next

All 100 guides · How every check works · API for agents