Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallUse HttpRequest.Builder.header(name, value) before calling build(), then send the completed request with HttpClient. Use setHeader when an existing value must be replaced, and use headers for a compact alternating name/value list. The example below works with the Java HTTP Client introduced in Java 11 and shows GET, POST, authentication, JSON, repeated fields, asynchronous requests, and the restricted headers that Java manages itself.
Minimal working example
This complete program creates an HTTP client, adds two application headers, performs a GET, and prints the status and response body.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class CustomHeaders {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/api"))
.header("Accept", "application/json")
.header("X-Request-Id", "abc123")
.GET()
.build();
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
System.out.println(response.body());
}
}
header adds the name/value pair to this request. The headers belong to the immutable HttpRequest produced by build(); they are not added to the client globally. This keeps request-specific credentials, tracing IDs, and content negotiation separate when one client sends many requests.
Choose the header method
header: add one value
Call header(name, value) for an individual field. Calling it again with the same name can add another value. This is useful only when the HTTP field’s semantics permit multiple values. Java’s builder does not decide whether two values should instead be comma-joined; that meaning comes from the HTTP field definition and the server.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesHttpRequest request = HttpRequest.newBuilder(URI.create("https://example.com/items"))
.header("Accept", "application/json")
.header("X-Trace-Id", "trace-7f31")
.GET()
.build();
setHeader: replace a value
Use setHeader(name, value) when earlier code may already have supplied the field and the new value must replace it rather than add another value.
HttpRequest.Builder builder = HttpRequest.newBuilder(URI.create("https://example.com/items"))
.header("X-Environment", "staging");
builder.setHeader("X-Environment", "production");
HttpRequest request = builder.GET().build();
headers: compact name/value pairs
headers(String... headers) accepts alternating names and values. It is convenient for a short, fixed set, but each name must have a matching value.
HttpRequest request = HttpRequest.newBuilder(URI.create("https://example.com/items"))
.headers(
"Accept", "application/json",
"X-Request-Id", "abc123")
.GET()
.build();
Headers for a JSON POST
For a request with a body, set the media type and authorization headers and use a body publisher. The content length is normally determined by the request body publisher and should not be supplied manually.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class JsonPost {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
String json = "{"name":"Ada","active":true}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/api/users"))
.timeout(Duration.ofSeconds(30))
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", "Bearer YOUR_TOKEN")
.header("X-Request-Id", "abc123")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}
Replace the token and endpoint with values for your service. Do not hard-code real credentials in source control; read them from a protected configuration mechanism and avoid logging authorization values.
Authentication and common application headers
Most custom headers are ordinary strings. Typical patterns include:
Rank #2
- Bearer authentication:
Authorization: Bearer token. - API keys: use the exact field name required by the service, such as
X-Api-Key. - Content negotiation:
Accept: application/jsontells the server which response representation you prefer. - Request metadata: an
X-Request-Idor trace value helps correlate logs. - Conditional requests: fields such as
If-None-MatchorIf-Modified-Sinceare sent only when your caching workflow supplies the corresponding value.
The Java API does not validate whether a custom field has useful business meaning. The receiving server can still reject an unknown, malformed, unauthorized, or incorrectly formatted value.
Send requests asynchronously
Use sendAsync when a calling thread should not block while the response arrives. Header construction is the same; only response handling changes.
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("https://example.com/api"))
.header("Accept", "application/json")
.header("X-Request-Id", "async-123")
.GET()
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenAccept(response -> {
System.out.println(response.statusCode());
System.out.println(response.body());
})
.exceptionally(error -> {
error.printStackTrace();
return null;
});
Keep a reference to the returned future if the surrounding application needs to wait, cancel, or compose the operation. A request timeout and a client connection timeout address different stages: the former limits an individual request, while the latter limits establishing a connection.
Free tools Windows power users keep installed
One-click scans. No signup required.
Restricted and client-managed headers
A builder call can throw IllegalArgumentException when a name or value is malformed or when the implementation rejects that field. In the JDK implementation documented for Java SE 26, these names are normally restricted from direct user code: connection, content-length, expect, host, and upgrade. Header names are case-insensitive, so changing capitalization does not bypass the restriction.
Do not set Content-Length yourself. The request body publisher and HTTP client determine framing. Likewise, the client controls connection-level fields such as Host and Connection from the URI and protocol state. Set application headers instead, for example Authorization, Accept, or a service-specific tracing field.
The JDK module reference documents a jdk.httpclient.allowRestrictedHeaders system property that accepts a comma-separated list for overriding some defaults. Oracle labels this facility for testing and warns that protocol errors or undefined behavior are likely; contextual restrictions may remain. It is not a production remedy. If an API insists on a client-managed field, verify the protocol and choose an API design that lets Java calculate it.
Diagnose failures systematically
Builder throws IllegalArgumentException
- Check that the field name contains no illegal characters and that the value is valid for the field.
- Check the restricted list for your JDK version, especially
Host,Content-Length, andConnection. - Confirm that your code is calling
setHeaderwhen replacement was intended, rather than accumulating values withheader.
Server returns 400 or 401
A syntactically valid Java request can still be rejected. Verify the exact required spelling, token prefix, media type, and value format in the service’s API documentation. A 401 generally indicates missing or invalid authentication; a 400 commonly indicates malformed input or a missing required field.
The server sees duplicate values
Inspect every builder path for repeated header calls and shared helper methods. Replace with setHeader when only one value is valid. Do not blindly combine values with commas: some HTTP fields define lists, while others do not.
JSON is rejected despite a body
Set Content-Type: application/json, ensure the body is valid JSON, and use a character encoding appropriate for the endpoint. Accept describes the response and does not replace Content-Type, which describes the request body.
A timeout or connection error occurs
Distinguish DNS, TLS, connection, request, and server-response failures in your exception handling. Set explicit, realistic timeouts, check the URI scheme and hostname, and avoid retrying non-idempotent operations unless the service documents safe retry behavior. Never retry automatically with the same payment or mutation request merely because a client-side timeout occurred; the server may have completed it.
Rank #4
Reusable request construction
For an application that sends many calls, centralize common headers while leaving per-request values adjustable.
HttpRequest.Builder baseRequest(String url, String token) {
return HttpRequest.newBuilder(URI.create(url))
.header("Accept", "application/json")
.header("Authorization", "Bearer " + token)
.header("User-Agent", "inventory-client/1.0");
}
HttpRequest request = baseRequest("https://example.com/api/items", token)
.setHeader("X-Request-Id", requestId)
.GET()
.build();
Do not reuse a built request while trying to mutate it: HttpRequest is immutable. Create a new builder or derive one through your own helper method. Keep secrets out of exception messages and request logs; if diagnostic logging is required, redact authorization and cookie values.
Or skip the browser setup
If your goal is obtaining a clean image or PDF of a web page rather than making an API request from Java, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. Its capture process accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot.
Here is the supplied cURL call; see the ScreenshotNeo documentation for parameters 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
Only clean shots are billed. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Sign up at ScreenshotNeo.
Best Value
Java, cURL, Python, and Node.js equivalents
The same ScreenshotNeo request can be made from scripts when Java is not the right integration point.
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
For a Java integration, use the same HttpClient pattern shown earlier: put the access key and URL in the query string, request the binary response with HttpResponse.BodyHandlers.ofByteArray(), and write the bytes to a file. Keep the access key confidential.
Practical checklist
- Build the URI and request before sending.
- Use
headerto add,setHeaderto replace, andheadersfor alternating pairs. - Set
Content-Typefor the request body andAcceptfor the desired response. - Let Java determine
Content-Lengthand other restricted connection fields. - Use explicit timeouts and handle both HTTP status codes and transport exceptions.
- Redact authorization and other secrets in logs.
- Check the JDK version when behavior depends on restricted-header rules.
Frequently Asked Questions
Can I add headers after calling build()?
No. Build a new request (or a new builder in your helper code) with the additional fields; the built HttpRequest is immutable.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Does Java HttpClient automatically follow redirects with my custom headers?
Redirect behavior is configured on HttpClient, while this article’s header methods configure the original request. Verify how your target service expects credentials to be handled across redirects before enabling or relying on redirect handling.
Which Java version contains HttpClient?
The standard java.net.http client API is available starting with Java 11. Restricted-header details can vary by JDK implementation and version, so consult the documentation for the runtime you deploy.
Quick Recap
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.

