Customizing the HTTP Host header in curl enables precise testing of virtual hosts, reverse proxies, and multi-tenant applications that rely on host names for routing. Adjusting the header clarifies how traffic is dispatched when several sites share the same IP address and helps isolate misrouted requests, broken redirects, and odd cache behavior without touching DNS configuration.

In HTTP/1.1 and later, the Host header is mandatory and informs the server which site a client wants even when the TCP endpoint is identical. curl derives this header from the URL hostname and sends it with the request metadata, while options such as --header (-H) allow overriding or adding headers. Flags like --resolve or --connect-to refine how hostnames map to addresses, so traffic can be directed at specific backends while still sending a chosen host name.

Unexpected hostnames can confuse virtual host configuration, upset strict TLS setups, or trigger intrusion detection systems. Mismatched host and certificate names or duplicate Host headers may be treated as header smuggling or cache poisoning attempts. Custom host values therefore belong in controlled test environments or production investigations with explicit authorization and careful logging.

Steps to override the Host header with cURL:

  1. Run a command to display the installed curl version as a quick availability check.
    $ curl --version
    curl 8.5.0 (aarch64-unknown-linux-gnu) libcurl/8.5.0 OpenSSL/3.0.13 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.7 libpsl/0.21.2 (+libidn2/2.3.7) libssh/0.10.6/openssl/zlib nghttp2/1.59.0 librtmp/2.3 OpenLDAP/2.6.7
    Release-Date: 2023-12-06, security patched: 8.5.0-2ubuntu10.6
    Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
    Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd
    ##### snipped #####

    If the command is not found on Linux or other platforms, installing curl from the system package manager or official distribution provides the required binary.

  2. Send a verbose HTTP request to a test URL to see the default Host header that curl derives from the URL hostname.
    $ curl -v --silent http://api.example.net/
    * Host api.example.net:80 was resolved.
    * IPv6: (none)
    * IPv4: 127.0.0.1
    *   Trying 127.0.0.1:80...
    * Connected to api.example.net (127.0.0.1) port 80
    > GET / HTTP/1.1
    > Host: api.example.net
    > User-Agent: curl/8.5.0
    > Accept: */*
    > 
    ##### snipped #####

    The line beginning with > Host: shows the header value that virtual host configuration and reverse proxies use for routing decisions.

  3. Repeat the request while overriding the Host header with a custom hostname to simulate a different virtual host on the same endpoint.
    $ curl -v --silent --header 'Host: app.internal.example' http://api.example.net/
    * Host api.example.net:80 was resolved.
    * IPv6: (none)
    * IPv4: 127.0.0.1
    *   Trying 127.0.0.1:80...
    * Connected to api.example.net (127.0.0.1) port 80
    > GET / HTTP/1.1
    > Host: app.internal.example
    > User-Agent: curl/8.5.0
    > Accept: */*
    > 
    ##### snipped #####

    Supplying an arbitrary Host value can expose unintended content, interfere with application security checks, or trigger web application firewalls that watch for host header attacks.

  4. Combine a custom Host header with --resolve to route a hostname to a specific IP address without altering external DNS.
    $ curl -v --silent --header 'Host: app.internal.example' --resolve app.internal.example:80:127.0.0.1 http://app.internal.example/
    * Added app.internal.example:80:127.0.0.1 to DNS cache
    * Hostname app.internal.example was found in DNS cache
    *   Trying 127.0.0.1:80...
    * Connected to app.internal.example (127.0.0.1) port 80
    > GET / HTTP/1.1
    > Host: app.internal.example
    > User-Agent: curl/8.5.0
    > Accept: */*
    > 
    ##### snipped #####

    The --resolve option pins a hostname, port, and IP triple for curl, which is useful when testing new backends, CDNs, or reverse proxies before DNS records change.

  5. Filter the verbose output to confirm that the outgoing request carries the intended Host header value.
    $ curl -v --silent --header 'Host: app.internal.example' http://api.example.net/ 2>&1 | grep '^> Host:'
    > Host: app.internal.example

    Successful override appears when the extracted line shows the custom hostname after > Host: while the connection details still reflect the desired network target.