コードベース全体にBase64文字列が散在しているのを見たことがあるでしょう — JWTトークン、 HTMLの<img>タグ、HTTP Authorizationヘッダー、またはファイルデータを含むJSONペイロードなど。 SGVsbG8sIFdvcmxkIQ==のように、意味不明に見えます。しかし、それらが存在する明確な理由があり、 一度理解すれば、Base64は謎めいたものではなく、あなたのツールボックスにおける本当に役立つツールになります。

Base64とは何か

Base64はバイナリ-テキスト変換スキームです。それだけです。 ヌル文字、制御コード、または0から255の任意の値を含む可能性のある任意のバイナリデータを取り込み、 64個の印刷可能な ASCII文字のみを使用して表現します。 結果は、破損したり誤解されたりすることなく、任意のテキストベースのチャネルを安全に通過できる文字列です。

正式な仕様はIETFが発行した RFC 4648に記載されています。 標準Base64とURLセーフバリアントの両方を定義しています。パディングルールやアルファベットの選択について 議論を解決する必要がある場合に備えてブックマークしておく価値があります。

Base64アルファベット

64文字のアルファベットは、大文字A–Z(26文字)、 小文字a–z(26文字)、数字0–9(10文字)、 そして2つの記号:+/で構成されています。これでちょうど64文字になります — これが名前の由来です。入力の長さが3の倍数でない場合、末尾のパディング文字として=記号が使用されます。

text
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

各文字はデータの正確に6ビットをエンコードします(2^6 = 64の可能な値)。これが エンコードの核心的なメカニズムであり、約33%のサイズオーバーヘッドの理由です。

エンコードの仕組み

アルゴリズムは3バイト → 4つのBase64文字のチャンクで動作します。 3バイト = 24ビット。その24ビットを4つの6ビットグループに分割し、各グループがBase64アルファベットの 1つの文字にマッピングされます。

text
Input:  "Man"
Bytes:  M=77 (01001101)  a=97 (01100001)  n=110 (01101110)
Bits:   010011 010110 000101 101110
Index:  19     22     5      46
Output: T      W      F      u     →  "TWFu"

入力が3で割り切れない場合、パディングが機能します。残り2バイトは 3つのBase64文字と1つの=になります。残り1バイトは2つのBase64文字 と==になります。パディングはデコーダーに末尾に実際に何バイトあるかを伝えるだけです — それはデータ自体の一部ではありません。

サイズオーバーヘッド:入力の3バイトごとに4文字の出力になります。 これは33%のサイズ増加です。小さな文字列には無視できます。大きなバイナリ ファイル — 10MBの画像は約13.3MBのBase64になります — オーバーヘッドは重要であり、 直接埋め込む前によく考えるべきです。

JavaScriptでのエンコードとデコード

ブラウザは btoa()atob() をグローバルとして公開しています。シンプルですが落とし穴があります:Latin-1文字(バイト値0〜255)のみを処理します。 マルチバイトのUnicode文字列を直接渡すとInvalidCharacterErrorが発生します。

js
// Basic browser encoding/decoding
const encoded = btoa('Hello, World!');  // "SGVsbG8sIFdvcmxkIQ=="
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');  // "Hello, World!"

// Safe Unicode version — encode to UTF-8 first
function encodeUnicode(str) {
  return btoa(
    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (_, hex) =>
      String.fromCharCode(parseInt(hex, 16))
    )
  );
}

function decodeUnicode(str) {
  return decodeURIComponent(
    atob(str)
      .split('')
      .map(c => '%' + c.charCodeAt(0).toString(16).padStart(2, '0'))
      .join('')
  );
}

const emoji = encodeUnicode('Héllo wörld 🌍');
console.log(emoji);                  // "SMOpbGxvIHfDtnJsZCDwn4yN"
console.log(decodeUnicode(emoji));   // "Héllo wörld 🌍"

Node.js — Bufferの使用

Node.jsでは、慣用的なアプローチは Buffer APIです。 これはUnicodeを正しく処理し、上記のブラウザの回避策よりもずっとクリーンです。

js
// Encoding
const encoded = Buffer.from('Hello, World!', 'utf8').toString('base64');
console.log(encoded);  // "SGVsbG8sIFdvcmxkIQ=="

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

// Encoding a file to Base64 (e.g. to embed in a JSON payload)
const fs = require('fs');

function fileToBase64(filePath) {
  const fileBuffer = fs.readFileSync(filePath);
  return fileBuffer.toString('base64');
}

function base64ToFile(base64String, outputPath) {
  const fileBuffer = Buffer.from(base64String, 'base64');
  fs.writeFileSync(outputPath, fileBuffer);
}

const avatarBase64 = fileToBase64('./uploads/avatar.png');
const payload = {
  userId: 'usr_8f3k2',
  avatarData: avatarBase64,
  mimeType: 'image/png'
};

Python — base64モジュール

Pythonの標準ライブラリには、エンコード、デコード、URLセーフバリアントを処理する base64モジュール が含まれています。関数はbytesオブジェクトで動作するため、 通常は明示的な文字セットで文字列をエンコード/デコードします。

python
import base64

# Encoding a string
message = "Hello, World!"
encoded = base64.b64encode(message.encode("utf-8"))
print(encoded)           # b'SGVsbG8sIFdvcmxkIQ=='
print(encoded.decode())  # 'SGVsbG8sIFdvcmxkIQ=='

# Decoding
decoded_bytes = base64.b64decode("SGVsbG8sIFdvcmxkIQ==")
print(decoded_bytes.decode("utf-8"))  # 'Hello, World!'

# Encoding a file
with open("report.pdf", "rb") as f:
    pdf_base64 = base64.b64encode(f.read()).decode("utf-8")

# Embedding it in a JSON-compatible structure
import json
payload = {
    "filename": "report.pdf",
    "content": pdf_base64,
    "encoding": "base64"
}
print(json.dumps(payload, indent=2))

URLセーフBase64

標準のBase64はURLで特殊文字である+/を使用します。 標準のBase64文字列をクエリパラメータに入れると、最初にパーセントエンコードしない限り 微妙な破損が発生します。URLセーフBase64( RFC 4648 §5でも定義)は +-に、/_に置き換えることでこれを解決します。 パディング=記号はURLコンテキストでは完全に省略されることが多いです。

js
// Standard → URL-safe conversion in JavaScript
function toBase64Url(base64) {
  return base64
    .replace(/+/g, '-')
    .replace(///g, '_')
    .replace(/=+$/, '');  // strip padding
}

function fromBase64Url(base64url) {
  // Restore padding
  const padded = base64url + '=='.slice(0, (4 - (base64url.length % 4)) % 4);
  return padded.replace(/-/g, '+').replace(/_/g, '/');
}

const standard = btoa('some binary  data');
const urlSafe  = toBase64Url(standard);

console.log(standard);  // "c29tZSBiaW5hcnkAAGRhdGE="
console.log(urlSafe);   // "c29tZSBiaW5hcnkAAGRhdGE"  (safe for URLs)

Pythonではbase64.urlsafe_b64encode()base64.urlsafe_b64decode()を使用してください — 自動的に置換を行います。

一般的な実際のユースケース

  • HTML/CSSへの画像の埋め込みdata: URIのような src="data:image/png;base64,iVBORw0KGgo..."は別のHTTPリクエストを排除します。 小さなアイコンやスプライトには最適ですが、33%のサイズオーバーヘッドのため大きな画像には不向きです。
  • JWTトークンJSON Webトークンの ヘッダーとペイロードセクションはURLセーフBase64エンコードされたJSONオブジェクトです。JWTで見るドット区切りの3つの部分は Base64Url(ヘッダー).Base64Url(ペイロード).Base64Url(署名)です。
  • HTTP基本認証Authorization: Basic ... ヘッダーはユーザー名:パスワードをBase64としてエンコードします。 RFC 7617で定義されています。 注意:これはエンコードであり、暗号化ではありません — 常にHTTPSを使用してください。
  • JSONへのバイナリデータの埋め込み — JSONにはバイナリ型がないため、APIを介して送信されるファイル、画像、 証明書は通常、文字列フィールドにBase64エンコードされます。このワークフローについては ファイルからBase64画像からBase64 ツールを参照してください。
  • メールの添付ファイル — MIME(メールの基礎フォーマット)はBase64を使用して バイナリの添付ファイルをエンコードし、テキストのみのメールリレーサーバーを通じた転送で生き残れるようにします。 Base64が解決するために設計された元の問題です。
  • データベースへのバイナリデータの保存 — テキスト列またはJSONドキュメント内に小さなブロブ (証明書、サムネイル)を格納する必要がある場合、Base64が標準的な選択です。

Base64は暗号化ではない

これは常に人々を混乱させます — 特にコードレビュー時に。Base64は エンコードであり、暗号化ではありません。エンコードはデータの表現を変更する 可逆的な変換です。暗号化は秘密鍵を使用してデータをスクランブルし、 鍵を持つ人だけが逆にできるようにします。

誰でも数秒でBase64文字列をデコードできます — Base64デコーダーに貼り付ければ完了です。パスワード、APIキー、 個人データなどの機密値を「隠す」ためにBase64を使用しないでください。機密性が必要な場合は、 実際の暗号化(AES、RSA、またはブラウザの Web Crypto API、 またはPythonのcryptographyなどのライブラリ)を使用してください。

注目すべき点:Base64は圧縮ではありません。出力は常に 入力より大きくなります — 約3分の1。サイズを削減する必要がある場合は、まず圧縮し(gzip、 Brotli、zstd)、チャンネルがテキストを必要とする場合は圧縮されたバイトをBase64エンコードしてください。

Base64を扱うためのツール

毎日Base64を扱う場合、迅速なツールを持つことで大きな違いが生まれます。 任意のテキスト文字列をエンコードするにはBase64エンコーダー、 Base64値をデコードして検査するにはBase64デコーダー、 APIペイロードやストレージ用にバイナリファイルを変換するにはファイルからBase64、 HTMLやCSSに直接画像を埋め込むためのデータURIを生成するには画像からBase64 を使用してください。

まとめ

Base64はテキストのみのチャネルを通じてバイナリデータを破損なく通過させるという 特定の問題を解決するために存在します。64文字のアルファベット(A–Z、a–z、0–9、+、/)を使用して、 入力の3バイトごとに4つの印刷可能なASCII文字にマッピングすることでこれを実現します。 結果はメール、HTTPヘッダー、JSONフィールド、およびURL(URLセーフバリアントで)に安全です。 トレードオフは固定された33%のサイズ増加です。暗号化でも圧縮でもありません — 透明で可逆的なエンコードです。これを内面化すると、いつそれを使うべきか、 いつ別のツールが適しているかをすぐに知ることができます。