Base64 Encoding in Java β java.util.Base64 Examples
Use the free online Base64 Encode Online directly in your browser β no install required.
Try Base64 Encode Online Online βEvery time I wire up an HTTP Basic Auth header, embed a certificate in a Kubernetes secret, or push binary data through a JSON API, the first step is the same: base64 encode the raw bytes into an ASCII-safe string. Java makes this straightforward with java.util.Base64, the standard API available since Java 8 that replaced the deprecated sun.misc.BASE64Encoder. For a quick one-off encoding without writing any code, ToolDeck's Base64 Encoder handles it instantly in the browser. This guide covers Base64.getEncoder(), getUrlEncoder(), getMimeEncoder(), file encoding, streaming with wrap(OutputStream), and the mistakes that trip up even experienced Java developers. All examples compile on Java 8 through Java 21+.
- βBase64.getEncoder().encodeToString(bytes) is the standard one-liner β built into the JDK since Java 8, unchanged through Java 17 and 21.
- βAlways pass StandardCharsets.UTF_8 to String.getBytes() before encoding β omitting it uses the platform default, which varies across JVMs.
- βgetUrlEncoder() produces URL-safe output (- instead of +, _ instead of /) and withoutPadding() strips trailing = characters.
- βgetMimeEncoder() inserts line breaks every 76 characters β required by email (MIME) and PEM certificate formats.
- βFor large files, use Base64.getEncoder().wrap(OutputStream) to stream without loading the entire file into memory.
What is Base64 Encoding?
Base64 converts arbitrary binary data into a string composed of 64 printable ASCII characters: A-Z, a-z, 0-9, +, and /. Every 3 bytes of input produce exactly 4 Base64 characters. If the input length is not a multiple of 3, one or two = padding characters are appended. The encoded output is always roughly 33% larger than the original data.
Base64 is not encryption. Anyone with the encoded string can decode it. Its purpose is transport safety: HTTP headers, JSON payloads, XML documents, and email bodies are text-based protocols that cannot carry raw binary bytes without corruption. Common Java use cases include HTTP Basic Authentication, embedding PEM certificates, storing binary data in database text columns, and constructing JWT token segments.
deploy-svc:sk_live_4eC39HqLyjWDarjtT1zdp7dc
ZGVwbG95LXN2Yzpza19saXZlXzRlQzM5SHFMeWpXRGFyanRUMXpkcDdkYw==
Base64.getEncoder().encodeToString() β The Standard API
java.util.Base64 was introduced in Java 8 as the official replacement for sun.misc.BASE64Encoder. The class provides three static factory methods β each returning a Base64.Encoder nested class instance β covering the three Base64 variants defined in RFC 4648. No third-party library is needed. No Maven dependency. Just import and call.
Minimal Example β Encode a String
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class EncodeDemo {
public static void main(String[] args) {
String credentials = "monitoring-svc:9f2a7c4e-b1d8-4a3f";
byte[] credentialBytes = credentials.getBytes(StandardCharsets.UTF_8);
String encoded = Base64.getEncoder().encodeToString(credentialBytes);
System.out.println(encoded);
// bW9uaXRvcmluZy1zdmM6OWYyYTdjNGUtYjFkOC00YTNm
}
}The key step most Java developers miss on the first pass: a String must be converted to byte[] before encoding. Base64 operates on bytes, not characters. encodeToString() accepts a byte[] and returns the Base64 String directly. If you need the encoded result as bytes instead, use encode(byte[]) β this returns a byte[] of the ASCII-encoded Base64 characters, useful when you're writing directly to an OutputStream or building binary protocol frames.
HTTP Basic Auth β The Most Common Use Case
HTTP Basic Authentication is probably the single most common reason Java developers reach for Base64 encoding. The spec (RFC 7617) requires the credentials string username:password to be Base64-encoded and placed in the Authorization header. I've seen this done wrong more times than I can count β usually by forgetting the colon separator or encoding the components separately.
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class BasicAuthExample {
public static void main(String[] args) throws Exception {
String username = "metrics-exporter";
String apiKey = "sk_live_4eC39HqLyjWDarjtT1zdp7dc";
// username:password β Base64
String credentials = username + ":" + apiKey;
String authHeader = "Basic " + Base64.getEncoder()
.encodeToString(credentials.getBytes(StandardCharsets.UTF_8));
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/v2/metrics"))
.header("Authorization", authHeader)
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode()); // 200
}
}Round-Trip β Encode and Decode
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class RoundTrip {
public static void main(String[] args) {
String original = "X-Correlation-ID: req_8a4f2c91-e7b3-4d56-9012-3f7a8b9c0d1e";
// Encode
String encoded = Base64.getEncoder()
.encodeToString(original.getBytes(StandardCharsets.UTF_8));
System.out.println(encoded);
// WC1Db3JyZWxhdGlvbi1JRDogcmVxXzhhNGYyYzkxLWU3YjMtNGQ1Ni05MDEyLTNmN2E4YjljMGQxZQ==
// Decode
byte[] decodedBytes = Base64.getDecoder().decode(encoded);
String decoded = new String(decodedBytes, StandardCharsets.UTF_8);
System.out.println(original.equals(decoded)); // true
}
}java.util.Base64 API is identical from Java 8 through Java 17 and Java 21. No migration is needed when upgrading your JDK. The same code compiles and runs on any version since Java 8.Encoding Non-String Data β byte[], UUID, and Timestamps
Base64 encoding in Java always starts with a byte[]. Strings convert through getBytes(StandardCharsets.UTF_8), but other types need a conversion step first. UUIDs, timestamps, and numeric identifiers must be serialized to a string or byte representation before you can Base64-encode them.
UUID β Encode as String Representation
import java.util.Base64;
import java.util.UUID;
import java.nio.charset.StandardCharsets;
UUID sessionId = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
String encoded = Base64.getEncoder()
.encodeToString(sessionId.toString().getBytes(StandardCharsets.UTF_8));
System.out.println(encoded);
// NmJhN2I4MTAtOWRhZC0xMWQxLTgwYjQtMDBjMDRmZDQzMGM4Compact UUID β Encode the Raw 16 Bytes
If you want a shorter encoded result, extract the UUID's 128 bits as 16 raw bytes instead of converting to its 36-character string form. The Base64 output drops from 48 characters to 24.
import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.UUID;
UUID eventId = UUID.fromString("550e8400-e29b-41d4-a716-446655440000");
ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
buffer.putLong(eventId.getMostSignificantBits());
buffer.putLong(eventId.getLeastSignificantBits());
String compact = Base64.getUrlEncoder()
.withoutPadding()
.encodeToString(buffer.array());
System.out.println(compact);
// VQ6EAOKbQdSnFkRmVUQAAA
// 22 chars vs 48 for the string-based approachTimestamp and Mixed Payload
import java.time.Instant;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
// Simulating a JWT-style payload
String payload = String.format(
"{"sub":"usr_7b3c","iss":"auth.internal","iat":%d,"exp":%d}",
Instant.now().getEpochSecond(),
Instant.now().plusSeconds(3600).getEpochSecond()
);
String encoded = Base64.getUrlEncoder()
.withoutPadding()
.encodeToString(payload.getBytes(StandardCharsets.UTF_8));
System.out.println(encoded);
// eyJzdWIiOiJ1c3JfN2IzYyIsImlzcyI6ImF1dGguaW50ZXJuYWwiLCJpYXQiOj... (URL-safe, no padding)toString() on a byte[]expecting its contents β that gives you the array's identity hash like [B@6d06d69c. Use new String(bytes, StandardCharsets.UTF_8) or pass the byte array directly to encodeToString().Base64.Encoder Methods Reference
The java.util.Base64 class exposes three factory methods, each returning a Base64.Encoder configured for a specific variant. The encoder instances are thread-safe and stateless β create them once and reuse them.
Base64.getUrlEncoder() β URL-Safe Encoding
The URL-safe encoder uses an alternate alphabet where + becomes - and / becomes _, as defined in RFC 4648 Section 5. This matters whenever the Base64 string appears in a URL query parameter, a filename, or a cookie value β standard Base64 characters conflict with URL delimiters and filesystem reserved characters.
import java.util.Base64; import java.nio.charset.StandardCharsets; String redirectUri = "https://app.internal/callback?state=auth_pending&nonce=9f2a7c"; byte[] data = redirectUri.getBytes(StandardCharsets.UTF_8); // Standard encoder β contains + and / which break URLs String standard = Base64.getEncoder().encodeToString(data); System.out.println(standard); // aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s/c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw== // URL-safe encoder β safe for query parameters and filenames String urlSafe = Base64.getUrlEncoder().encodeToString(data); System.out.println(urlSafe); // aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s_c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw== // URL-safe without padding β for JWTs and compact tokens String noPadding = Base64.getUrlEncoder().withoutPadding().encodeToString(data); System.out.println(noPadding); // aHR0cHM6Ly9hcHAuaW50ZXJuYWwvY2FsbGJhY2s_c3RhdGU9YXV0aF9wZW5kaW5nJm5vbmNlPTlmMmE3Yw
The withoutPadding() variant strips the trailing = characters. JWT specifications require URL-safe Base64 without padding for the header and payload segments, so getUrlEncoder().withoutPadding() is the exact call you want when constructing or manipulating JWT tokens manually.
withoutPadding() method returns a new encoder instance β it does not modify the original. Both can be assigned to static final fields and reused safely across threads.Encode from File and API Response
The two most common real-world scenarios for Base64 encoding in Java: reading a binary file from disk (certificates, images, configuration bundles) and encoding data received from an HTTP response.
Encode a File to Base64
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
public class FileEncoder {
public static void main(String[] args) {
try {
byte[] fileBytes = Files.readAllBytes(Path.of("certs/server.pem"));
String encoded = Base64.getEncoder().encodeToString(fileBytes);
System.out.printf("Original: %d bytes%n", fileBytes.length);
System.out.printf("Encoded: %d chars%n", encoded.length());
// Write encoded content to a text file
Files.writeString(
Path.of("certs/server.pem.b64"),
encoded
);
} catch (java.io.IOException e) {
System.err.println("Failed to read file: " + e.getMessage());
}
}
}Encode an API Response Body
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;
public class ApiEncoder {
public static void main(String[] args) {
try {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/v2/reports/weekly.pdf"))
.header("Authorization", "Bearer tok_8f2a9c3d")
.build();
HttpResponse<byte[]> response = client.send(
request, HttpResponse.BodyHandlers.ofByteArray()
);
if (response.statusCode() == 200) {
String encoded = Base64.getEncoder()
.encodeToString(response.body());
System.out.printf("Encoded %d bytes β %d chars%n",
response.body().length, encoded.length());
} else {
System.err.printf("HTTP %d: %s%n",
response.statusCode(),
new String(response.body()));
}
} catch (Exception e) {
System.err.println("Request failed: " + e.getMessage());
}
}
}Quick note before the CLI section: if you just need to paste a file or API response and get the Base64 output without writing code, the online Base64 Encoder handles both text and binary input.
Command-Line Base64 Encoding
Sometimes you just need to encode a string or file from the terminal β no Java project, no IDE, no build step. Most Unix systems ship with a base64 command, and if you have a JDK installed, you can use jshell for a Java-native approach.
# macOS / Linux β encode a string
echo -n "deploy-bot:sk_prod_9f2a7c4e" | base64
# ZGVwbG95LWJvdDpza19wcm9kXzlmMmE3YzRl
# Encode a file
base64 < certs/server.pem > certs/server.pem.b64
# Using jshell (JDK 9+)
echo 'System.out.println(java.util.Base64.getEncoder().encodeToString("deploy-bot:sk_prod_9f2a7c4e".getBytes()))' | jshell -
# Using java directly with a one-liner
java -e 'System.out.println(java.util.Base64.getEncoder().encodeToString(args[0].getBytes()))' "my-secret"
# Note: java -e requires JDK 23+ (JEP 477)The jshellapproach is particularly useful when you need to verify that your Java code produces the same output as a Unix tool, or when you're debugging a mismatch between what your service sends and what the receiver expects. I keep a shell alias for it.
base64 command uses -D for decoding. On Linux (GNU coreutils) it uses -d. The encoding behavior is identical on both. The -w 0 flag on Linux disables line wrapping in the output, which is usually what you want when piping to other commands.Apache Commons Codec β High-Performance Alternative
For most applications, java.util.Base64 is fast enough. But if you're processing millions of encoding operations in a tight loop β think log ingestion pipelines or high-throughput message brokers β Apache Commons Codec is worth benchmarking. It has been around since long before Java 8 and provides a battle-tested alternative with a slightly different API surface.
// Maven: org.apache.commons:commons-codec:1.17.0
import org.apache.commons.codec.binary.Base64;
import java.nio.charset.StandardCharsets;
byte[] telemetryPayload = ("{"service":"metrics-collector","
+ ""host":"prod-east-07","
+ ""cpu_pct":72.4,"
+ ""mem_mb":3891,"
+ ""timestamp":1710523200}")
.getBytes(StandardCharsets.UTF_8);
// Standard encoding
String encoded = Base64.encodeBase64String(telemetryPayload);
// URL-safe encoding
String urlSafe = Base64.encodeBase64URLSafeString(telemetryPayload);
// Check if a string is valid Base64
boolean valid = Base64.isBase64(encoded);
System.out.println(valid); // trueApache Commons Codec also provides Base64OutputStream and Base64InputStream for streaming scenarios, and includes a validation method that the JDK encoder lacks. If Commons Codec is already in your dependency tree (it ships with many Apache projects), there is no reason not to use it.
Guava BaseEncoding
Google's Guava library includes BaseEncoding which provides a fluent API for Base64 with configurable line separators, padding control, and support for both standard and URL-safe alphabets. Adding Guava (roughly 3 MB) solely for Base64 encoding is overkill. If Guava is already in your project for its collections or caching utilities, the encoding API is a nice bonus.
// Maven: com.google.guava:guava:33.1.0-jre
import com.google.common.io.BaseEncoding;
import java.nio.charset.StandardCharsets;
byte[] webhookPayload = ("{"event":"deployment.completed","
+ ""repo":"payments-api","
+ ""sha":"a7f2c91e4b3d","
+ ""environment":"production"}")
.getBytes(StandardCharsets.UTF_8);
// Standard Base64
String standard = BaseEncoding.base64().encode(webhookPayload);
// URL-safe
String urlSafe = BaseEncoding.base64Url().encode(webhookPayload);
// Without padding
String noPad = BaseEncoding.base64Url().omitPadding().encode(webhookPayload);
// With line separators (PEM-style)
String wrapped = BaseEncoding.base64()
.withSeparator("\n", 64)
.encode(webhookPayload);Base64.getMimeEncoder() β MIME and PEM Line-Wrapped Output
The MIME encoder inserts \r\n line breaks every 76 characters, matching the MIME specification (RFC 2045). PEM certificates, S/MIME email attachments, and some legacy APIs expect this format. The standard and URL-safe encoders produce a single unbroken line β if you pass their output to a system expecting line-wrapped Base64, it may silently fail or reject the data.
import java.util.Base64;
import java.nio.charset.StandardCharsets;
// Simulate a PEM certificate body
byte[] certData = new byte[256]; // In practice, read from a .der file
new java.security.SecureRandom().nextBytes(certData);
// Default MIME encoder β 76 chars per line, \r\n separator
String mimeEncoded = Base64.getMimeEncoder().encodeToString(certData);
System.out.println(mimeEncoded);
// QYx2K3p8Xg7JmN1R+wFkLd... (76 chars)
// Ht5Bv9CzAq0PnSjYl8WxUe... (76 chars)
// ...
// Custom MIME encoder β 64 chars per line (PEM standard), \n separator
Base64.Encoder pemEncoder = Base64.getMimeEncoder(64, new byte[]{'\n'});
String pemBody = pemEncoder.encodeToString(certData);
System.out.println("-----BEGIN CERTIFICATE-----");
System.out.println(pemBody);
System.out.println("-----END CERTIFICATE-----");getMimeEncoder() for JWT tokens, HTTP headers, or URL parameters. The line breaks will corrupt the data in those contexts. Use getEncoder() or getUrlEncoder() instead.Streaming Large Files with Base64.getEncoder().wrap()
Loading an entire file into a byte[] with Files.readAllBytes() works for small files, but for anything over 50-100 MB you risk OutOfMemoryError. The JDK provides Base64.getEncoder().wrap(OutputStream), which returns an OutputStream that encodes data on the fly as you write to it. The encoded bytes flow through to the underlying stream without buffering the entire input.
import java.io.*;
import java.nio.file.*;
import java.util.Base64;
public class StreamingEncoder {
public static void main(String[] args) throws IOException {
Path inputPath = Path.of("backups/database-export.sql.gz");
Path outputPath = Path.of("backups/database-export.sql.gz.b64");
try (
InputStream in = Files.newInputStream(inputPath);
OutputStream fileOut = Files.newOutputStream(outputPath);
OutputStream base64Out = Base64.getEncoder().wrap(fileOut)
) {
byte[] buffer = new byte[8192];
int bytesRead;
long totalBytes = 0;
while ((bytesRead = in.read(buffer)) != -1) {
base64Out.write(buffer, 0, bytesRead);
totalBytes += bytesRead;
}
System.out.printf("Streamed %d bytes through Base64 encoder%n", totalBytes);
}
// Closing base64Out flushes the final padding bytes automatically
}
}The try-with-resources block handles flushing and closing. One detail that catches people: the final Base64 padding is only written when the wrapping OutputStream is closed. If you forget to close it (or close only the outer stream), the last few characters of your encoded output may be missing.
Streaming to a Network Socket
The wrap() method works with any OutputStream β file output, socket output, HTTP response body, even ByteArrayOutputStream. Here is an example writing Base64-encoded data directly into an in-memory buffer, which is useful for unit testing or building payloads that will be sent over HTTP:
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try (OutputStream encoder = Base64.getEncoder().wrap(buffer)) {
// Write data in chunks β simulates reading from a stream
encoder.write("chunk-1:telemetry-data-".getBytes(StandardCharsets.UTF_8));
encoder.write("chunk-2:more-payload-".getBytes(StandardCharsets.UTF_8));
encoder.write("chunk-3:final-segment".getBytes(StandardCharsets.UTF_8));
}
String encoded = buffer.toString(StandardCharsets.UTF_8);
System.out.println(encoded);
// Y2h1bmstMTp0ZWxlbWV0cnktZGF0YS1jaHVuay0yOm1vcmUtcGF5bG9hZC1jaHVuay0zOmZpbmFsLXNlZ21lbnQ=
// Verify round-trip
byte[] decoded = Base64.getDecoder().decode(encoded);
System.out.println(new String(decoded, StandardCharsets.UTF_8));
// chunk-1:telemetry-data-chunk-2:more-payload-chunk-3:final-segmentBufferedInputStream and is a good balance between memory usage and system call overhead. Smaller buffers increase the number of read/write calls; larger buffers waste memory without meaningful throughput improvement.Thread-Safe Encoder Instances β Store and Reuse
The Base64.Encoder returned by the factory methods is immutable and thread-safe. Calling Base64.getEncoder() on every encoding operation creates a new object each time. The JVM will likely optimize this away, but storing the encoder in a static final field makes the intent clear and avoids unnecessary allocations in hot paths.
import java.util.Base64;
import java.nio.charset.StandardCharsets;
public class TokenService {
// Create once, reuse everywhere β thread-safe
private static final Base64.Encoder STANDARD = Base64.getEncoder();
private static final Base64.Encoder URL_SAFE = Base64.getUrlEncoder().withoutPadding();
private static final Base64.Encoder MIME = Base64.getMimeEncoder();
public static String encodeForHeader(String value) {
return STANDARD.encodeToString(value.getBytes(StandardCharsets.UTF_8));
}
public static String encodeForUrl(byte[] data) {
return URL_SAFE.encodeToString(data);
}
public static String encodeForEmail(byte[] attachment) {
return MIME.encodeToString(attachment);
}
}The withoutPadding() call returns a new encoder instance, so you can store both padded and unpadded variants as separate fields. Each call to encodeToString() or encode() is stateless β no synchronization needed, no shared mutable state.
Common Mistakes
Problem: String.getBytes() without a charset argument uses the platform's default encoding, which is windows-1252 on Windows, UTF-8 on most Linux systems, and varies on macOS. The same code produces different Base64 output on different machines.
Fix: Always pass StandardCharsets.UTF_8 explicitly.
String text = "ΠΠ»ΡΡ Π΄ΠΎΡΡΡΠΏΠ°: prod-east"; byte[] bytes = text.getBytes(); // platform default β unpredictable String encoded = Base64.getEncoder().encodeToString(bytes);
String text = "ΠΠ»ΡΡ Π΄ΠΎΡΡΡΠΏΠ°: prod-east"; byte[] bytes = text.getBytes(StandardCharsets.UTF_8); String encoded = Base64.getEncoder().encodeToString(bytes);
Problem: Base64.getEncoder() outputs + and / characters. When placed in a URL query string, + is interpreted as a space and / as a path separator, silently corrupting the value on the receiving end.
Fix: Use Base64.getUrlEncoder() for any value that will appear in a URL.
// Token in URL query parameter β will break
String token = Base64.getEncoder()
.encodeToString(sessionData);
String url = "https://auth.internal/verify?token=" + token;// URL-safe encoding β no + or / characters
String token = Base64.getUrlEncoder()
.withoutPadding()
.encodeToString(sessionData);
String url = "https://auth.internal/verify?token=" + token;Problem: Encoding with getUrlEncoder() and decoding with getDecoder() (or vice versa) throws IllegalArgumentException because - and _ are not valid in the standard Base64 alphabet, and + and / are not valid in the URL-safe alphabet.
Fix: Always decode with the matching decoder: getUrlDecoder() for URL-safe, getDecoder() for standard.
String encoded = Base64.getUrlEncoder()
.encodeToString(data);
// Later...
byte[] decoded = Base64.getDecoder() // WRONG decoder
.decode(encoded);
// IllegalArgumentException if encoded contains - or _String encoded = Base64.getUrlEncoder()
.encodeToString(data);
// Later...
byte[] decoded = Base64.getUrlDecoder() // matching decoder
.decode(encoded);Problem: The streaming encoder buffers up to 2 input bytes waiting for a complete 3-byte group. If you don't close the wrapping OutputStream, the final 1-4 Base64 characters (including padding) are never written.
Fix: Use try-with-resources, or call close() explicitly on the wrapped stream before reading the output.
ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream b64os = Base64.getEncoder().wrap(baos); b64os.write(data); // baos.toString() is INCOMPLETE β missing final bytes
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (OutputStream b64os = Base64.getEncoder().wrap(baos)) {
b64os.write(data);
} // close() flushes final padding
String encoded = baos.toString(); // completeBase64 Encoding Methods β Comparison
For most projects: java.util.Base64 is the right choice. Zero dependencies, built into the JDK, thread-safe, and covers all three RFC 4648 variants. Reach for Apache Commons Codec only if it's already in your classpath and you need the isBase64() validation method or the streaming Base64OutputStream. Guava's BaseEncoding is a reasonable option if your project already depends on Guava, but adding a 3 MB dependency just for Base64 is hard to justify.
Three scenarios, three picks: standard web service that needs Basic Auth or JWT encoding? Stick with the JDK. Legacy project already pulling in Commons Codec through Spring or Apache HTTP Client? Use it β no reason to have two Base64 libraries on the classpath. Project using Guava for caching and collections? Use BaseEncoding for its clean fluent API. Never add a library just for Base64 encoding β the JDK version has been good enough since 2014.
If you need to quickly verify an encoded result without running your Java code, paste it into the Base64 Encoder to confirm the output matches what your code produces.
Frequently Asked Questions
How do I base64 encode a String in Java?
Convert the string to bytes first using getBytes(StandardCharsets.UTF_8), then pass the byte array to Base64.getEncoder().encodeToString(). Always specify UTF-8 explicitly β calling getBytes() with no charset argument uses the platform default, which varies between operating systems and JVM configurations.
import java.util.Base64;
import java.nio.charset.StandardCharsets;
String payload = "grant_type=client_credentials&scope=read:metrics";
String encoded = Base64.getEncoder()
.encodeToString(payload.getBytes(StandardCharsets.UTF_8));
// Z3JhbnRfdHlwZT1jbGllbnRfY3JlZGVudGlhbHMmc2NvcGU9cmVhZDptZXRyaWNzWhat is the difference between Base64.getEncoder() and Base64.getUrlEncoder()?
Both encode to Base64, but getUrlEncoder() uses the URL-safe alphabet defined in RFC 4648 Section 5. It replaces + with - and / with _ so the output can appear in URLs and filenames without percent-encoding. The standard encoder uses + and / which conflict with URL query parameters and path segments.
byte[] data = "subject=usr_7b3c&role=admin".getBytes(StandardCharsets.UTF_8); String standard = Base64.getEncoder().encodeToString(data); // c3ViamVjdD11c3JfN2IzYyZyb2xlPWFkbWlu String urlSafe = Base64.getUrlEncoder().encodeToString(data); // c3ViamVjdD11c3JfN2IzYyZyb2xlPWFkbWlu // (same here, but with + β - and / β _ when those chars appear)
Is java.util.Base64 the same in Java 8 and Java 17?
Yes. The java.util.Base64 API has not changed since it was introduced in Java 8. The class, its nested Encoder and Decoder classes, and all factory methods (getEncoder, getUrlEncoder, getMimeEncoder) are identical across Java 8, 11, 17, and 21. No migration or code changes are needed when upgrading your JDK version.
// This code compiles and runs identically on Java 8 through Java 21+
import java.util.Base64;
import java.nio.charset.StandardCharsets;
String encoded = Base64.getEncoder()
.encodeToString("stable-api".getBytes(StandardCharsets.UTF_8));
System.out.println(encoded); // c3RhYmxlLWFwaQ==How do I encode a file to Base64 in Java?
Read the file into a byte array with Files.readAllBytes(Path) and pass it to Base64.getEncoder().encodeToString(). For large files that should not be loaded entirely into memory, use Base64.getEncoder().wrap(OutputStream) to stream the encoded output.
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
byte[] fileBytes = Files.readAllBytes(Path.of("config/tls-cert.pem"));
String encoded = Base64.getEncoder().encodeToString(fileBytes);Why was sun.misc.BASE64Encoder deprecated?
sun.misc.BASE64Encoder was an internal JDK class that was never part of the public API. It lived in the sun.misc package, which Oracle explicitly warned against using. Java 8 introduced java.util.Base64 as the official, public, supported replacement. Since Java 9 and the module system, accessing sun.misc classes produces warnings or errors depending on JDK configuration.
// Old way β do NOT use, removed in modern JDKs // import sun.misc.BASE64Encoder; // String encoded = new BASE64Encoder().encode(data); // Correct way since Java 8 import java.util.Base64; String encoded = Base64.getEncoder().encodeToString(data);
How do I do a round-trip Base64 encode and decode in Java?
Encode with Base64.getEncoder().encodeToString(bytes) and decode with Base64.getDecoder().decode(encodedString). Convert the decoded byte array back to a String using new String(bytes, StandardCharsets.UTF_8). The round-trip preserves the original data exactly β as long as you use the same charset for both getBytes() and new String().
import java.util.Base64; import java.nio.charset.StandardCharsets; // Encode String original = "session_token=eyJhbGciOiJSUzI1NiJ9"; byte[] originalBytes = original.getBytes(StandardCharsets.UTF_8); String encoded = Base64.getEncoder().encodeToString(originalBytes); // Decode byte[] decodedBytes = Base64.getDecoder().decode(encoded); String decoded = new String(decodedBytes, StandardCharsets.UTF_8); System.out.println(original.equals(decoded)); // true
Related Tools
- Base64 Decoder β Decode Base64 strings back to their original text or binary form β the reverse operation of encoding.
- URL Encoder β Percent-encode strings for safe use in URLs β different from Base64 URL-safe encoding, but often used alongside it.
- JWT Decoder β Inspect JWT tokens whose header and payload segments are Base64url-encoded JSON β decode them without a library.
- JSON Formatter β Pretty-print JSON payloads before or after Base64 encoding β useful when debugging API integrations.
Aisha is a Java engineer specialising in application security, Spring Security, and API design. She has worked on identity and access management systems, OAuth 2.0 integrations, and microservice security at scale. She writes about secure Java coding practices, token validation, cryptographic utilities, and the Spring ecosystem from a security-first perspective.
Pavel is a backend engineer with deep roots in the JVM ecosystem, working primarily with Java and Kotlin. He has extensive experience building data-intensive services and integrating third-party APIs at scale. He writes about modern Java features, the Jackson ecosystem, serialisation patterns, and practical approaches to keeping large codebases maintainable.