How HTTP Works

Response header · non-standard

< X-Powered-By: Express

X-Powered-By Header: Remove It in Express, PHP, Next.js

X-Powered-By advertises your framework, such as Express or PHP. Remove it in Express, PHP, Next.js, ASP.NET and nginx, and why it is hygiene, not security.

Reviewed 2 min readbeginner4 sourcesTry itMarkdown
Direction
Response
Category
Diagnostics
Spec
MDN reference
Status
Non-standard: Framework convention; safe to remove
On this page

TL;DR: X-Powered-By is a non-standard header that frameworks add to name themselves (Express, PHP/8.3.12, ASP.NET). Turn it off in the framework: app.disable('x-powered-by') in Express, expose_php = Off in PHP, poweredByHeader: false in Next.js. It is hygiene, not security.

What it looks like

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
HTTP/1.1 200 OK
X-Powered-By: PHP/8.3.12

It is not defined by any RFC, browsers do nothing with it, and the value format is whatever the framework chose. It is a sibling of the Server header; Server names the web server and X-Powered-By names the application layer behind it.

Remove it

Express

import express from 'express'

const app = express()
app.disable('x-powered-by')

Or use Helmet, which removes the header among its defaults:

import helmet from 'helmet'

app.use(helmet())

The Express security guide shows app.disable('x-powered-by'), and says this does not prevent a sophisticated attacker from determining that an app is running Express; it may only discourage a casual exploit.

PHP

; php.ini
expose_php = Off

expose_php defaults to on, which makes PHP send X-Powered-By: PHP/<version>. The PHP manual lists it as changeable in php.ini only, so ini_set() at runtime will not work. Reload PHP-FPM or Apache afterwards.

Next.js

// next.config.js
module.exports = {
  poweredByHeader: false
}

Next.js adds x-powered-by: Next.js by default and this option opts out.

ASP.NET and IIS

<!-- web.config -->
<system.webServer>
  <httpProtocol>
    <customHeaders>
      <remove name="X-Powered-By" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

nginx or Apache in front

When the framework cannot be changed, strip it at the proxy. nginx:

location / {
    proxy_pass http://app;
    proxy_hide_header X-Powered-By;
}

Apache with mod_headers:

Header always unset X-Powered-By

proxy_hide_header removes the header from the upstream response before it reaches the client. Setting it at the proxy also covers several backends at once.

How much it matters

Honest accounting. Leaving the header on gives an attacker a free hint about the stack. Removing it:

  • stops the trivial banner grab and clears automated audit findings,
  • does nothing about how the framework behaves: cookie names such as connect.sid or PHPSESSID, default error pages, route shapes and static file paths all still point to the stack,
  • does not patch anything.

Do it, because it takes one line, then put your effort into updates, dependency audits and real controls such as Content-Security-Policy and X-Content-Type-Options.

Verify

curl -sI https://example.com | grep -i -E '^(x-powered-by|server)'

Check a 404 and a 500 response as well. Error handlers and upstream proxies sometimes add their own headers separately from the normal path.

Frequently asked questions

What is the X-Powered-By header?

A non-standard response header that application frameworks and runtimes add to say what generated the page, for example X-Powered-By: Express, X-Powered-By: PHP/8.3.12 or X-Powered-By: ASP.NET. It is not defined in any RFC and browsers ignore it.

How do I remove X-Powered-By in Express?

Call app.disable("x-powered-by") once at startup, or use the Helmet middleware, which removes the header as part of its defaults. If you disable it on the app and a reverse proxy adds its own copy, remove that one at the proxy.

How do I remove X-Powered-By in PHP?

Set expose_php = Off in php.ini. It can be changed only in php.ini (not with ini_set or .htaccess), and PHP-FPM needs a reload afterwards. A web server or CDN in front can also unset the header, but the PHP setting stops it being generated at all.

Is it dangerous to leave X-Powered-By on?

It tells an attacker which framework and sometimes which version you run, which narrows which known vulnerabilities to try. It is not a vulnerability itself, and removing it does not stop a determined attacker from identifying the stack through other behaviour. Keep software patched; treat removal as small extra hardening.

Does removing X-Powered-By affect SEO or performance?

It does not affect ranking. It saves a few bytes per response, which is negligible for a single request. Some audit tools flag its presence, which is the usual reason to remove it.

Sources

  1. MDN Web Docs: X-Powered-Bydeveloper.mozilla.org
  2. Express: Security best practicesexpressjs.com
  3. PHP manual: expose_phpphp.net
  4. Next.js: poweredByHeadernextjs.org

Keep going

Browse /search