Base64 Encode & Decode in Kotlin
Encode or decode below — it runs locally in your browser — then grab the canonical Kotlin code. On Kotlin 1.8+ the multiplatform stdlib kotlin.io.encoding.Base64 works with ByteArray, so you encodeToByteArray() a string before encoding and decodeToString() the result after. On JVM/Android you can also use java.util.Base64.
Encode and decode a string
On Kotlin 1.8+, the stdlib kotlin.io.encoding.Base64 is the idiomatic, multiplatform choice. It operates on ByteArray, so encode the string to bytes first:
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
@OptIn(ExperimentalEncodingApi::class)
fun main() {
// Encode
val encoded = Base64.Default.encode("Hello, world!".encodeToByteArray())
println(encoded) // SGVsbG8sIHdvcmxkIQ==
// Decode
val decoded = Base64.Default.decode("SGVsbG8sIHdvcmxkIQ==").decodeToString()
println(decoded) // Hello, world!
}
On the JVM and Android (API 26+) you can use java.util.Base64 instead, which needs no opt-in:
import java.util.Base64
// Encode
val encoded = Base64.getEncoder()
.encodeToString("Hello, world!".toByteArray(Charsets.UTF_8))
println(encoded) // SGVsbG8sIHdvcmxkIQ==
// Decode
val decoded = Base64.getDecoder()
.decode(encoded)
.toString(Charsets.UTF_8)
println(decoded) // Hello, world!
Tip: On Android before API 26, java.util.Base64 isn't available — use android.util.Base64 and pass the NO_WRAP flag, or it inserts a newline every 76 characters.
URL-safe Base64
For JWTs, URLs, and filenames, use the URL-safe alphabet (- and _ instead of + and /). The stdlib exposes a Base64.UrlSafe instance; the JVM has Base64.getUrlEncoder():
// Kotlin stdlib (1.8+)
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
@OptIn(ExperimentalEncodingApi::class)
val urlEncoded = Base64.UrlSafe.encode("user:secret".encodeToByteArray())
// JVM / Android (API 26+), padding stripped (JWT-style)
import java.util.Base64
val token = Base64.getUrlEncoder().withoutPadding()
.encodeToString("user:secret".toByteArray(Charsets.UTF_8))
println(token) // no +, /, or = characters
Android note
On older Android (API < 26), use android.util.Base64. Always pass NO_WRAP so the output is a single line:
import android.util.Base64 as AndroidBase64
val encoded = AndroidBase64.encodeToString(
"Hello".toByteArray(Charsets.UTF_8),
AndroidBase64.NO_WRAP // no newlines
)
By default android.util.Base64 uses DEFAULT flags, which wrap the output with a newline every 76 characters. NO_WRAP avoids those line breaks — essential when the Base64 string goes into JSON, a URL, or an HTTP header.
Frequently asked questions
How do I Base64 encode a string in Kotlin?
On Kotlin 1.8+, encode the string to bytes then Base64-encode: Base64.Default.encode("Hello".encodeToByteArray()) returns "SGVsbG8=" (opt in with @OptIn(ExperimentalEncodingApi::class)).
How do I Base64 decode in Kotlin?
Base64.Default.decode("SGVsbG8=") returns a ByteArray; add .decodeToString() for a string.
How do I do URL-safe Base64?
Use the stdlib Base64.UrlSafe instance, or on the JVM Base64.getUrlEncoder() — both use the - and _ alphabet.
Which Base64 API should I use on Android?
On API 26+ use java.util.Base64 or the Kotlin stdlib. For older devices use android.util.Base64 with the NO_WRAP flag.
Need image, file, or URL-safe modes?
The main base64.dev tool handles text, images, files, and URL-safe Base64 with auto-detect.
Open base64.dev →