Of course! Here is a comprehensive guide on how to make HTTP POST requests using Java's HttpClient, which is the modern, recommended way to handle HTTP requests in Java.

We'll cover:
- The Modern
java.net.http.HttpClient(Java 11+): This is the current standard and the recommended approach. - The Classic Apache HttpClient (Legacy): Many projects still use this, so it's good to know.
- Comparison: A quick look at the differences.
Modern java.net.http.HttpClient (Java 11+)
This is the built-in, standard library client since Java 11. It's non-blocking (supports reactive programming) and has a clean, fluent API.
Key Components:
HttpClient: The main entry point. You configure it (e.g., with a proxy, SSL context).HttpRequest: Represents the request to be sent (method, URI, headers, body).HttpResponse<T>: Represents the response received from the server. TheTis a type parameter for the body (e.g.,String,byte[]).BodyPublishers: Used to create the request body (e.g., from a string, file, or form data).BodyHandlers: Used to process the response body (e.g., as a string, byte array, or stream it to a file).
Example 1: Simple POST with JSON
This is the most common use case: sending a JSON payload to a REST API endpoint.
Scenario: Send a JSON object to https://example.com/api/users to create a new user.

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 HttpClientPostExample {
public static void main(String[] args) {
// 1. Create an HttpClient
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2) // Use HTTP/2 if possible
.connectTimeout(Duration.ofSeconds(10)) // Set a connection timeout
.build();
// 2. Create the JSON payload
String jsonPayload = """
{
"name": "John Doe",
"email": "john.doe@example.com"
}
""";
// 3. Create an HttpRequest
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/api/users"))
.header("Content-Type", "application/json") // Set the content type header
.header("Accept", "application/json") // Tell the server we expect JSON back
.timeout(Duration.ofSeconds(5)) // Set a request timeout
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) // Set the method and body
.build();
// 4. Send the request and get the response
try {
System.out.println("Sending POST request...");
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// 5. Process the response
System.out.println("Response Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
} catch (Exception e) {
System.err.println("An error occurred: " + e.getMessage());
e.printStackTrace();
}
}
}
Explanation:
- We create a
HttpClientwith some basic configuration. - The JSON payload is defined as a multi-line string (using ).
HttpRequest.Builderis used to configure the request. We set the URI, addContent-TypeandAcceptheaders, and specify the method asPOST.HttpRequest.BodyPublishers.ofString(jsonPayload)converts our JSON string into a request body.client.send()blocks until the response is received. It takes the request and aBodyHandler.HttpResponse.BodyHandlers.ofString()tells the client to collect the response body into aString.- Finally, we print the status code and the body of the response.
Example 2: POST with Form Data (application/x-www-form-urlencoded)
Scenario: Send username and password to a login form.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.StringJoiner;
public class HttpClientFormPostExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
// 1. Prepare form data as a URL-encoded string
String formData = buildFormData(
Map.of(
"username", "testuser",
"password", "securePassword123",
"remember", "true"
)
);
// 2. Create the HttpRequest
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/login"))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(formData))
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Helper method to build URL-encoded form data.
*/
private static String buildFormData(Map<String, String> data) {
StringJoiner sj = new StringJoiner("&");
for (Map.Entry<String, String> entry : data.entrySet()) {
try {
sj.add(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + "=" +
URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
} catch (Exception e) {
throw new RuntimeException("Failed to encode form data", e);
}
}
return sj.toString();
}
}
Example 3: Asynchronous POST Request
HttpClient can also send requests asynchronously without blocking the current thread. This is extremely useful in modern applications.
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 AsyncHttpClientPostExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
String jsonPayload = """
{
"title": "Async Post",
"body": "This post was sent asynchronously."
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
.build();
// Send the request asynchronously
CompletableFuture<HttpResponse<String>> futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// Define what to do when the response is received
futureResponse.thenAccept(response -> {
System.out.println("Async Response Status Code: " + response.statusCode());
System.out.println("Async Response Body: " + response.body());
}).exceptionally(e -> {
System.err.println("Async request failed: " + e.getMessage());
return null;
});
// Keep the main thread alive to see the async result
System.out.println("Request sent asynchronously. Main thread continues...");
try {
// Wait for the async operation to complete (in a real app, you'd have a proper event loop)
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Classic Apache HttpClient (Legacy)
Before Java 11, the de-facto standard was the Apache HttpClient library. It's still widely used in older projects or when you need features not available in the standard library (like more advanced cookie management or connection pooling configurations).

First, you need to add the dependency to your project (e.g., in Maven's pom.xml):
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version> <!-- Use the latest version -->
</dependency>
Example: POST with JSON using Apache HttpClient
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.StringEntity;
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.ContentType;
import org.apache.hc.core5.http.io.entity.EntityUtils;
public class ApacheHttpClientPostExample {
public static void main(String[] args) {
// 1. Create a HttpClient instance
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// 2. Create an HttpPost object
HttpPost httpPost = new HttpPost("https://example.com/api/users");
// 3. Set the JSON payload
String jsonPayload = """
{
"name": "Jane Doe",
"email": "jane.doe@example.com"
}
""";
StringEntity entity = new 