Of course! Here is a comprehensive guide to making HTTP requests in Java, covering the modern standard approach, the classic legacy method, and popular third-party libraries.

Summary of Approaches
| Method | When to Use | Pros | Cons |
|---|---|---|---|
java.net.http (JDK 11+) |
Recommended for modern Java (11+). New projects, standard library. | - Modern, fluent API - Built-in support for HTTP/2 - Async support is excellent - Part of the JDK, no dependencies |
- Not available in Java 8 or older |
HttpURLConnection (Legacy) |
When you're on Java 8 or older and want to avoid third-party libraries. | - Part of the standard library - No external dependencies |
- Verbose and clunky API - Poor async support - Lacks modern features |
| Third-Party Libraries | When you need maximum flexibility, power, or a simpler API (e.g., for REST). | - Often much simpler and more powerful - Excellent features (JSON parsing, interceptors, etc.) - Mature and widely used |
- Adds an external dependency to your project |
Modern Approach: java.net.http (Java 11+)
This is the current standard and the recommended way to handle HTTP requests in modern Java applications. It's clean, powerful, and supports both synchronous and asynchronous operations.
Example: Synchronous GET Request
This example fetches the content of https://jsonplaceholder.typicode.com/posts/1.
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Java11HttpClientExample {
public static void main(String[] args) {
// 1. Create an HttpClient
HttpClient client = HttpClient.newHttpClient();
// 2. Create an HttpRequest
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.build();
try {
// 3. Send the request and get the response
// The .body() method returns the response body as a String
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// 4. Check the status code and print the body
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body:");
System.out.println(response.body());
} catch (IOException | InterruptedException e) {
// Handle exceptions
System.err.println("Request failed: " + e.getMessage());
e.printStackTrace();
// Restore the interrupted status
Thread.currentThread().interrupt();
}
}
}
Example: Synchronous POST Request with JSON
This example sends a JSON payload to create a new resource.
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse.BodyHandlers;
public class Java11PostExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
// The JSON payload we want to send
String jsonBody = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
.header("Content-Type", "application/json") // Set the content type header
.POST(BodyPublishers.ofString(jsonBody)) // Set the request method and body
.build();
try {
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body (created post):");
System.out.println(response.body());
} catch (IOException | InterruptedException e) {
System.err.println("Request failed: " + e.getMessage());
Thread.currentThread().interrupt();
}
}
}
Example: Asynchronous GET Request
This is a key strength of the java.net.http API. It doesn't block the calling thread.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class Java11AsyncExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.build();
// Send the request asynchronously
CompletableFuture<HttpResponse<String>> futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// Define what to do when the response is ready
futureResponse.thenAccept(response -> {
System.out.println("Async Status Code: " + response.statusCode());
System.out.println("Async Response Body:");
System.out.println(response.body());
});
System.out.println("Request sent. Doing other work here...");
// The main thread needs to stay alive to receive the async response
// In a real app, the server would keep running.
try {
// Wait for the async operation to complete
futureResponse.join();
} catch (Exception e) {
System.err.println("Async request failed: " + e.getMessage());
}
}
}
Legacy Approach: HttpURLConnection (Java 8 and older)
Before Java 11, this was the standard way to do it in the JDK. It's more verbose and less flexible.
Example: GET Request
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class LegacyUrlConnectionExample {
public static void main(String[] args) {
try {
URL url = new URL("https://jsonplaceholder.typicode.com/posts/1");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Set request method
connection.setRequestMethod("GET");
// Get the response code
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// If the request was successful (200 OK)
if (responseCode == HttpURLConnection.HTTP_OK) {
// Read the response
BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// Print the response
System.out.println("Response Body:");
System.out.println(response.toString());
} else {
System.out.println("GET request failed");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Third-Party Libraries
These libraries are extremely popular because they simplify common tasks like JSON handling, header management, and authentication.
a) Apache HttpClient
A very powerful and mature library from the Apache Software Foundation.
Setup (Maven):

<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version> <!-- Use the latest version -->
</dependency>
Example: GET Request
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.io.entity.EntityUtils;
public class ApacheHttpClientExample {
public static void main(String[] args) {
// 1. Create a HttpClient
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 2. Create an HttpGet request
HttpGet request = new HttpGet("https://jsonplaceholder.typicode.com/posts/1");
// 3. Execute the request
try (CloseableHttpResponse response = httpClient.execute(request)) {
// 4. Get the response entity and print it
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("Status Code: " + response.getCode());
System.out.println("Response Body:");
System.out.println(responseBody);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
b) OkHttp
A modern, efficient HTTP client from Square (the same company behind Retrofit). It's very easy to use.
Setup (Maven):
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version> <!-- Use the latest version -->
</dependency>
Example: GET Request
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttpExample {
public static void main(String[] args) {
// 1. Create an OkHttpClient
OkHttpClient client = new OkHttpClient();
// 2. Build a request
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.build();
try (Response response = client.newCall(request).execute()) {
// 3. Check for successful response
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
// 4. Get the response body
String responseBody = response.body().string();
System.out.println("Status Code: " + response.code());
System.out.println("Response Body:");
System.out.println(responseBody);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Which One Should I Choose?
- For new projects on Java 11 or newer: Use
java.net.http. It's the standard, has a great API, and requires no external dependencies. - For projects on Java 8 or older: Use
HttpURLConnectionif you want to avoid dependencies, or Apache HttpClient / OkHttp if you need a more robust and feature-rich solution. The latter two are highly recommended for any serious application. - For Android Development: OkHttp is the de-facto standard and is highly recommended due to its efficiency and excellent integration with other Android libraries.
