How to Base64 encode/decode (without breaking Unicode)
Practical Base64 snippets for UTF-8 text. Includes notes to avoid common bytes vs strings mistakes.
Use this article when...
This section is built for speed: one concrete task, multiple stacks, and the minimum context needed not to copy the wrong thing.
Work from the request or response body that actually failed instead of rebuilding JSON from memory.
The useful path here is fast adaptation: choose your stack, then copy only after reading the notes around parsing and formatting.
Once the snippet runs, inspect the live payload with JSON Formatter or the related tool to confirm the structure is really fixed.
What this article gives you
A short path from incident to implementation: context, language-specific snippets, and the warning signs that usually get skipped.
13
3
base64, encoding, debugging, web
Base64 is not “encryption”: it is a representation to transport bytes as text. It is used in headers, tokens, payloads, and to debug binary data.
The common mistake: treating Base64 as “plain text” without defining UTF-8. Practical rule: string → UTF-8 bytes → Base64, and back.
Dependency snapshot by language
Check this first to see which snippets use built-in/runtime APIs and which ones need external packages before you start copying code.
Review the notes for setup details.
Built-in or runtime API
Review the notes for setup details.
Review the notes for setup details.
Built-in or runtime API
Built-in or runtime API
Review the notes for setup details.
Built-in or runtime API
Built-in or runtime API
Built-in or runtime API
base64 = "0.22".
Built-in or runtime API
Built-in or runtime API
How to use these code examples well
The snippet is only the fast path. The explanation and notes are what keep you from copying the wrong assumption into production.
Make sure the article really matches the issue you are debugging before copying code just because the title looks close.
That is where portability limits, dependency requirements, and runtime assumptions usually appear.
If the code runs but the bug remains, jump to the related tool and inspect the real payload, token, timestamp, or config.
Code examples by language
Snippets that compile/run, plus short explanations and real-world notes.
Bash
echo -n 'Hello world' | base64
echo 'SGVsbG8gd29ybGQ=' | base64 -d
The base64 CLI encodes stdin to Base64 and can decode it back. Useful for quick debugging of small payloads.
- On macOS, decode flag is often -D instead of -d.
- For binary data, redirect to a file (do not print in terminal).
C#
using System;
using System.Text;
var text = "Hola mundo";
var b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(b64));
Console.WriteLine(b64);
Console.WriteLine(decoded);
Converts string → UTF-8 bytes → Base64. To decode, reverse: Base64 → bytes → UTF-8.
- Std.
- If input may be invalid, catch FormatException from FromBase64String.
Delphi
program Base64Utf8;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.NetEncoding;
var
Text: string;
B64: string;
Decoded: string;
begin
Text := "Hola mundo";
B64 := TNetEncoding.Base64.Encode(Text);
Decoded := TNetEncoding.Base64.Decode(B64);
Writeln(B64);
Writeln(Decoded);
end.
TNetEncoding.Base64 can encode/decode strings directly. For binary flows, work with bytes/streams.
- Std: System.NetEncoding.
- For binary data, use overloads that work with bytes/streams.
Go
package main
import (
"encoding/base64"
"fmt"
)
func main() {
text := "Hola mundo"
b64 := base64.StdEncoding.EncodeToString([]byte(text))
raw, err := base64.StdEncoding.DecodeString(b64)
if err != nil {
panic(err)
}
fmt.Println(b64)
fmt.Println(string(raw))
}
EncodeToString and DecodeString cover the common UTF-8 string ↔ Base64 use case.
- Std: encoding/base64.
- If your Base64 is URL-safe, use RawURLEncoding or URLEncoding.
Java
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class Main {
public static void main(String[] args) {
String text = "Hola mundo";
String b64 = Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8));
String decoded = new String(Base64.getDecoder().decode(b64), StandardCharsets.UTF_8);
System.out.println(b64);
System.out.println(decoded);
}
}
java.util.Base64 is standard since Java 8. It is the simplest correct approach for UTF-8 text.
- Std.
- For Base64URL use Base64.getUrlEncoder()/getUrlDecoder().
JavaScript
const text = "Hola mundo";
const b64 = Buffer.from(text, "utf8").toString("base64");
const decoded = Buffer.from(b64, "base64").toString("utf8");
console.log(b64);
console.log(decoded);
In Node.js, Buffer handles UTF-8 and Base64 directly. Great for scripts and JS backends.
- Node.js.
- In browsers, avoid atob/btoa with Unicode unless you use TextEncoder/TextDecoder.
Kotlin
import java.nio.charset.StandardCharsets
import java.util.Base64
fun main() {
val text = "Hola mundo"
val b64 = Base64.getEncoder().encodeToString(text.toByteArray(StandardCharsets.UTF_8))
val decoded = String(Base64.getDecoder().decode(b64), StandardCharsets.UTF_8)
println(b64)
println(decoded)
}
Kotlin/JVM uses the same Java Base64 API to encode/decode UTF-8 bytes.
- Std (JVM).
PHP
<?php
$text = "Hola mundo";
$b64 = base64_encode($text);
$decoded = base64_decode($b64, true);
echo $b64 . PHP_EOL;
echo $decoded . PHP_EOL;
base64_encode/base64_decode work well for UTF-8 text. Use strict=true on decode to catch invalid input.
- Std.
- If input is Base64URL, normalize -_ to +/ and add padding.
Python
import base64
text = "Hola mundo"
b64 = base64.b64encode(text.encode("utf-8")).decode("ascii")
decoded = base64.b64decode(b64).decode("utf-8")
print(b64)
print(decoded)
Convert to UTF-8 bytes before b64encode. For output, decode bytes back to UTF-8.
- Std.
Ruby
require "base64"
text = "Hola mundo"
b64 = Base64.strict_encode64(text)
decoded = Base64.decode64(b64)
puts b64
puts decoded
strict_encode64 avoids newlines in Base64 output, which is typically what you want for tokens/headers.
- Std.
Rust
use base64::{engine::general_purpose::STANDARD, Engine as _};
fn main() {
let text = "Hola mundo";
let b64 = STANDARD.encode(text.as_bytes());
let decoded = String::from_utf8(STANDARD.decode(&b64).unwrap()).unwrap();
println!("{}", b64);
println!("{}", decoded);
}
The base64 crate encodes/decodes bytes. Convert to UTF-8 when the content is text.
- Dependency: base64 = "0.22".
TypeScript
const text = "Hola mundo";
const b64 = Buffer.from(text, "utf8").toString("base64");
const decoded = Buffer.from(b64, "base64").toString("utf8");
console.log(b64);
console.log(decoded);
Same pattern as JS in Node: Buffer handles UTF-8 and Base64 directly.
- Node.js.
VB.NET
Imports System
Imports System.Text
Module Program
Sub Main()
Dim text = "Hola mundo"
Dim b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(text))
Dim decoded = Encoding.UTF8.GetString(Convert.FromBase64String(b64))
Console.WriteLine(b64)
Console.WriteLine(decoded)
End Sub
End Module
In .NET, the correct pattern is always string ↔ UTF-8 bytes ↔ Base64.
- Std.
Related tools
Use the tool when you need to generate or validate output fast.
Trust and privacy
Copy/paste-friendly by design. Still, treat real production secrets carefully.
- Prefer synthetic examples when sharing screens or recording.
- Do not paste real API keys, tokens, or personal data unless you fully trust your environment.
- If you need ordering, do not use UUID v4 as a sortable id: add createdAt or use sortable ids.