Question
How to Use java.net.URLConnection for HTTP Requests in Java
Question
I often see questions about using java.net.URLConnection, and the Oracle tutorial is very brief.
It mostly shows how to send a simple GET request and read the response. It does not clearly explain how to use it to:
- send a
POSTrequest - set request headers
- read response headers
- handle cookies
- submit an HTML form
- upload a file
- work with more advanced HTTP request/response behavior
How can java.net.URLConnection be used to send and handle advanced HTTP requests in Java?
Short Answer
By the end of this page, you will understand how Java's URLConnection and, more specifically, HttpURLConnection are used for HTTP communication. You will learn how to send GET and POST requests, add headers, read status codes and response headers, submit form data, upload files, and manage cookies in a beginner-friendly way.
Concept
URLConnection is Java's general-purpose API for communicating with resources identified by a URL. When that URL uses the http or https protocol, the actual object is usually an instance of HttpURLConnection.
That distinction matters:
URLConnectionis the base class for many kinds of connections.HttpURLConnectionadds HTTP-specific features such as:- request method (
GET,POST, etc.) - response status code
- redirects
- HTTP headers
- request method (
In real programs, you usually create a URL, open a connection, cast it to HttpURLConnection, configure the request, optionally write a request body, then read the response.
A typical HTTP exchange in Java involves these steps:
- Create a
URL - Open the connection
- Cast to
HttpURLConnection - Set request method and headers
- If needed, enable output and write request data
- Read the response code
- Read the response body or error body
- Close streams and disconnect
This matters because most applications talk to APIs, web services, login systems, file upload endpoints, or external platforms over HTTP. Understanding this low-level API helps you understand what higher-level libraries are doing under the hood.
Mental Model
Think of HttpURLConnection like filling out and sending a postal package:
- The URL is the destination address.
- The request method (
GET,POST) is the type of service you choose. - Headers are labels on the package, such as content type or authorization.
- The request body is the item you put inside the package.
- The response code is the delivery result.
- The response headers are metadata returned by the receiver.
- The response body is the message sent back.
If you only do a GET, you are basically asking, "Please send me the information at this address." If you do a POST, you are sending data along with the request.
Syntax and Examples
Basic GET request
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class GetExample {
public static void main(String[] args) throws Exception {
URL url = new URL("https://api.example.com/users");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");
int status = connection.getResponseCode();
System.out.println("Status: " + status);
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream())
);
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
System.out.println(response);
connection.disconnect();
}
}
This example:
- opens an HTTP connection
- sends a
GETrequest - asks for JSON using the
Acceptheader - reads the response body
Basic POST request
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class PostExample {
public static void main(String[] args) throws Exception {
URL url = new URL("https://api.example.com/login");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
connection.setDoOutput(true);
String formData = "username=alice&password=secret";
byte[] out = formData.getBytes(StandardCharsets.UTF_8);
try (OutputStream os = connection.getOutputStream()) {
os.write(out);
}
int status = connection.getResponseCode();
System.out.println("Status: " + status);
connection.disconnect();
}
}
Important points:
setDoOutput(true)is required when sending a request body.Content-Typetells the server what format you are sending.getOutputStream()is how you write the body.
Setting request headers
connection.setRequestProperty("Authorization", "Bearer your-token");
connection.setRequestProperty("User-Agent", "MyJavaApp/1.0");
connection.setRequestProperty("Accept", "application/json");
Reading response headers
String contentType = connection.getHeaderField("Content-Type");
String setCookie = connection.getHeaderField("Set-Cookie");
System.out.println(contentType);
System.out.println(setCookie);
You can also read all headers:
for (var entry : connection.getHeaderFields().entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
Step by Step Execution
Example: sending form data
URL url = new URL("https://example.com/login");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
connection.setDoOutput(true);
String body = "email=test%40example.com&password=abc123";
try (OutputStream os = connection.getOutputStream()) {
os.write(body.getBytes(StandardCharsets.UTF_8));
}
int status = connection.getResponseCode();
What happens step by step
-
new URL(...)- Creates a URL object that points to the target endpoint.
-
url.openConnection()- Opens a connection object for that URL.
- Because the URL uses HTTP or HTTPS, the object is really an
HttpURLConnection.
-
setRequestMethod("POST")- Tells Java to use the HTTP
POSTmethod.
- Tells Java to use the HTTP
-
setRequestProperty("Content-Type", ...)- Adds an HTTP header so the server knows the request body format.
-
setDoOutput(true)- Tells the connection that you plan to send data in the request body.
-
Build the
bodystring- This is URL-encoded form data, similar to what a browser sends for a simple HTML form.
-
getOutputStream()- Opens a stream connected to the outgoing HTTP request body.
-
os.write(...)- Writes the bytes of the form data to the request.
-
getResponseCode()- Sends the request if it has not already been sent.
- Waits for the server response.
- Returns the HTTP status code such as
200,201,400, or500.
A useful detail: the request is often not fully sent until you read or request response information, such as getResponseCode() or getInputStream().
Real World Use Cases
Common places this is used
-
Calling REST APIs
- Send
GETrequests to fetch users, orders, or reports. - Send
POSTrequests to create new records.
- Send
-
Logging into a service
- Submit username and password as form data or JSON.
-
Sending authentication headers
- Add tokens using
Authorizationheaders.
- Add tokens using
-
Submitting HTML forms
- Use
application/x-www-form-urlencodedfor simple forms. - Use
multipart/form-datafor file uploads.
- Use
-
Reading API metadata
- Check content type, rate limit headers, cache headers, or cookies.
-
Downloading files
- Read bytes from the input stream and save them locally.
-
Working with session-based systems
- Read cookies from login responses and send them on later requests.
Real Codebase Usage
In real projects, developers often wrap HttpURLConnection in helper methods so the rest of the application does not deal with repetitive setup code.
Common patterns
Guard clauses for status codes
int status = connection.getResponseCode();
if (status < 200 || status >= 300) {
throw new RuntimeException("Request failed with status: " + status);
}
This quickly stops processing when the server returns an error.
Reading the error stream
InputStream stream = status >= 400
? connection.getErrorStream()
: connection.getInputStream();
Servers often send useful error details in the error stream.
Validation before sending requests
Developers often validate inputs before building the request:
- ensure required fields are present
- avoid null tokens
- confirm file paths exist before upload
Helper methods
A codebase might have methods like:
sendGet(String url)sendPost(String url, String body, String contentType)readResponse(HttpURLConnection connection)
This reduces duplication and makes testing easier.
Cookie handling
Java can use a CookieManager so cookies are stored and resent automatically:
import java.net.CookieHandler;
import java.net.CookieManager;
CookieHandler.setDefault(new CookieManager());
This is useful when working with login sessions.
Timeouts
Real applications usually set timeouts:
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
Without timeouts, a request may hang longer than expected.
Common Mistakes
1. Using URLConnection when you need HTTP-specific features
Broken idea:
URLConnection connection = url.openConnection();
connection.setRequestProperty("Accept", "application/json");
// Cannot access HTTP status code directly here
Use HttpURLConnection when working with HTTP:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
2. Forgetting setDoOutput(true) for POST bodies
Broken code:
connection.setRequestMethod("POST");
OutputStream os = connection.getOutputStream();
Safer version:
connection.setRequestMethod("POST");
connection.setDoOutput(true);
3. Not encoding form data properly
Broken code:
String body = "name=John Doe&city=New York";
Spaces and special characters should be encoded:
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
String body = "name=" + URLEncoder.encode("John Doe", StandardCharsets.UTF_8)
+ "&city=" + URLEncoder.encode("New York", StandardCharsets.UTF_8);
4. Always reading only getInputStream()
Broken assumption:
String response = new String(connection.getInputStream().readAllBytes());
If the server returns an error code, getInputStream() may fail. Check the status code and use getErrorStream() when needed.
5. Forgetting to close streams
Always use try-with-resources:
try (InputStream is = connection.getInputStream()) {
// read response
}
6. Not setting the correct Content-Type
If you send JSON but label it as form data, the server may reject it.
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
7. Assuming cookies are automatic in every setup
Cookies are not always managed the way beginners expect. Use a CookieManager if you need session persistence across requests.
Comparisons
| Concept | Purpose | When to use |
|---|---|---|
URLConnection | Generic URL connection base class | When you do not need protocol-specific features |
HttpURLConnection | HTTP-specific connection handling | For HTTP/HTTPS requests |
GET | Retrieve data | Reading resources, API fetches |
POST | Send data to the server | Creating records, submitting forms, login |
application/x-www-form-urlencoded | Simple key-value form body | HTML forms without file upload |
multipart/form-data | Form body with separate parts | File uploads and mixed form fields |
| Request headers | Metadata sent to server | Auth, content type, accepted response format |
| Response headers | Metadata sent by server | Cookies, caching, content type, rate limits |
GET vs POST
| Feature | GET | POST |
|---|---|---|
| Sends data in URL | Yes | Usually no |
| Has request body | Usually no | Yes |
| Common use | Read data | Submit data |
| Bookmarkable | Yes | Usually no |
application/x-www-form-urlencoded vs multipart/form-data
| Format | Best for | Notes |
|---|---|---|
application/x-www-form-urlencoded | Simple text fields | Compact and easy to generate |
multipart/form-data | File uploads | More complex format with boundaries |
Cheat Sheet
Quick reference
Open a connection
URL url = new URL("https://example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
Set request method
connection.setRequestMethod("GET");
connection.setRequestMethod("POST");
Set headers
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
Send a request body
connection.setDoOutput(true);
try (OutputStream os = connection.getOutputStream()) {
os.write(dataBytes);
}
Read response code
int status = connection.getResponseCode();
Read response stream safely
InputStream stream = status >= 400
? connection.getErrorStream()
: connection.getInputStream();
Read a response header
String contentType = connection.getHeaderField("Content-Type");
Timeouts
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
Form encoding
String value = URLEncoder.encode("hello world", StandardCharsets.UTF_8);
Cookies
CookieHandler.setDefault(new CookieManager());
Always remember
- Cast to
HttpURLConnectionfor HTTP features - Use
setDoOutput(true)before writing a body - Set the correct
Content-Type - Check the status code
- Use
getErrorStream()for error responses - Close streams with try-with-resources
- Call
disconnect()when finished
FAQ
When should I use HttpURLConnection instead of URLConnection?
Use HttpURLConnection when the URL is HTTP or HTTPS and you need HTTP-specific features like methods, status codes, and headers.
How do I send JSON with HttpURLConnection?
Set Content-Type to application/json; charset=UTF-8, call setDoOutput(true), and write the JSON string to the output stream.
How do I submit an HTML form in Java?
For simple text fields, send URL-encoded data with application/x-www-form-urlencoded. For file uploads, use multipart/form-data.
How do I read HTTP response headers in Java?
Use getHeaderField("Header-Name") for one header or getHeaderFields() for all headers.
How do I handle cookies with HttpURLConnection?
Use a CookieManager with CookieHandler.setDefault(...) so cookies can be stored and reused across requests.
Why does getInputStream() fail on some requests?
If the server returns an error status such as 404 or 500, the content may be available through getErrorStream() instead.
Can HttpURLConnection upload files?
Yes. You can build a multipart/form-data request manually and write both form fields and file bytes to the output stream.
Mini Project
Description
Build a small Java utility that logs in to a server using form data, reads the response, and prints important response headers. This demonstrates the most common HttpURLConnection tasks in one practical example: sending a POST request, setting headers, writing form data, reading the status code, and handling success or error responses.
Goal
Create a reusable Java method that sends form data with POST and returns the server response as text.
Requirements
- Send a
POSTrequest to a given URL. - Set
Content-Typetoapplication/x-www-form-urlencoded; charset=UTF-8. - Accept a map of form fields and URL-encode each key and value.
- Read the response body for both success and error status codes.
- Print the HTTP status code and all response headers.
Keep learning
Related questions
Add External JAR Files to an IntelliJ IDEA Java Project
Learn how to add external JAR dependencies to an IntelliJ IDEA Java project using module libraries, and when to use Maven or Gradle instead.
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Call a Method After a Delay in Android Java
Learn how to run Java code after a delay in Android using Handler.postDelayed, manage the main thread, and cancel callbacks safely.