Safeguard
Security

Java URLEncode: How to Encode URLs Safely in Java

Java urlencode is usually URLEncoder.encode, but it is built for form bodies, not full URLs. Here is when to use it and when it introduces bugs.

Yukti Singhal
Security Analyst
5 min read

Java urlencode almost always means java.net.URLEncoder.encode, and the single most important fact about it is that it performs application/x-www-form-urlencoded encoding, not general URL encoding. That distinction is the source of most Java urlencode bugs, and some of them are security bugs. This guide explains what URLEncoder does, where it is correct, where it silently produces wrong output, and how proper encoding blocks a class of injection attacks.

What Java urlencode does

The classic way to urlencode a Java string:

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

String encoded = URLEncoder.encode(value, StandardCharsets.UTF_8);

URLEncoder converts characters that are unsafe in a form body into percent-encoded sequences, and it encodes spaces as +. That last detail is the trap. In an actual URL path or query, a space should be %20, and a literal + in a query value is often interpreted as a space by the receiver. So when you urlencode a Java string with URLEncoder and drop it into a path segment, you can get subtly wrong values.

Always pass the charset. The no-charset overload was deprecated because it relied on the platform default, which is not portable across systems.

Where URLEncoder is correct and where it is not

Use URLEncoder when you are building a form body or a query-string value:

String query = "q=" + URLEncoder.encode(searchTerm, StandardCharsets.UTF_8)
             + "&page=" + URLEncoder.encode(page, StandardCharsets.UTF_8);

That is the right tool for the job: each value is form-encoded, and + for space is exactly what a form-decoding server expects.

Do not use URLEncoder to encode a whole URL, or a path segment where + matters. For those, prefer a URI builder that applies the correct rules per component. Spring's UriComponentsBuilder, the JAX-RS UriBuilder, or java.net.URI's multi-argument constructor encode each part (path, query, fragment) according to that part's grammar:

import org.springframework.web.util.UriComponentsBuilder;

String url = UriComponentsBuilder
    .fromUriString("https://api.example.com/search")
    .queryParam("q", searchTerm)   // component-aware encoding
    .build()
    .toUriString();

The rule of thumb: urlencode in Java with URLEncoder for form values, and a URI builder for anything that assembles a full URL.

The security angle: encoding stops injection

Encoding is not just correctness, it is a defense. When you concatenate raw user input into a URL and then use that URL to make an outbound request, unencoded input can break out of the value it was supposed to occupy. That is the shape of several attack classes.

Parameter injection. If a user-supplied value lands unencoded in a query string, an attacker can inject &admin=true and add parameters you never intended:

// Vulnerable: raw input concatenated into the query
String url = "https://api.internal/user?id=" + userInput;
// userInput = "42&role=admin" now smuggles an extra parameter

Encoding the value with URLEncoder.encode turns the & into %26, so it stays a single opaque value instead of a new parameter.

Server-side request forgery (SSRF) amplification. When user input becomes part of a URL your server fetches, faulty encoding can be one link in an SSRF chain. Correct encoding is not a complete SSRF defense on its own, but failing to encode makes the input far easier to weaponize. Pair encoding with host allowlisting for outbound requests.

Log and header injection. A raw newline or control character carried into a URL that later gets logged or placed in a header can forge log lines or split responses. Encoding neutralizes the control characters.

Encode at the boundary, decode once

A reliable model: values are stored and processed in their raw form, encoded exactly once when they cross into a URL, and decoded exactly once when they are read back out. Double-encoding (%2520 instead of %20) and double-decoding are both common bugs, and double-decoding is dangerous because it can resurrect a payload that looked safe after the first decode. If you find yourself calling URLEncoder.encode on something that is already encoded, stop and fix the data flow instead.

Watch for it in dependencies too

Your own code is not the only place URL encoding goes wrong. HTTP client libraries, URL parsers, and routing frameworks have all shipped encoding and normalization bugs over the years, some of which enabled request smuggling or path traversal. Keeping those libraries current matters as much as encoding your own values correctly, and an SCA tool can surface a known encoding or parsing CVE in a transitive HTTP dependency before it reaches production. For the fundamentals of input handling, the Safeguard Academy has a walkthrough of injection defenses.

Quick reference

  • Use URLEncoder.encode(value, StandardCharsets.UTF_8) for form bodies and query values.
  • Remember it encodes space as +, not %20 — do not use it for path segments.
  • Use a URI builder (UriComponentsBuilder, UriBuilder, URI multi-arg constructor) to assemble whole URLs.
  • Encode once at the boundary, decode once on read, never double either way.

FAQ

What does java urlencode actually encode?

URLEncoder.encode performs application/x-www-form-urlencoded encoding: it percent-encodes unsafe characters and encodes spaces as +. It is designed for form bodies and query values, not for encoding a complete URL or a path segment.

Why does URLEncoder turn spaces into plus signs?

Because it implements form encoding, where + means space. In an actual URL path a space should be %20. This mismatch is the most common java urlencode bug, so use a URI builder for path components.

Does urlencode in Java prevent injection attacks?

Correct encoding neutralizes characters like &, newlines, and control characters that attackers use for parameter injection, log injection, and as SSRF building blocks. It is a necessary defense but should be paired with allowlisting for outbound requests.

Which class should I use to build a full URL in Java?

Use a component-aware builder such as Spring's UriComponentsBuilder, JAX-RS UriBuilder, or the multi-argument java.net.URI constructor. These encode each URL part by its own rules, unlike URLEncoder.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.