Where the fingerprint comes from
Every HTTP response starts with a status line and a block of headers, and two of them routinely leak the software stack. Server names the web server, often with a version and, in distribution packages, the OS in parentheses: Apache/2.4.52 (Ubuntu). X-Powered-By names the application layer, typically something like PHP/8.1.2-1ubuntu2.14 or ASP.NET. The checker requests the page once, follows up to five redirects, and reads the headers of the final response.
The inference rules are deliberately narrow. Microsoft-IIS/10.0 maps to Windows Server 2016, 2019 or 2022 because that IIS build only ships with those releases, and older IIS versions map to their matching Windows Server generation. Distribution tokens such as Ubuntu, Debian, CentOS, Red Hat, Fedora, Amazon Linux, Alpine, FreeBSD and OpenBSD are matched in the Server banner first and in the PHP build string second. A bare Apache, nginx, OpenResty, LiteSpeed or Caddy banner only earns a low-confidence Linux / Unix guess, and an X-AspNet-Version header counts as medium evidence for Windows.
Reading the tiles and the evidence table
The operating system tile shows the inferred OS and a confidence of high, medium or low. When nothing can be inferred it reads Not revealed. The web server tile shows the Server header with any parenthetical removed, or Hidden when the header is absent. Language / framework is filled from X-Powered-By when it names PHP (with version), ASP.NET, Express or Next.js. CDN / proxy names the edge network, or None detected.
Below the tiles, the evidence table has one row per header that contributed: the header name, its raw value and a one-line reading of what it implies. A Server row can carry the note that it identifies the software but not the OS. That is the honest result for a banner like nginx/1.24.0. When no identifying headers came back at all, the table is replaced by a single line saying so.
The Technologies detected list is broader than the OS question. It picks up hosting platforms from their request-ID headers (Vercel, Netlify, Fly.io, Render, Heroku, AWS, Azure), site builders such as Shopify, Wix and Squarespace, managed WordPress hosts, and frameworks seen in the markup: wp-content paths for WordPress, _next/static for Next.js, and the first word of a meta generator tag.
Why the answer is often that it cannot tell
Most production sites sit behind a CDN or a reverse proxy, and the headers you receive belong to that layer, not to the origin. A Cloudflare-fronted site returns Server: cloudflare and a cf-ray ID whatever is running behind it. The checker reports the CDN and leaves the OS blank rather than guessing, and the note under the tiles explains which proxy got in the way.
Hardening removes the rest. Apache's ServerTokens Prod reduces the banner to Apache, nginx's server_tokens off drops the version, PHP's expose_php = Off removes X-Powered-By, and IIS can strip its Server header through request filtering or an outbound rewrite rule. A site that has done all of this returns Hidden and Not revealed.
The check is also a single request to one URL. Different paths can be served by different backends (a static front page from a CDN, an API from an origin), so a result for the home page does not describe every service under the domain. If you need the hosting provider rather than the OS, Website Hosting Checker works from the IP's ownership records instead of headers.
What to do with the result
For your own site, treat any high-confidence row as a to-do item. A banner that exposes Apache 2.4.52 on Ubuntu tells an attacker which CVE list to read. Stripping it costs nothing and changes nothing about how the site behaves. Re-run the checker after the change and confirm the evidence table has gone quiet.
For someone else's site, use the result as a starting assumption. A low-confidence Linux guess is only that, and a CDN result says nothing about the origin. Pair it with Port Scanner to see which services actually answer, or DNS Lookup to find where the name resolves.
- Set ServerTokens Prod and ServerSignature Off in Apache's main configuration.
- Set server_tokens off in the nginx http block. Removing the header entirely needs an extra module or a proxy in front.
- Set expose_php = Off in php.ini to drop X-Powered-By.
- On IIS 10, enable removeServerHeader under request filtering, or add an outbound rewrite rule.