Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For new Java code, add custom HTTP headers with HttpRequest.Builder.header(name, value) and send the built request using Java 11+ HttpClient. Use setHeader when a later value should replace an earlier one. In Java 8-era code, set headers on HttpURLConnection with setRequestProperty, before anything opens the connection.

Choose the Java HTTP client that fits your project

The right method depends mainly on your JDK baseline and existing dependencies. Oracle documents the JDK HttpClient API as available since Java 11; it supports blocking and asynchronous requests. If you must support Java 8, use the older URLConnection/HttpURLConnection API or a third-party library already approved for your application.

Approach Java version and dependencies Sending model Header behavior Configuration and error handling
JDK HttpClient Java 11+; no added library dependency Blocking send or asynchronous sendAsync header adds a value; setHeader replaces values for that name Build a client and immutable request; inspect the response status and body
HttpURLConnection Available in the JDK, including Java 8 Blocking connection operations setRequestProperty sets a property; addRequestProperty adds another value Configure before connection; set connection and read timeouts explicitly
Third-party client Depends on the library and version; adds a dependency Depends on the client Depends on the API; Apache HttpClient 3.1 distinguishes replacement and add methods Can provide broader HTTP configuration; verify examples against the exact version in use

For a new project on Java 11 or later, start with HttpClient unless you need a feature or integration that makes another client a better fit. In an existing Java 8 application, avoid switching libraries just to add a header if HttpURLConnection already meets the need.

Send headers with Java 11+ HttpClient

Build the request with its URI and headers, then send it through an HttpClient. This complete example sends a GET request and prints the HTTP status and response body:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class GetWithHeaders {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.example.com/items"))
                .header("X-Request-ID", "abc-123")
                .header("Accept", "application/json")
                .GET()
                .build();

        HttpResponse<String> response = client.send(
                request, HttpResponse.BodyHandlers.ofString());

        System.out.println("Status: " + response.statusCode());
        System.out.println(response.body());
    }
}

Replace the example URL and header values with those required by your endpoint. send waits for the response. To make the request asynchronously, use sendAsync; Oracle documents both sending styles for this client. The response still needs to be handled by your application.

Send a POST with headers and a body

Set the request headers on the same builder before choosing the body publisher and building the request. For JSON, the endpoint will commonly expect an appropriate content type; verify the API’s requirements.

String token = System.getenv("API_TOKEN");
String json = "{"name":"Ada"}";

HttpRequest request = HttpRequest.newBuilder(
                URI.create("https://api.example.com/items"))
        .header("Authorization", "Bearer " + token)
        .header("Content-Type", "application/json")
        .header("Accept", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(json))
        .build();

HttpResponse<String> response = client.send(
        request, HttpResponse.BodyHandlers.ofString());

This POST fragment uses the client created in the GET example. Keep credentials out of source control and avoid printing them in logs. Do not manually set protocol-controlled values such as Content-Length when the client derives them from the body publisher.

Choose between header, setHeader, and headers

Builder method Use it when Effect
header(name, value) You want to add a value, including an intentional additional value Adds the name/value pair to the request builder
setHeader(name, value) The request should have the specified value for that name Replaces previously set values for that name
headers(name, value, ...) You want to supply several headers in one call Accepts alternating header names and values

Use header for repeated values only when the target service expects them. If a request builder already has a value and your later call is intended to supersede it, use setHeader. Oracle’s builder contract also allows the HTTP client to restrict names or values it manages itself; an invalid or restricted header can result in IllegalArgumentException.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Put values that vary by request on that request’s builder. For a policy common to many requests, centralize it in the code that constructs requests or in a wrapper around the client, so the behavior remains explicit and testable.

Use HttpURLConnection in Java 8 or legacy code

URLConnection has a setup phase followed by connection. Set request properties and timeouts before any operation that may connect, including connect, getInputStream, or getOutputStream. This example handles both successful and HTTP error responses and closes the reader:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.nio.charset.StandardCharsets;

public class LegacyGetWithHeaders {
    public static void main(String[] args) throws Exception {
        HttpURLConnection connection = (HttpURLConnection)
                URI.create("https://api.example.com/items")
                        .toURL().openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("X-Request-ID", "abc-123");
        connection.setRequestProperty("Accept", "application/json");
        connection.setConnectTimeout(10_000);
        connection.setReadTimeout(10_000);

        int status = connection.getResponseCode();
        InputStream stream = status >= 400
                ? connection.getErrorStream()
                : connection.getInputStream();

        System.out.println("Status: " + status);
        if (stream != null) {
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(stream, StandardCharsets.UTF_8))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
            }
        }
        connection.disconnect();
    }
}

setRequestProperty sets a general request property; addRequestProperty adds another value. As with HttpClient, only add duplicates if the endpoint expects them. Setting connection and read timeouts prevents this example from waiting indefinitely for those phases. The actual values appropriate for an application depend on its endpoint and latency requirements.

Send a body with HttpURLConnection

For a request with a body, configure its method, headers, timeouts, and output mode before obtaining the output stream. Then write the body and read the response as in the GET example.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", "Bearer " + token);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "application/json");
connection.setDoOutput(true);

try (var output = connection.getOutputStream()) {
    output.write("{"name":"Ada"}".getBytes(StandardCharsets.UTF_8));
}

Use this fragment in place of the GET setup and perform it before calling getResponseCode or obtaining an input stream. The request properties must be set before the connection is established.

Third-party clients: check the exact API version

Libraries such as Apache HttpClient offer their own request-header methods and may suit applications that already use them or need their wider HTTP feature set. Names and behavior vary between releases. The cited Apache HttpClient 3.1 reference documents setRequestHeader/setHeader for replacement and addRequestHeader/addHeader for additional instances, but labels that API deprecated. Do not paste a 3.1 example into a current project without checking the documentation for the version actually installed.

Or skip the browser setup

If your Java task is to capture a web page rather than call an arbitrary API, ScreenshotNeo provides a screenshot API and MCP server. Its one-call GET returns a screenshot or PDF; the example below follows the published cURL form. See the ScreenshotNeo API documentation for request options and response details.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
  • Cookie banners and more than 60 known consent platforms, newsletter popups, and chat widgets can be removed before capture; each step can be turned off.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; response headers report the page verdict and billing status.
  • An MCP server gives AI agents tools for screenshots, page information, and PDF capture.
  • The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.

Learn more at ScreenshotNeo, or sign up for 1,000 free screenshots a month with no card.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot a header that does not work

  • The server says the header is missing: Verify that you added it to the same request object that is actually sent. Check the server response status and body; a client accepting a header does not mean the server recognizes or uses it.
  • A URLConnection header has no effect: Move every setRequestProperty or addRequestProperty call before connect, getInputStream, getOutputStream, or another operation that can connect implicitly.
  • The request has duplicate values: Decide whether the target endpoint allows multiple values. In HttpClient, use setHeader if a new value should replace an earlier value; with URLConnection, use setRequestProperty instead of addRequestProperty when accumulation is not intended.
  • The builder throws IllegalArgumentException: Check the header name and value for invalid input, and check whether the client reserves that field. Do not try to set values the client manages from the request body, such as Content-Length.
  • The request gets an HTTP error: Read the response status and error body. With HttpURLConnection, use getErrorStream for an error response rather than assuming getInputStream will provide its body.
  • A secret appears in diagnostics: Remove authorization values, API keys, and cookies from logs and request dumps.

Performance, reliability, and cost considerations

Reuse a configured HttpClient where appropriate and build a request for each call, keeping per-request headers attached to the right request. For legacy URL connections, set both connect and read timeouts to values suited to the service rather than leaving calls unbounded. A successful send only establishes that an HTTP response arrived: check its status and body to determine whether the server accepted the operation. No general performance or cost figure applies to adding a header itself; those depend on the application, endpoint, and client configuration.

Frequently asked questions

Does Java convert or validate every header value the server expects?

No. The JDK builder can reject invalid or client-managed fields, but application-level meaning belongs to the endpoint. Confirm required names, formats, and authentication behavior in that API’s documentation.

Can I set the same header more than once?

Yes, the Java APIs expose methods that add values, but whether duplicates are valid is determined by the field and target service. If you need exactly one value after updating a request builder, use setHeader.

Frequently Asked Questions

Does Java validate whether the server understands a custom header?

No. The client can reject invalid or client-managed fields, but the endpoint determines whether it recognizes or acts on a header. Check that API’s documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can I set the same header more than once?

The APIs provide methods that add values, but whether duplicates are valid depends on the field and endpoint. Use HttpRequest.Builder.setHeader when you want a single replacement value.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.