Server Signature Test: Check Server and X-Powered-By Version Leaks
Check whether your HTTP responses disclose server or framework versions, understand what the headers do and don’t prove, and reduce unnecessary detail.

Direct answer: send an HTTP request to a site you own or are authorized to assess, then inspect the response headers for Server, X-Powered-By, and related version markers. A value such as Server: nginx/1.0.14 or X-Powered-By: PHP/5.4.16 reveals a possible technology or version clue. It does not prove that the identified software is vulnerable, and a missing or generic header does not prove that the stack cannot be fingerprinted.
This guide shows runnable checks with cURL, Python, and Node.js; explains how to check redirects, paths, and error responses; and outlines ways to reduce disclosure without treating header cleanup as a substitute for patching. The same request-and-inspect workflow can be used before and after configuration changes.
1. What Server and X-Powered-By disclose
The Server response header describes software associated with the origin server that handled a request. X-Powered-By can identify technologies or frameworks used by the web server. Depending on the stack, related headers may expose a product, framework, or version.
These headers matter because version details can help someone investigate version-specific weaknesses or decide what to examine next. A banner is a lead for inventory and patch review, not evidence that a host is exploitable. Headers can also be removed, changed, generated by an intermediary, or inaccurate. OWASP notes that other fingerprinting clues may remain even when these headers are absent. See the [OWASP HTTP Security Response Headers Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html) and [OWASP Web Security Testing Guide: Fingerprint Web Server](https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/01-Information_Gathering/030-Fingerprint_Web_Server).
2. How do I check my Server header?
For a quick first look, make a HEAD request and print the response headers. Use a hostname and paths you are authorized to test. Some sites handle HEAD differently from GET, so if the response is empty or unusual, repeat the inspection with a GET request.
cURL: quick header check
curl -sS -I https://example.com/
Look for lines beginning with Server:, X-Powered-By:, or other implementation markers. The -I option asks for headers using HEAD. To inspect a GET response while discarding its body, use:
curl -sS -D - -o /dev/null https://example.com/
To include redirect responses and the final destination in the trace, add -L:
curl -sS -I -L https://example.com/
With redirects, review each response in the output. A redirect can be served by a different layer or host from the final page. If you need to see where the request ended, include -w '\nFinal URL: %{url_effective}\nStatus: %{http_code}\n' at the end of the cURL command.
Python: inspect a GET response
Install the commonly used requests package if needed with python -m pip install requests. Save this as check_headers.py, replace the URL, then run python check_headers.py.
import requests
url = "https://example.com/"
response = requests.get(url, timeout=20, allow_redirects=True)
print("Final URL:", response.url)
print("Status:", response.status_code)
for name, value in response.headers.items():
print(f"{name}: {value}")
for name in ("server", "x-powered-by"):
print(f"{name}: {response.headers.get(name, '(absent)')}")
Python Requests follows redirects by default; the explicit setting makes the behavior clear. response.headers represents the final response. To examine every hop, inspect response.history too:
for hop in response.history:
print("Redirect:", hop.status_code, hop.url)
print("Headers:", dict(hop.headers))
Node.js: inspect a GET response
In a current Node.js runtime with built-in fetch, save this as check-headers.mjs and run node check-headers.mjs. The code follows redirects and prints the final response headers.
const response = await fetch('https://example.com/', {
method: 'GET',
redirect: 'follow',
signal: AbortSignal.timeout(20000),
});
console.log('Final URL:', response.url);
console.log('Status:', response.status);
for (const [name, value] of response.headers) {
console.log(`${name}: ${value}`);
}
console.log('Server:', response.headers.get('server') ?? '(absent)');
console.log('X-Powered-By:', response.headers.get('x-powered-by') ?? '(absent)');
Fetch follows redirects by default; setting redirect documents the intended behavior. Browser JavaScript has cross-origin restrictions on which response headers it can read. Run this check from Node.js or another server-side environment when you need the raw public response.
3. Check more than the homepage
A single request is a useful starting point, not a complete audit. Header behavior may differ by route, status code, cache state, redirect, application server, reverse proxy, CDN, or WAF. Check a representative set of public responses, including:

- The homepage and important application routes.
- Redirects, including HTTP-to-HTTPS and canonical-host redirects.
- Not-found and other error responses that you can safely request.
- Static assets and API endpoints where relevant.
- Responses served through each public hostname or edge configuration.
Record the URL, status, redirect chain, and response headers. Compare the public result with the configuration at the application and edge layers. If the origin is behind a proxy, the public-facing response is what an outside observer receives; an origin-only check cannot establish what the proxy exposes.
Do not limit the review to the two headers in the title. Depending on the stack, look for X-AspNet-Version, X-AspNetMvc-Version, X-Php-Version, X-Generator, X-Powered-CMS, and headers that identify proxies or hosting components. Some Content-Type and WWW-Authenticate values can also provide implementation clues. OWASP’s [Secure Headers Project best practices](https://owasp.org/www-project-secure-headers/#best-practices) discusses examples of headers that can reveal technical environment details.
Headers are only one source of fingerprints. Cookies, HTML, URL paths, file extensions, error messages, and response behavior can offer other clues. Do not infer a precise software stack from header order alone; that method is inconclusive. OWASP describes fingerprinting as matching markers from known locations, and recommends considering multiple markers.
4. Does X-Powered-By reveal my framework version?
It may. If the value explicitly includes a framework and version, it discloses that string to anyone who can read the response. But the header may be absent, generic, stale, or added by an intermediary, so it is not a definitive inventory of the live application. Likewise, removing it does not make the framework impossible to identify by other means.
Use a revealed version as a prompt to confirm the actual deployed software and review its patch status using your authoritative inventory and deployment records. Do not assume the version is accurate, and do not conclude that a vulnerability exists based on a banner alone.
5. How do I hide my server version from HTTP headers?
OWASP recommends removing X-Powered-By and removing the Server header or replacing it with a non-informative value. Apply the change at the layer that emits the header: application/framework, web server, reverse proxy, CDN, or WAF. A downstream layer may re-add a header that an upstream layer removed, so verify the externally visible response after each change.

- Identify the emitter. Compare responses from the public endpoint and, where your operational access allows, the origin or internal service. Check the relevant server and framework configuration.
- Remove framework markers. Turn off version headers in the framework or application configuration where supported. For example, OWASP documents
<httpRuntime enableVersionHeader="false" />under<system.web>forX-AspNet-Version, andMvcHandler.DisableMvcResponseHeader = true;inGlobal.asaxforX-AspNetMvc-Version. Confirm applicability against the documentation for the framework version you actually run. - Filter at the edge if appropriate. A reverse proxy or WAF may be able to remove or normalize headers consistently across responses. Check whether the application or upstream layer adds them again, and whether error responses follow the same rules.
- Decide between removal and generic replacement. OWASP permits removing
Serveror using a non-informative value such asServer: webserver. A generic replacement reduces detail, but it remains a header and should be assessed against your operational needs. - Recheck public responses. Repeat the checks for several paths, redirects, and statuses. Verify that changes apply where expected and that no related version headers remain.
- Patch the software. Keep the web server, framework, and dependencies current. Header minimization is defense in depth; it does not fix vulnerable software.
Configuration syntax varies by product and version. Consult current official documentation for your server, framework, proxy, CDN, or WAF rather than copying a directive intended for a different product. In particular, an example about adding a security header with an always option is not universal syntax for removing Server.
6. Manual inspection or automated scanning?
| Approach | Useful for | What to check |
|---|---|---|
| Manual requests with cURL or code | Fast checks of known URLs and repeatable verification after a change. | Record raw headers, status, redirects, and the exact paths checked. |
| Browser network inspector | Seeing the response associated with a normal browser visit. | Inspect the relevant document and redirect requests; browser access to headers in page scripts differs from developer tools. |
| Header or site scanner | Repeating checks across a larger set of pages. | Confirm whether it checks only the homepage or crawls more routes, and retain raw results for review. |
OWASP lists resources such as Mozilla Observatory and SmartScanner and notes that some online checks focus on the homepage, while whole-site scanning can cover more pages. A scanner’s summary is not a substitute for reviewing the raw responses and scope. Use automated checks on systems you are authorized to assess.
7. Troubleshooting common results
| Symptom | Likely cause | What to do |
|---|---|---|
No Server or X-Powered-By appears |
The header is omitted, filtered, or the request reached a layer that does not emit it. | Check all response headers, another route and status, and other fingerprint clues. Absence is not proof of anonymity. |
| HEAD has different headers or returns an error | The server, application, or intermediary handles HEAD differently from GET. | Repeat with GET and discard the body, for example curl -sS -D - -o /dev/null URL. |
| The final response is clean, but a redirect exposes a version | A redirecting host or edge layer emits a different response. | Inspect each redirect hop and configure the layer that produced the disclosure. |
| The header remains after changing application configuration | A proxy, CDN, web server, or another application component may add it later. | Compare the response at each layer you control and filter at the layer that emits it; then retest the public endpoint. |
| The header is gone on success but present on errors | Error responses may be generated by a different component or use separate configuration. | Check representative error statuses and align their edge and server handling. |
| The reported product or version conflicts with deployment records | The value may be stale, generic, rewritten, or generated by an intermediary. | Treat it as a clue, confirm the active software from trusted inventory, and review the full request path. |
| A scanner reports a finding after the change | It may have checked a different route, cached response, redirect, or related marker. | Inspect the exact URL and raw response it reports; check cache behavior and all related headers. |
| A browser script cannot read a response header | Cross-origin browser rules restrict script access to some headers. | Use browser developer tools or make the check from a server-side tool such as cURL, Python, or Node.js. |
8. Performance, reliability, and cost
A handful of direct HTTP requests is inexpensive in time and resource use, but it only covers the URLs you request. A crawler or scanner can improve coverage and repeatability while generating more requests and requiring scope control. Set reasonable timeouts, avoid aggressive concurrency against production systems, and use a documented URL list so results can be compared between runs.
For reliable comparisons, keep the method, URL, redirect behavior, and timing conditions consistent. Record timestamps and status codes, and note whether a cache or CDN may have served the response. If a request fails, that says nothing by itself about header exposure; resolve DNS, TLS, access, or timeout issues before interpreting the result. No single scan proves that every path and response is clean.
There is no need to pay for a one-off check that can be made with standard HTTP clients. A scanning service may be useful when it provides the breadth and repeatability your review needs; evaluate its route coverage, raw evidence, and operational fit rather than treating a score as proof. The cost of remediation should be weighed against the actual configuration and maintenance work, while patching remains essential regardless of whether a banner is visible.
9. Or skip the browser setup
If your workflow also needs a clean screenshot of the page being reviewed, ScreenshotNeo is a website screenshot API and MCP server. The header checks above inspect HTTP responses; a screenshot is a separate view of rendered page content, not a replacement for reading response headers.
One GET request returns an image or PDF. This cURL example saves a WebP screenshot; see the ScreenshotNeo API documentation for the API options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and whether the request was billed. Its MCP server lets Claude, Cursor, and other MCP clients use take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Every feature is on every plan.
Sign up for 1,000 free screenshots a month, with no card.
10. FAQ
Is a Server header a security vulnerability?
Not by itself. It can disclose useful software information, so reduce unnecessary detail and use it as an inventory and patch-review clue.
Does removing these headers prevent fingerprinting?
No. Other headers, cookies, HTML, paths, extensions, errors, and response behavior can still identify technologies.
Should I remove Server or replace it?
OWASP recommends removal or a non-informative value. Choose the approach supported by your stack, then verify it across public responses.
What should I fix first if a version is exposed?
Confirm the deployed version using trusted records, check whether it is current and patched, and remove unnecessary disclosure at the layer that emits it.


