poweredByHeader

Removes the x-powered-by response header when set to false.

Signature
poweredByHeader?: boolean

Parameters

ParameterTypeDescription
$poweredByHeaderoptionalboolean= trueWhether Next.js adds the `x-powered-by` header to responses. Set to `false` to opt out.

Next.js adds x-powered-by: Next.js to responses by default. Setting poweredByHeader: false stops it being sent. That is the whole feature — a boolean with no options.

When to reach for it

It appears on essentially every security hardening checklist, and scanners flag the header as technology disclosure. Turning it off costs nothing and removes one signal that tells an automated scanner which framework and stack to probe. If you have a compliance review or a penetration test coming, set it before someone files it as a finding.

What trips people up

  • It is obscurity, not security. The header is one of many tells — build output paths, the __next asset prefix, RSC payload shapes and error page markup all still identify the framework. Removing it does not make the app harder to attack, only marginally harder to categorise.
  • It only controls the header Next.js itself sets. A proxy, load balancer or platform in front of the app can add its own x-powered-by or server header, so verify with curl -I against the deployed URL rather than against localhost.
  • next.config.ts is read at build and server start, so a change needs a restart or redeploy before it takes effect.

Example

Example · typescript
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  poweredByHeader: false,
}

export default nextConfig

When to use it

  • Clear a technology-disclosure finding from a security scan or penetration test.
  • Meet a hardening baseline that forbids framework identification headers.
  • Trim one header from every response on a very high-traffic site.
  • Keep responses consistent with a proxy that already strips identifying headers.

Frequently asked questions

How do I remove the x-powered-by header in Next.js?

Set `poweredByHeader: false` in next.config.ts, then restart or redeploy. Next.js adds `x-powered-by` by default and this boolean is the only switch for it. Confirm with `curl -I` against the deployed URL, since a proxy in front of the app can add the header back independently.

Is leaving x-powered-by enabled a security risk?

It is a minor information disclosure rather than a vulnerability — it tells scanners which framework you run, so they can prioritise relevant probes. Removing it is free and clears the finding, but it is obscurity, not protection: asset paths, RSC payloads and error pages still identify Next.js.

Why is x-powered-by still in my responses after setting poweredByHeader to false?

Because something other than Next.js is adding it, or the config change has not been redeployed. next.config.ts is read at build and server start, so restart the server first; if the header survives, check your reverse proxy, load balancer or hosting edge layer, which can set its own x-powered-by or server header.

More examples

Verifying the header is gone

An empty result means Next.js is no longer emitting the header. If a value still comes back after a redeploy, something in front of the app is adding it — a reverse proxy, a PHP-era default in an old nginx config, or a platform edge layer. Check against the deployed URL rather than localhost, because the local dev server does not exercise the same proxy chain.

Example · bash
curl -sI https://example.com/ | grep -i 'x-powered-by'
# no output when poweredByHeader is false

Combined with explicit security headers

Shows where this option sits in a realistic hardening pass. Removing x-powered-by is the smallest item on the list; the headers() function is what actually changes an attacker's options. Note that poweredByHeader is a top-level boolean and cannot be expressed as a headers() entry, because you are suppressing a header rather than adding one.

Example · typescript
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  poweredByHeader: false,
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          { key: 'X-Content-Type-Options', value: 'nosniff' },
          { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
          {
            key: 'Strict-Transport-Security',
            value: 'max-age=63072000; includeSubDomains; preload',
          },
        ],
      },
    ]
  },
}

export default nextConfig

Keeping the header in development only

Production responses omit the header while local and preview responses keep it, which is occasionally useful when you are debugging a proxy chain and want to confirm a response actually came from the Next.js server rather than a cache. next.config.ts is evaluated once at build and server start, so the branch resolves per deployment, not per request.

Example · typescript
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  poweredByHeader: process.env.NODE_ENV !== 'production',
}

export default nextConfig

Discussion

  • Be the first to comment on this lesson.