Calling APIs with the Java HTTP Client
Since Java 11, java.net.http.HttpClient is the standard way to call HTTP APIs, with no extra library.
- Build one client and reuse it:
HttpClient.newBuilder().connectTimeout(…). - Build a request: address, method, headers, body and timeout.
- Send it with
send(blocking) orsendAsync(returns aCompletableFuture). - Choose a body handler:
ofString(),ofFile(path)orofInputStream().
It uses HTTP/2 automatically, and HTTP/3 is available since Java 26. Always set timeouts and check the status code: a 404 or 500 is a normal response, not an exception.
In Spring apps, RestClient and HTTP interface clients add JSON mapping and error handling on top; in plain Java, pair HttpClient with Jackson for JSON.
Example
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build(); // create once, reuse
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.github.com/repos/openjdk/jdk"))
.header("Accept", "application/json")
.timeout(Duration.ofSeconds(10))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
System.out.println(response.body().substring(0, 80));
} else {
System.out.println("Failed with status " + response.statusCode());
}
// Several calls in parallel
List<URI> uris = List.of(URI.create("https://example.com/a"), URI.create("https://example.com/b"));
List<CompletableFuture<String>> calls = uris.stream()
.map(u -> client.sendAsync(HttpRequest.newBuilder(u).build(), HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body))
.toList();Common mistake
Expecting an exception for a 404 or 500. HttpClient only throws for network problems and timeouts; always check statusCode().
Under the hood
HttpClient manages a connection pool, so creating one per request wastes connections and threads. With virtual threads, plain blocking send calls scale well and read more simply than long sendAsync chains. To POST JSON, use HttpRequest.BodyPublishers.ofString(json) with a Content-Type: application/json header.
Check yourself
When does HttpClient.send throw an exception?
How this connects
Know these first
Where this leads
You've reached the end of this thread. Try a learning path for what's next.
Part of Upgrade from Java 8 to Java 25.
Was this lesson helpful?
Finished reading? Mark it complete to track your progress.