Question

How to Use java.net.URLConnection for HTTP Requests in Java

javahttphttprequesthttpurlconnectionurlconnection

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 POST request
  • 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:

  • URLConnection is the base class for many kinds of connections.
  • HttpURLConnection adds HTTP-specific features such as:
    • request method (GET, POST, etc.)
    • response status code
    • redirects
    • HTTP headers

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:

  1. Create a URL
  2. Open the connection
  3. Cast to HttpURLConnection
  4. Set request method and headers
  5. If needed, enable output and write request data
  6. Read the response code
  7. Read the response body or error body
  8. 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.

Take Quiz

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 GET request
  • asks for JSON using the Accept header
  • 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-Type tells 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

  1. new URL(...)

    • Creates a URL object that points to the target endpoint.
  2. url.openConnection()

    • Opens a connection object for that URL.
    • Because the URL uses HTTP or HTTPS, the object is really an HttpURLConnection.
  3. setRequestMethod("POST")

    • Tells Java to use the HTTP POST method.
  4. setRequestProperty("Content-Type", ...)

    • Adds an HTTP header so the server knows the request body format.
  5. setDoOutput(true)

    • Tells the connection that you plan to send data in the request body.
  6. Build the body string

    • This is URL-encoded form data, similar to what a browser sends for a simple HTML form.
  7. getOutputStream()

    • Opens a stream connected to the outgoing HTTP request body.
  8. os.write(...)

    • Writes the bytes of the form data to the request.
  9. 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, or 500.

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 GET requests to fetch users, orders, or reports.
    • Send POST requests to create new records.
  • Logging into a service

    • Submit username and password as form data or JSON.
  • Sending authentication headers

    • Add tokens using Authorization headers.
  • Submitting HTML forms

    • Use application/x-www-form-urlencoded for simple forms.
    • Use multipart/form-data for file uploads.
  • 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.
Take Quiz

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

ConceptPurposeWhen to use
URLConnectionGeneric URL connection base classWhen you do not need protocol-specific features
HttpURLConnectionHTTP-specific connection handlingFor HTTP/HTTPS requests
GETRetrieve dataReading resources, API fetches
POSTSend data to the serverCreating records, submitting forms, login
application/x-www-form-urlencodedSimple key-value form bodyHTML forms without file upload
multipart/form-dataForm body with separate partsFile uploads and mixed form fields
Request headersMetadata sent to serverAuth, content type, accepted response format
Response headersMetadata sent by serverCookies, caching, content type, rate limits

GET vs POST

FeatureGETPOST
Sends data in URLYesUsually no
Has request bodyUsually noYes
Common useRead dataSubmit data
BookmarkableYesUsually no

application/x-www-form-urlencoded vs multipart/form-data

FormatBest forNotes
application/x-www-form-urlencodedSimple text fieldsCompact and easy to generate
multipart/form-dataFile uploadsMore complex format with boundaries
Take Quiz

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 HttpURLConnection for 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.

Take Quiz

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

  1. Send a POST request to a given URL.
  2. Set Content-Type to application/x-www-form-urlencoded; charset=UTF-8.
  3. Accept a map of form fields and URL-encode each key and value.
  4. Read the response body for both success and error status codes.
  5. Print the HTTP status code and all response headers.
Take Quiz

Keep learning

Related questions

View more