Overriding the HTTP Host value in cURL is useful when testing name-based virtual hosts, multi-tenant routes, reverse proxies, and staging listeners before any shared DNS change is made. It lets one request present a different site name to the application even when the connection still goes to a local listener, an IP address, or a temporary backend.

In cURL, --header 'Host: ...' replaces the hostname that the HTTP layer sees. The URL still decides where cURL connects unless the URL already uses an IP address or another option such as --resolve overrides name resolution. On HTTP/1.1, the custom value is sent as the Host: header. On HTTP/2 and HTTP/3, curl maps the custom hostname to :authority instead.

A custom host name changes routing only after the request reaches the server. On HTTPS, the URL host still controls SNI and certificate checks, so TLS tests need the URL host, certificate, and any --resolve mapping to stay aligned. Cookie scope, redirects, tenant selection, and generated absolute URLs can also change with the overridden name, so keep these checks pointed at controlled test targets.

Steps to override the Host header with cURL:

  1. Send a baseline request to the target listener so the default host value is visible before any override is added.
    $ curl --silent --show-error http://127.0.0.1:18080/
    {
      "host": "127.0.0.1:18080",
      "path": "/",
      "method": "GET"
    }

    Any endpoint that echoes request headers or writes the received host to its access log is enough for this check.

  2. Repeat the request with a custom Host header so the application receives the alternate site name instead of the URL host.
    $ curl --silent --show-error --header 'Host: app.internal.example' http://127.0.0.1:18080/
    {
      "host": "app.internal.example",
      "path": "/",
      "method": "GET"
    }

    Success is when the response or server log shows app.internal.example while the path and method stay unchanged.

  3. Add --http1.1 and --verbose when the exact outbound header line needs to be inspected during debugging.
    $ curl --http1.1 --silent --show-error --verbose --header 'Host: app.internal.example' --output /dev/null http://127.0.0.1:18080/
    *   Trying 127.0.0.1:18080...
    * Connected to 127.0.0.1 (127.0.0.1) port 18080
    > GET / HTTP/1.1
    > Host: app.internal.example
    > User-Agent: curl/8.7.1
    > Accept: */*
    >
    ##### snipped #####

    On HTTP/2 and HTTP/3, curl uses :authority for the custom host name instead of sending a literal Host: line on the wire.

  4. Pair the header override with --resolve when the request must also connect to a chosen address without changing system DNS.
    $ curl --http1.1 --silent --show-error --verbose --header 'Host: app.internal.example' --resolve preview.example.test:18080:127.0.0.1 --output /dev/null http://preview.example.test:18080/
    * Added preview.example.test:18080:127.0.0.1 to DNS cache
    * Hostname preview.example.test was found in DNS cache
    *   Trying 127.0.0.1:18080...
    * Connected to preview.example.test (127.0.0.1) port 18080
    > GET / HTTP/1.1
    > Host: app.internal.example
    ##### snipped #####

    On HTTPS, the overridden Host value does not change SNI or certificate validation. The URL host still has to match the certificate unless the page is intentionally testing a different TLS path.