DevToolBox免费
博客

Base64 编码/解码器:在线编解码完整指南

8 分钟阅读作者 DevToolBox

TL;DR

Base64 converts 3 bytes into 4 ASCII characters using a 64-character alphabet (A-Z, a-z, 0-9, +/). Use btoa()/atob() in the browser, Buffer.from() in Node.js, and the built-in base64 module in Python. Base64URL swaps + for - and / for _ for URL safety. Base64 is encoding, NOT encryption — anyone can decode it.

What Is Base64?

Base64 is a binary-to-text encoding scheme defined in RFC 4648. It represents arbitrary binary data using only 64 printable ASCII characters, making it safe to transmit through text-based protocols like HTTP, SMTP, and JSON. The name comes directly from the 64-character alphabet it uses.

The algorithm takes 3 bytes (24 bits) of input at a time and splits them into 4 groups of 6 bits. Each 6-bit group (values 0–63) maps to one character in the Base64 alphabet. Since 6 bits can represent 64 distinct values, this perfectly covers the full alphabet.

How 3 Bytes Become 4 Characters

Example: encoding the string "Man":

  • M = 77 = 01001101
  • a = 97 = 01100001
  • n = 110 = 01101110

Concatenated: 010011010110000101101110 → split into 6-bit groups: 010011 (19=T), 010110 (22=W), 000101 (5=F), 101110 (46=u) → result: TWFu

The Base64 Alphabet

The standard alphabet: A–Z (0–25), a–z (26–51), 0–9 (52–61), + (62), / (63). The = character is used as padding when the input is not a multiple of 3 bytes.

  • 1 remaining byte → 2 Base64 chars + ==
  • 2 remaining bytes → 3 Base64 chars + =
  • 3 bytes exactly → 4 Base64 chars, no padding

Base64 vs Base64URL vs Base32 vs Hex

FormatAlphabetURL SafePaddingSize IncreasePrimary Use Case
Base64A-Z, a-z, 0-9, +/No=~33%Email attachments, data URIs, API payloads
Base64URLA-Z, a-z, 0-9, -_YesOptional~33%JWT tokens, URL params, filenames
Base32A-Z, 2-7Yes=~60%TOTP secrets, case-insensitive systems
Hex0-9, a-fYesNone~100%Hashes, colors, binary inspection

JavaScript — Browser (btoa / atob)

Modern browsers provide two global functions for Base64 encoding and decoding:

  • btoa(string) — encodes a binary string to Base64 ("binary to ASCII")
  • atob(base64) — decodes a Base64 string back to binary ("ASCII to binary")

Basic ASCII Encoding

// Encode
const encoded = btoa('Hello, World!');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="

// Decode
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
console.log(decoded); // "Hello, World!"

// Encode binary string (e.g., from fetch response)
const response = await fetch('/api/data');
const arrayBuffer = await response.arrayBuffer();
const bytes = new Uint8Array(arrayBuffer);
const binaryString = bytes.reduce((acc, byte) => acc + String.fromCharCode(byte), '');
const b64 = btoa(binaryString);

Why btoa() Fails on Unicode

btoa() was designed for binary strings where each character has a code point between 0 and 255. Passing characters outside this range (emoji, Chinese characters, etc.) throws a InvalidCharacterError:

// This throws: "InvalidCharacterError: Failed to execute 'btoa'"
btoa('Hello 🌍'); // ERROR!
btoa('中文');     // ERROR!

Fix: Encoding Unicode with encodeURIComponent

// Encode Unicode to Base64
function encodeUnicode(str) {
  return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (_, p1) =>
    String.fromCharCode('0x' + p1)
  ));
}

// Decode Base64 to Unicode
function decodeUnicode(b64) {
  return decodeURIComponent(
    atob(b64).split('').map(c =>
      '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
    ).join('')
  );
}

const encoded = encodeUnicode('Hello 🌍');
console.log(encoded);               // "SGVsbG8g8J+MjQ=="
console.log(decodeUnicode(encoded)); // "Hello 🌍"

Modern Approach: TextEncoder for Binary Data

// Encode any string using TextEncoder (handles all Unicode)
function toBase64(str) {
  const bytes = new TextEncoder().encode(str);
  const binString = String.fromCodePoint(...bytes);
  return btoa(binString);
}

// Decode Base64 back to string using TextDecoder
function fromBase64(b64) {
  const binString = atob(b64);
  const bytes = Uint8Array.from(binString, m => m.codePointAt(0));
  return new TextDecoder().decode(bytes);
}

console.log(toBase64('Hello 🌍'));  // Properly encoded
console.log(fromBase64(toBase64('Hello 🌍'))); // "Hello 🌍"

JavaScript — Node.js (Buffer)

Node.js uses the Buffer class for Base64 operations. This works for both text and binary data without any Unicode workarounds.

String Encoding and Decoding

// Encode string to Base64
const encoded = Buffer.from('Hello, World!').toString('base64');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="

// Decode Base64 to string
const decoded = Buffer.from('SGVsbG8sIFdvcmxkIQ==', 'base64').toString('utf8');
console.log(decoded); // "Hello, World!"

// Unicode strings work natively
const unicodeEncoded = Buffer.from('Hello 🌍').toString('base64');
const unicodeDecoded = Buffer.from(unicodeEncoded, 'base64').toString('utf8');
console.log(unicodeDecoded); // "Hello 🌍"

URL-Safe Base64 (base64url)

// Node.js 16+ natively supports 'base64url'
const urlSafe = Buffer.from('Hello+World/Test==').toString('base64url');
console.log(urlSafe); // No +, /, or = characters

// Decode base64url
const original = Buffer.from(urlSafe, 'base64url').toString('utf8');

// Manual conversion for older Node.js versions
function toBase64url(b64) {
  return b64.replace(/+/g, '-').replace(///g, '_').replace(/=/g, '');
}

function fromBase64url(b64url) {
  const pad = b64url.length % 4;
  const padded = b64url + (pad ? '='.repeat(4 - pad) : '');
  return padded.replace(/-/g, '+').replace(/_/g, '/');
}

File Encoding with fs + Buffer

const fs = require('fs');

// Encode file to Base64
const fileBuffer = fs.readFileSync('./image.png');
const base64String = fileBuffer.toString('base64');
console.log(`data:image/png;base64,${base64String}`);

// Decode Base64 back to file
const base64Data = 'iVBORw0KGgo...'; // your base64 string
const buffer = Buffer.from(base64Data, 'base64');
fs.writeFileSync('./decoded-image.png', buffer);
console.log('File saved successfully');

Base64URL — URL-Safe Encoding

Standard Base64 uses + and / which have special meanings in URLs and filenames. Base64URL (defined in RFC 4648 Section 5) solves this:

  • + is replaced with - (hyphen)
  • / is replaced with _ (underscore)
  • Padding = is usually omitted

When to Use Base64URL

Use CaseWhy Base64URL
JWT tokensToken appears in Authorization headers and URLs without escaping
URL query parameters+ would be interpreted as a space in some parsers
Filenames/ would create directory separators on Unix
Email-safe tokensAvoids characters that email clients might treat specially

Conversion Code

// Standard Base64 → Base64URL
function base64ToBase64url(b64) {
  return b64.replace(/+/g, '-').replace(///g, '_').replace(/=+$/, '');
}

// Base64URL → Standard Base64
function base64urlToBase64(b64url) {
  const padLen = (4 - (b64url.length % 4)) % 4;
  return b64url.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat(padLen);
}

// Examples
const standard = 'SGVsbG8+V29ybGQv';
const urlSafe = base64ToBase64url(standard); // "SGVsbG8-V29ybGQv"
const back = base64urlToBase64(urlSafe);     // "SGVsbG8+V29ybGQv"

Python — base64 Module

Python includes a built-in base64 module that handles standard Base64, URL-safe Base64, Base32, and more. All functions work with bytes objects.

Standard Encoding and Decoding

import base64

# Encode bytes to Base64
data = b"Hello, World!"
encoded = base64.b64encode(data)
print(encoded)         # b'SGVsbG8sIFdvcmxkIQ=='
print(encoded.decode('utf-8'))  # String: "SGVsbG8sIFdvcmxkIQ=="

# Decode Base64 to bytes
decoded = base64.b64decode(b'SGVsbG8sIFdvcmxkIQ==')
print(decoded)          # b'Hello, World!'
print(decoded.decode('utf-8'))  # String: "Hello, World!"

# Encode a string (convert to bytes first)
text = "Hello 🌍"
encoded = base64.b64encode(text.encode('utf-8'))
decoded_text = base64.b64decode(encoded).decode('utf-8')
print(decoded_text)     # "Hello 🌍"

URL-Safe Base64

import base64

# URL-safe encoding (replaces + with - and / with _)
data = b"Hello+World/Test"
url_safe = base64.urlsafe_b64encode(data)
print(url_safe)  # b'SGVsbG8rV29ybGQvVGVzdA=='

# URL-safe decoding
decoded = base64.urlsafe_b64decode(url_safe)
print(decoded)   # b'Hello+World/Test'

# Remove padding for JWT-style encoding
no_pad = url_safe.rstrip(b'=').decode('utf-8')
print(no_pad)    # "SGVsbG8rV29ybGQvVGVzdA"

# Add padding back before decoding
def decode_base64url(b64url):
    padded = b64url + '=' * (4 - len(b64url) % 4)
    return base64.urlsafe_b64decode(padded)

Encoding Files in Python

import base64

# Encode a file to Base64
with open('document.pdf', 'rb') as f:
    file_data = f.read()
    encoded = base64.b64encode(file_data).decode('utf-8')
    print(f"Encoded length: {len(encoded)} chars")

# Decode and save Base64 back to file
with open('output.pdf', 'wb') as f:
    f.write(base64.b64decode(encoded))

# Encode image for data URI
with open('logo.png', 'rb') as img:
    img_data = base64.b64encode(img.read()).decode('utf-8')
    data_uri = f"data:image/png;base64,{img_data}"
    print(data_uri[:100] + '...')

Image to Base64 — Browser File API

Embedding images as Base64 data URIs allows them to be used inline in HTML, CSS, and JavaScript without separate HTTP requests. This is useful for small icons, email templates, and offline-capable apps.

Using FileReader to Convert an Uploaded Image

// HTML: <input type="file" id="imageInput" accept="image/*">
// HTML: <img id="preview" src="" alt="Preview">

document.getElementById('imageInput').addEventListener('change', function(e) {
  const file = e.target.files[0];
  if (!file) return;

  const reader = new FileReader();

  reader.onload = function(event) {
    // event.target.result is "data:image/png;base64,iVBORw0..."
    const dataURL = event.target.result;

    // Display the image
    document.getElementById('preview').src = dataURL;

    // Extract just the Base64 string (without the data URI prefix)
    const base64String = dataURL.split(',')[1];
    console.log('Base64 length:', base64String.length);
    console.log('MIME type:', file.type);

    // Send to server
    fetch('/api/upload', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ image: base64String, mimeType: file.type }),
    });
  };

  reader.readAsDataURL(file); // This triggers encoding
});

Using Canvas for Image Transformation

// Convert image URL to Base64 using Canvas
function imageUrlToBase64(url) {
  return new Promise((resolve, reject) => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img = new Image();
    img.crossOrigin = 'anonymous'; // Required for cross-origin images

    img.onload = () => {
      canvas.width = img.width;
      canvas.height = img.height;
      ctx.drawImage(img, 0, 0);
      resolve(canvas.toDataURL('image/png')); // data:image/png;base64,...
    };
    img.onerror = reject;
    img.src = url;
  });
}

// Usage
const dataUrl = await imageUrlToBase64('https://example.com/logo.png');
document.querySelector('img').src = dataUrl;

Using Inline Base64 Images in HTML and CSS

<!-- Inline in HTML img tag -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEA..." alt="1px dot">

<!-- Inline in CSS background -->
<style>
.icon {
  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL...");
  width: 24px;
  height: 24px;
}
</style>

<!-- SVG can also be used directly without base64 -->
<img src="data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg'><circle cx='5' cy='5' r='5'/></svg>" alt="circle">

When to Use vs When NOT to Use Image Base64

ScenarioUse Base64?Reason
Small icons (<5KB)YesReduces HTTP requests, negligible size penalty
Email template imagesYesExternal images often blocked by email clients
Offline PWA assetsYesAvoids network dependency for critical assets
Large photos (>10KB)No33% larger, no browser caching, slow initial load
Page hero imagesNoBlocks HTML parsing, cannot be cached separately
CDN-served imagesNoCDN caching provides better performance

Go — encoding/base64

Go's standard library includes the encoding/base64 package with support for standard Base64, URL-safe Base64, and raw (no padding) variants.

package main

import (
    "encoding/base64"
    "fmt"
)

func main() {
    input := []byte("Hello, World!")

    // Standard Base64 (with padding)
    encoded := base64.StdEncoding.EncodeToString(input)
    fmt.Println(encoded) // "SGVsbG8sIFdvcmxkIQ=="

    // Decode
    decoded, err := base64.StdEncoding.DecodeString(encoded)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(decoded)) // "Hello, World!"

    // URL-safe Base64 (with padding)
    urlEncoded := base64.URLEncoding.EncodeToString(input)
    fmt.Println(urlEncoded)

    // URL-safe Base64 WITHOUT padding (for JWT)
    rawURLEncoded := base64.RawURLEncoding.EncodeToString(input)
    fmt.Println(rawURLEncoded) // No = at the end

    // Decode raw URL-safe
    rawDecoded, _ := base64.RawURLEncoding.DecodeString(rawURLEncoded)
    fmt.Println(string(rawDecoded))

    // Standard Base64 WITHOUT padding
    rawStdEncoded := base64.RawStdEncoding.EncodeToString(input)
    fmt.Println(rawStdEncoded)
}

Go Base64 Encoding Variants Summary

Go ConstantAlphabetPaddingUse Case
base64.StdEncodingA-Z, a-z, 0-9, +/Yes (=)Standard MIME / file encoding
base64.URLEncodingA-Z, a-z, 0-9, -_Yes (=)URL parameters
base64.RawURLEncodingA-Z, a-z, 0-9, -_NoJWT tokens, compact URLs
base64.RawStdEncodingA-Z, a-z, 0-9, +/NoCompact data transfer

Rust — base64 Crate

Rust uses the base64 crate (not in std library). Add it to your Cargo.toml: base64 = "0.22"

use base64::{Engine as _, engine::general_purpose};

fn main() {
    let input = b"Hello, World!";

    // Standard Base64 encode
    let encoded = general_purpose::STANDARD.encode(input);
    println!("{}", encoded); // "SGVsbG8sIFdvcmxkIQ=="

    // Standard Base64 decode
    let decoded = general_purpose::STANDARD.decode(&encoded).unwrap();
    println!("{}", String::from_utf8(decoded).unwrap()); // "Hello, World!"

    // URL-safe Base64 with padding
    let url_encoded = general_purpose::URL_SAFE.encode(input);
    println!("{}", url_encoded);

    // URL-safe WITHOUT padding (for JWT)
    let jwt_encoded = general_purpose::URL_SAFE_NO_PAD.encode(input);
    println!("{}", jwt_encoded); // No = padding

    // Decode URL-safe without padding
    let jwt_decoded = general_purpose::URL_SAFE_NO_PAD.decode(&jwt_encoded).unwrap();
    println!("{}", String::from_utf8(jwt_decoded).unwrap());
}

// Custom engine example
use base64::engine::general_purpose::GeneralPurpose;
use base64::alphabet;

let custom_engine = GeneralPurpose::new(
    &alphabet::URL_SAFE,
    base64::engine::general_purpose::NO_PAD,
);
let encoded = custom_engine.encode(b"test data");

Base64 in HTTP — Authentication, Data URIs, MIME

HTTP Basic Authentication

HTTP Basic Auth encodes credentials as Base64 in the Authorization header. Note: this is not encryption — the credentials are trivially decodable. Always use HTTPS.

// Format: "username:password" → Base64
const username = 'admin';
const password = 'secret123';
const credentials = btoa(`${username}:${password}`);
// credentials = "YWRtaW46c2VjcmV0MTIz"

// HTTP request with Basic Auth
const response = await fetch('https://api.example.com/data', {
  headers: {
    'Authorization': `Basic ${credentials}`,
    'Content-Type': 'application/json',
  },
});

// Server-side decoding (Node.js)
const authHeader = req.headers.authorization; // "Basic YWRtaW46c2VjcmV0MTIz"
const base64Credentials = authHeader.split(' ')[1];
const [user, pass] = Buffer.from(base64Credentials, 'base64').toString('utf8').split(':');
console.log(user, pass); // "admin" "secret123"

CSS Data URIs

/* Inline SVG as Base64 in CSS */
.icon-home {
  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTEwIDIwdi02aDR2Nmg1di04aDNMMTIgM0wyIDEyaDN2OHoiLz48L3N2Zz4=");
  background-size: contain;
  width: 24px;
  height: 24px;
}

/* Inline PNG as Base64 */
.logo {
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...");
}

/* Font as Base64 for offline use */
@font-face {
  font-family: 'CustomFont';
  src: url("data:font/woff2;base64,d09GMgABAAA...") format('woff2');
}

MIME Email Attachments

// Email attachment using Node.js (nodemailer)
const nodemailer = require('nodemailer');
const fs = require('fs');

const pdfBuffer = fs.readFileSync('report.pdf');
const pdfBase64 = pdfBuffer.toString('base64');

const mailOptions = {
  from: 'sender@example.com',
  to: 'recipient@example.com',
  subject: 'Monthly Report',
  text: 'Please find the report attached.',
  attachments: [
    {
      filename: 'report.pdf',
      content: pdfBase64,
      encoding: 'base64',
      contentType: 'application/pdf',
    },
  ],
};

// Raw MIME format (Content-Transfer-Encoding: base64)
/*
Content-Type: application/pdf; name="report.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="report.pdf"

JVBERi0xLjQKJeLjz9MKNSAwIG9iago8PAovRmlsdGVyIC9GbGF0ZURlY29kZQov...
*/

Streaming and Large File Encoding

Loading large files entirely into memory before encoding is inefficient and may crash for very large files. Use streaming approaches instead.

Critical rule: Chunk sizes for streaming Base64 encoding must be multiples of 3 bytes. Each 3-byte group maps to exactly 4 Base64 characters. Using non-multiples produces incorrect padding characters in intermediate chunks.

Node.js Streams

const fs = require('fs');
const { Transform } = require('stream');

// Custom Base64 encoding stream
class Base64Encoder extends Transform {
  constructor() {
    super();
    this._buffer = Buffer.alloc(0);
  }

  _transform(chunk, encoding, callback) {
    // Combine with leftover bytes
    this._buffer = Buffer.concat([this._buffer, chunk]);

    // Process in multiples of 3
    const safeLength = Math.floor(this._buffer.length / 3) * 3;
    if (safeLength > 0) {
      this.push(this._buffer.slice(0, safeLength).toString('base64'));
      this._buffer = this._buffer.slice(safeLength);
    }
    callback();
  }

  _flush(callback) {
    if (this._buffer.length > 0) {
      this.push(this._buffer.toString('base64'));
    }
    callback();
  }
}

// Usage: stream file through encoder
const readStream = fs.createReadStream('large-video.mp4');
const encoder = new Base64Encoder();
const writeStream = fs.createWriteStream('large-video.b64');

readStream.pipe(encoder).pipe(writeStream);
writeStream.on('finish', () => console.log('Streaming encode complete'));

Python Chunked Encoding

import base64

def encode_file_streaming(input_path, output_path, chunk_size=57):
    """
    Encode a large file using chunked streaming.
    chunk_size must be a multiple of 3 (57 = 3 * 19 → produces 76 char lines, MIME standard).
    """
    with open(input_path, 'rb') as infile, open(output_path, 'w') as outfile:
        while True:
            chunk = infile.read(chunk_size)
            if not chunk:
                break
            # Each 57-byte chunk produces 76 Base64 characters
            encoded_chunk = base64.b64encode(chunk).decode('utf-8')
            outfile.write(encoded_chunk + '\n')  # MIME adds newlines

# base64.encodebytes() automatically adds newlines every 76 chars
with open('large-file.bin', 'rb') as f:
    encoded = base64.encodebytes(f.read())
    print(encoded[:100])  # b'SGVsbG8...'

# Streaming decode
def decode_file_streaming(input_path, output_path):
    with open(input_path, 'r') as infile, open(output_path, 'wb') as outfile:
        for line in infile:
            chunk = base64.b64decode(line.strip())
            outfile.write(chunk)

Performance Comparison

FormatOutput Size IncreaseEncoding SpeedURL SafeBest Use Case
Hex+100% (2x size)Very FastYesHash values, debugging binary data
Base64+33%FastNoEmail attachments, data URIs, API payloads
Base64URL+33%FastYesJWT tokens, URL params, filenames
Base32+60%ModerateYesTOTP secrets, human-readable codes

Base64 vs raw binary: If your protocol supports binary data (e.g., WebSockets, HTTP/2, gRPC), always prefer raw binary over Base64 encoded text. You avoid the 33% overhead and the CPU cost of encoding/decoding.

Browser performance: Native btoa()/atob() are implemented in C++ and are very fast. For data under 1MB, they are typically instantaneous. For larger data, consider a Web Worker to avoid blocking the main thread.

Common Mistakes and How to Fix Them

1. Using btoa() on Unicode Strings

// WRONG — throws InvalidCharacterError
const encoded = btoa("Hello 🌍");  // Error!

// CORRECT — encode URI components first
const encoded = btoa(encodeURIComponent("Hello 🌍")
  .replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode('0x' + p1)));

// OR use TextEncoder (modern approach)
const bytes = new TextEncoder().encode("Hello 🌍");
const encoded = btoa(String.fromCodePoint(...bytes));

2. Forgetting Padding When Decoding

// Some APIs return Base64 without padding
const b64NoPad = "SGVsbG8"; // Missing ==

// WRONG
atob(b64NoPad);  // May throw or return incorrect data

// CORRECT — add padding before decoding
function safeDecode(b64) {
  const padded = b64 + '='.repeat((4 - b64.length % 4) % 4);
  return atob(padded);
}
console.log(safeDecode("SGVsbG8")); // "Hello"

3. Treating Base64 as Encryption

// WRONG — Base64 is NOT encryption
const "secret" = btoa("password123");  // Anyone can decode this!
// btoa("password123") = "cGFzc3dvcmQxMjM=" — trivially reversible

// CORRECT — use actual encryption
const key = await crypto.subtle.generateKey(
  { name: 'AES-GCM', length: 256 },
  true,
  ['encrypt', 'decrypt']
);
const encrypted = await crypto.subtle.encrypt(
  { name: 'AES-GCM', iv: crypto.getRandomValues(new Uint8Array(12)) },
  key,
  new TextEncoder().encode("password123")
);
// Now encode the encrypted bytes as Base64 for storage/transport
const encryptedB64 = btoa(String.fromCharCode(...new Uint8Array(encrypted)));

4. Confusing Base64URL with Standard Base64

// JWT tokens use Base64URL (- and _ instead of + and /)
const jwtPayload = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";

// WRONG — trying to decode JWT part with standard atob()
atob(jwtPayload);  // May fail if it contains - or _

// CORRECT — convert Base64URL to standard Base64 first
function decodeBase64url(b64url) {
  const padded = b64url.replace(/-/g, '+').replace(/_/g, '/')
    + '='.repeat((4 - b64url.length % 4) % 4);
  return JSON.parse(atob(padded));
}

const payload = decodeBase64url(jwtPayload);
console.log(payload); // { alg: 'HS256', typ: 'JWT' }

5. MIME Base64 Line Breaks

// MIME/email Base64 adds \r\n every 76 characters
// Some implementations choke on these line breaks

// Python's base64.encodebytes() adds newlines automatically
import base64
encoded_with_newlines = base64.encodebytes(b"Hello World " * 100)
# b'SGVsbG8gV29ybGQgSGVsbG8gV29ybGQg...'
# Note: each 76-char line ends with \n

# To get clean Base64 without newlines, use b64encode
clean = base64.b64encode(b"Hello World " * 100)

# Node.js does NOT add line breaks — this is safe
Buffer.from(data).toString('base64')  // No line breaks

// If you receive MIME Base64, strip whitespace before decoding
const cleanB64 = mimeB64.replace(/[\r\n\s]/g, '');
const decoded = atob(cleanB64);

6. Using Non-Multiple-of-3 Chunk Sizes for Streaming

// WRONG — chunk size 1000 is not a multiple of 3
// This produces incorrect = padding after each chunk
const chunks = [];
for (let i = 0; i < data.length; i += 1000) {
  chunks.push(btoa(String.fromCharCode(...data.slice(i, i + 1000))));
}
// Concatenating these produces WRONG output!

// CORRECT — use multiples of 3: 3, 6, 57, 3072, etc.
const CHUNK_SIZE = 3072; // 3 * 1024
const chunks = [];
for (let i = 0; i < data.length; i += CHUNK_SIZE) {
  chunks.push(btoa(String.fromCharCode(...data.slice(i, i + CHUNK_SIZE))));
}
// Only the LAST chunk may have = padding — this is correct!

Key Takeaways

  • Base64 converts 3 bytes → 4 characters using a 64-char alphabet; output is always ~33% larger than input.
  • Browser: use btoa()/atob() for ASCII, TextEncoder+TextDecoder for Unicode strings.
  • Node.js: Buffer.from(str).toString('base64') and Buffer.from(b64, 'base64').toString('utf8') handle all cases.
  • Python: base64.b64encode() and base64.b64decode() work with bytes objects; encode strings with .encode('utf-8') first.
  • Go: use base64.StdEncoding, base64.URLEncoding, or base64.RawURLEncoding from encoding/base64.
  • Rust: use the base64 crate with general_purpose::STANDARD or URL_SAFE_NO_PAD engines.
  • Base64URL replaces +- and /_ for JWT tokens and URL parameters.
  • For streaming/large files, always use chunk sizes that are multiples of 3 bytes.
  • Base64 is encoding, NOT encryption — never use it to protect sensitive data.
  • Inline Base64 images are only worthwhile for assets under ~5KB; larger images lose browser caching benefits.
𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

B64Base64 Encoder/DecoderB→Base64 Encoder🖼️Image Base64 ConverterJWTJWT Decoder

相关文章

Base64 编码实战:每个开发者都应该知道的 7 个真实用途

发现 Base64 编码的 7 个实际应用:HTML 嵌入图片、Kubernetes Secrets、JWT Token、Data URI 等。

命令行 Base64 编解码(Linux、Mac、Windows)

学习如何在任何操作系统的终端中编码和解码 Base64 字符串。涵盖 Linux base64 命令、macOS openssl 和 Windows PowerShell 示例。

Base64 编解码在线指南:JavaScript、Python、命令行及更多

Base64 编解码完整指南。学习 JavaScript(btoa/atob、Buffer)、Python、命令行、Data URI、JWT、API 认证、URL 安全 Base64、性能考量和安全警告。