On Android, Base64 decoding is built directly into the platform: android.util.Base64 has shipped since API level 8, and the modern java.util.Base64.Decoder arrived with API level 26. Whether you are a developer writing Kotlin or Java code, or simply someone who received a Base64 string in a chat message and wants to read it on their phone, the decoding logic is identical — Base64 turns groups of three raw bytes (24 bits) into four characters drawn from the 64-character alphabet (A–Z, a–z, 0–9, +, /), padding with '=' when the input is short. The catch on Android is the same as everywhere else: the alphabet works on bytes, but real text contains multi-byte Unicode characters, so the tool you choose must respect UTF-8 rather than Latin-1. This guide walks through the three practical ways to decode Base64 on an Android device — through the platform API in your own app, through a terminal emulator, and through a UTF-8 aware browser tool — so you can pick the right one for your situation.

Real Reasons You Need to Decode Base64 on Android
Android developers and everyday phone users hit Base64 in surprisingly similar places. A few of the most common scenarios that send people searching for "base64 decode on Android":
- API tokens and Basic HTTP auth. JSON Web Tokens and Authorization: Basic <credentials> headers encode payloads in Base64 so they can travel inside JSON or HTTP without escaping. A mobile app log or a screenshot from a support chat often contains one of these strings that you need to inspect.
- Data URIs in mobile web pages. Email templates, exported HTML and CSS files embed tiny images and web fonts as data:image/png;base64,... blocks. Pulling the original bytes out of a captured data URI is the first step before re-saving the asset.
- Push notifications and Firebase payloads. Server-side messages sometimes wrap JSON payloads in Base64 to survive older transports; decoding on-device is how you check what was actually delivered.
- QR codes and copy-paste in messengers. A QR scanner or a forwarded WhatsApp or Telegram message may hand you a long string that is supposed to be a decoded JSON config, license key, or short URL.
- Local debugging. When a Kotlin or Java string in your app contains binary data, dumping it as Base64 is the easiest way to inspect it without breaking the log output.
The thread running through all of these is that Base64 itself never disappears — it just shows up in different containers. Decoding on Android is the practical skill that lets you read what the string actually means.
Three Ways to Get the Job Done on an Android Device
You have three reasonable paths to decode a Base64 string on Android. They differ in setup effort, Unicode handling, and whether they need a working internet connection.
| Method | Setup | Unicode handling | Network |
|---|---|---|---|
| android.util.Base64 / java.util.Base64.Decoder in your own code | Write a few lines of Kotlin or Java | UTF-8 if you specify Charsets.UTF_8 | Fully offline |
| Terminal emulator (Termux, Material Terminal) with the base64 -d command | Install a terminal app from the Play Store | Depends on the system locale and how the input was captured | Fully offline |
| UTF-8 aware browser tool such as Base64 Encode / Decode | Open a URL in Chrome, Firefox or Samsung Internet | UTF-8 by design, with strict decoder on the way back | Loads the page once; the conversion itself never uploads data |
Writing code gives you the cleanest integration because Base64 support is part of the standard library that ships with the Android SDK. android.util.Base64 has been available since API level 8, and Java 8 desugaring or direct API 26+ access exposes java.util.Base64.Decoder with the same behavior plus flags for URL-safe and MIME variants. Both classes throw on malformed input, which is what you want during testing.
A terminal emulator such as Termux or Material Terminal gives you a UNIX-style workflow. The base64 command on Android is the same GNU coreutils binary you would use on Linux, so muscle memory carries over. It works entirely offline, but its UTF-8 handling depends on the system locale and on whether the input came from clipboard or a file, which can surprise you with accented characters.
A UTF-8 aware browser tool sits between the two: nothing to install, nothing uploaded, and Unicode is handled correctly by design. The Base64 Encode / Decode tool runs the conversion locally in your browser using the standard TextEncoder and a strict UTF-8 decoder, so café, 你好, and 😀 all round-trip cleanly. It is the most practical choice when you are not the developer of the app that produced the string.
Decoding Base64 in Android Code
Both Android-specific and Java-standard classes are available, and the choice depends on your minimum SDK level. android.util.Base64 is the original Android API and still ships with every device running the platform. The byte-array overload is the one you reach for in Kotlin and Java:
// Kotlin import android.util.Base64 val encoded = "SGVsbG8sIFdvcmxkIQ==" val bytes = Base64.decode(encoded, Base64.DEFAULT) val text = String(bytes, Charsets.UTF_8)The second argument is a flag bitmask. DEFAULT is the standard RFC 4648 alphabet with padding. NO_WRAP omits line terminators (added in API 8), and URL_SAFE swaps + and / for - and _ when you are decoding tokens that came from a URL-safe encoder. Pass NO_PADDING if the string is missing its trailing = signs; with DEFAULT and the decoder throws IllegalArgumentException, which is usually what you want during development.
For modern code targeting API 26 or above, the JDK class is cleaner and matches the API you may already know from server-side Java:
// Java import java.util.Base64; import java.nio.charset.StandardCharsets; String encoded = "SGVsbG8sIFdvcmxkIQ=="; byte[] bytes = Base64.getDecoder().decode(encoded); String text = new String(bytes, StandardCharsets.UTF_8);java.util.Base64 separates the URL-safe alphabet into getUrlDecoder() and the standard alphabet into getDecoder(). It also exposes getMimeDecoder() for Base64 with line breaks, which is what you see in email attachments.
Either way, the trap to avoid is passing a String directly into anything that internally calls the browser-style btoa. That function only accepts code points 0–255, so it throws on accented characters. The Android utility classes operate on a byte[] and leave UTF-8 encoding to you, which is the correct boundary — but you must specify Charsets.UTF_8 when you convert back to a String, otherwise the JVM default encoding takes over and silently mis-decodes anything outside ASCII.
How to Decode Base64 on Your Android Phone with a Browser Tool
When you do not want to write code, you can decode a Base64 string directly on the phone's browser. Open the Base64 Encode / Decode page in Chrome, Firefox or Samsung Internet, then follow these steps:
- Choose the Decode direction. The tool exposes Encode and Decode as two clear buttons at the top; tap Decode so the input becomes the Base64 string.
- Paste the Base64 string into the input box. The decoded text appears in the output box as you type, so you can paste from the clipboard in a single motion without pressing any extra button.
- Copy the result. Long-press the output and copy it, or use the Copy button next to the field to grab the exact result. If the input is malformed, the decoder shows an explicit error instead of producing silent garbage.
- Re-encode if you need to. Tap Swap direction — the decoded text moves into the input box and the encoder runs immediately, ready to copy again.
Because the conversion happens with the browser's TextEncoder and a strict UTF-8 decoder, the same workflow handles emoji, CJK characters and accented Latin letters without throwing. Nothing is uploaded, so tokens, session cookies and private payloads can be inspected safely.
Why UTF-8 Trips Up Most Android Decoders
Most "Base64 failed" reports on Android are not really about Base64 — they are about character encoding. Base64 itself is a reversible byte-to-text mapping that follows RFC 4648. The spec groups three input bytes (24 bits) into four 6-bit values and looks each one up in the 64-character alphabet. When the input is not a multiple of three bytes, the output is padded with one or two '=' signs so its length stays a multiple of four.
A worked example with the string foo makes the math concrete. The three ASCII bytes are 0x66 0x6F 0x6F, which in binary are 01100110 01101111 01101111. Concatenated into a 24-bit stream and split into four 6-bit groups you have 011001, 100110, 111101, 101111. Those decimal values are 25, 38, 61 and 47, which map to Z, m, 9 and v. So foo becomes Zm9v — no padding because the input was exactly three bytes. The single-byte string f is padded with four zero bits to make 12 bits and becomes Zg==, with two '=' signs because the input was one byte instead of three.
The trouble starts when the bytes come from real Unicode text instead of ASCII. The Android utility classes accept a byte[] and never look at the String, so you are responsible for giving them UTF-8 bytes (or whatever encoding your wire format specifies). The browser's built-in btoa function, in contrast, only accepts characters whose code points are 0–255 and throws on anything higher, including the common case of accented Latin letters. That is why a hand-rolled decoder inside a web view or a React Native app can fail on a perfectly normal message. The Base64 Encode / Decode tool avoids the trap by calling TextEncoder before Base64 and a strict fatal UTF-8 decoder on the way back, so invalid input is rejected explicitly rather than being silently corrupted into garbage characters. For a deeper look at how a UTF-8 aware converter differs from the broken btoa shortcut, see the UTF-8, accents, and emoji converter guide. If you want to read the exact alphabet and padding rules yourself, the canonical reference is RFC 4648.
Picking the Right Approach on Android
Inside your own app, the right answer is almost always java.util.Base64.Decoder on API 26 or higher, or android.util.Base64 on older minSdks — both wrapped with Charsets.UTF_8 so Unicode round-trips correctly. For one-off debugging on the phone, a terminal emulator running base64 -d is fast, offline and matches the Linux muscle memory most developers already have. For arbitrary text from chats, emails, screenshots and web pages, a UTF-8 aware browser tool is the lowest-friction option: no install, no upload, and malformed input produces an explicit error instead of silent garbage. Whatever path you take, keep in mind that Base64 is an encoding, not encryption — anyone holding the string can reverse it, so it should never be used to hide API secrets, passwords or session tokens.
Related reading: Convert File to Base64 in Java with java.util.Base64.