Android Base64 NO_WRAP
Android's Base64.encodeToString(bytes, Base64.DEFAULT) inserts a newline every 76 characters, which breaks JSON bodies, HTTP headers, and URLs. Use Base64.NO_WRAP instead. For decoding, use matching flags (NO_WRAP, plus URL_SAFE for -/_). The tool below shows the difference.
Why does Android Base64 add newlines?
The flag you pass to android.util.Base64 controls formatting, and the most common one — Base64.DEFAULT — follows the old MIME convention. That means it inserts a line break (\n) after every 76 characters of output, plus a trailing newline at the end. Inside an email that's fine, but it silently corrupts a Base64 value the moment you drop it into a JSON string, an HTTP header, or a URL query parameter — the embedded newlines are illegal or get stripped, and the far end fails to decode. Toggle the demo above between DEFAULT (wrapped) and NO_WRAP with a long input to see the line breaks appear and disappear.
Use Base64.NO_WRAP
Pass Base64.NO_WRAP instead of Base64.DEFAULT and the output is one continuous line with no breaks:
// Kotlin
import android.util.Base64
val bytes = "Hello".toByteArray(Charsets.UTF_8)
val encoded = Base64.encodeToString(bytes, Base64.NO_WRAP) // one line, no \n
// Combine flags with bitwise OR when you also need URL-safe / no padding:
val token = Base64.encodeToString(bytes, Base64.NO_WRAP or Base64.URL_SAFE)
// Java
import android.util.Base64;
byte[] bytes = "Hello".getBytes(StandardCharsets.UTF_8);
String encoded = Base64.encodeToString(bytes, Base64.NO_WRAP); // single line
// Multiple flags:
String token = Base64.encodeToString(bytes, Base64.NO_WRAP | Base64.URL_SAFE);
Decoding: match the flags
Decoding must use the same flags the data was encoded with, or you get an IllegalArgumentException: bad base-64. Decode NO_WRAP data with NO_WRAP; add URL_SAFE for tokens that use - and _:
// Kotlin — decode
val bytes = Base64.decode(encoded, Base64.NO_WRAP)
val text = String(bytes, Charsets.UTF_8)
// URL-safe token (contains - or _):
val raw = Base64.decode(token, Base64.NO_WRAP or Base64.URL_SAFE)
// Java — decode
byte[] bytes = Base64.decode(encoded, Base64.NO_WRAP);
String text = new String(bytes, StandardCharsets.UTF_8);
// Wrong flags -> java.lang.IllegalArgumentException: bad base-64
byte[] raw = Base64.decode(token, Base64.NO_WRAP | Base64.URL_SAFE);
Tip: Android's decoder is fairly tolerant of whitespace on input, so decoding still works even if the string was wrapped — the newline problem bites on the encode side, when the wrapped string travels through a transport that can't carry newlines.
android.util.Base64 vs java.util.Base64
There are two Base64 classes on Android and they behave differently by default:
android.util.Base64— available on every API level. ItsDEFAULTflag wraps at 76 characters, so you must passNO_WRAPfor single-line output. Flags are combined with bitwise OR.java.util.Base64— available on API 26+ (Android 8.0). Its basic encoder (Base64.getEncoder()) produces a single line with no wrapping by default, so there's nothing to fix. UsegetUrlEncoder()for URL-safe output andgetMimeEncoder()only if you actually want wrapping.
// java.util.Base64 (API 26+) — no wrapping to worry about
import java.util.Base64;
String encoded = Base64.getEncoder().encodeToString(bytes); // single line
byte[] back = Base64.getDecoder().decode(encoded);
String urlTok = Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
Is this private?
Yes. The encoder/decoder runs fully in your browser with JavaScript — text is encoded and decoded locally and nothing is uploaded to any server. You can confirm in DevTools → Network: encoding fires no request.
Frequently asked questions
Why does Android Base64.encodeToString add newlines?
The default flag, Base64.DEFAULT, follows MIME conventions and inserts a line break (\n) every 76 characters, plus a trailing newline. That wrapping breaks JSON bodies, HTTP headers, and URLs. Use Base64.NO_WRAP to produce a single unbroken line.
What is the difference between Base64.DEFAULT and Base64.NO_WRAP?
Base64.DEFAULT wraps output at 76 characters with newlines; Base64.NO_WRAP produces one continuous line with no line breaks. For transport in JSON, headers, or URLs you almost always want NO_WRAP.
Why do I get IllegalArgumentException when decoding Android Base64?
You're decoding with different flags than you encoded with — for example decoding URL-safe Base64 without Base64.URL_SAFE, or feeding padded input to a NO_PADDING decoder. Match the decode flags to how the string was produced.
Should I use android.util.Base64 or java.util.Base64?
On modern Android (API 26+) java.util.Base64 is available and its basic encoder returns single-line output by default, so there's no 76-character wrapping to fight. android.util.Base64 works on all API levels but defaults to MIME wrapping, so you must pass NO_WRAP.
Need plain Base64 encode/decode?
The main base64.dev tool handles text, files, and URL-safe mode with auto-detect.
Open base64.dev →