LASSIC Media らしくメディア
Base64の仕組みと使いどころ、base64urlとの違い
監修・編集責任者:牛尾 昭昌(株式会社LASSIC 執行役員)
この記事の結論
- Base64は、3バイトのデータを6ビットずつ4つに分け、64種類の英数字と記号の4文字で表す符号化の方式です。
- サイズは約4/3倍に増え、末尾の「=」、改行、URL向けのbase64urlなど、使う場面ごとに別の取り決めがあります。
- 暗号化ではないため秘密を守る手段にはならず、送る側と受ける側で方式と検証のしかたをそろえます。
※ 本記事は2026年10月時点の公式情報(省庁・公的機関、および製品やサービスを提供する事業者が公開している資料)に基づきます。
base64は、画像や証明書のようなバイナリのデータを、メールやJSON、URLのように文字しか通らない経路で送るための符号化の方式です。3バイトを4文字に置き換えるだけの単純な仕組みですが、パディングの「=」、76文字ごとの改行、URL向けの別の文字表といった細かな違いがあり、送る側と受ける側で方式がずれると、デコードの失敗やデータの欠けにつながります。
本記事では、システム開発や運用に携わる方に向けて、RFC 4648などの仕様をもとに、Base64の仕組みとサイズの増え方、base64urlとの違い、Python・JavaScript・コマンドでの変換例、実務での使いどころとつまずきやすい点を整理します。
目次
Base64とは
Base64は、任意のバイト列を、US-ASCIIの65文字で表す符号化の方式で、IETFのRFC 4648に定められています。使う文字はA〜Z、a〜z、0〜9、「+」「/」の64文字と、末尾を埋める「=」です。1文字で6ビットを表すため、2の6乗の64種類の文字が要ります。*1
もとは電子メールでバイナリを送るために広まった方式です。MIMEの規格であるRFC 2045は、Base64の転送符号化を、人が読める必要のない形でバイト列を表すものとし、符号化したデータはもとより約33%大きくなると書いています。あわせて、この文字の集まりがISO 646のどの版でも同じように表される点を挙げています。*2 文字化けや制御文字の混入を避けて、文字しか通らない経路にデータを載せられるのが、Base64を使う理由です。
Base64が扱うのはバイト列です。日本語の文字列を変換するときは、先にUTF-8などでバイト列にしてから符号化します。どの文字コードでバイト列にするかで結果が変わる点は、「文字コードとは?文字化けの原因とUTF-8への統一手順」で扱っています。
3バイトを4文字にする仕組み
RFC 4648の手順では、入力を左から3バイト(24ビット)ずつ区切り、それを6ビットずつ4つに分けて、それぞれの値(0〜63)を文字表の1文字に置き換えます。文字表では、値0がA、25がZ、26がa、51がz、52〜61が0〜9、62が「+」、63が「/」です。*1
図の例では、「Man」の3バイト(0x4D、0x61、0x6E)を並べた24ビットを6ビットずつ区切ると、19、22、5、46になり、文字表でT、W、F、uに当たります。こうして3バイトが「TWFu」の4文字になります。デコードはこの逆で、4文字をそれぞれ6ビットの値に戻し、つなげてから8ビットずつ切り出します。
表を引くだけの変換なので、計算は単純です。圧縮も暗号化もしないため、同じ入力からはいつも同じ文字列ができ、文字列から元のバイト列を誰でも復元できます。
パディングとサイズの増え方
入力の長さが3の倍数でないときは、最後の区切りが24ビットに満ちません。RFC 4648は、足りない部分を0のビットで埋めて6ビット単位にそろえ、出力が4文字の組になるよう「=」を足すと定めています。最後の区切りが1バイトなら2文字と「==」、2バイトなら3文字と「=」です。参照する仕様が別に定めない限り、この「=」は付けなければなりません。*1
| 入力 | バイト数 | 出力 | 末尾の「=」 |
|---|---|---|---|
| f | 1 | Zg== | 2つ |
| fo | 2 | Zm8= | 1つ |
| foo | 3 | Zm9v | なし |
| foob | 4 | Zm9vYg== | 2つ |
| foobar | 6 | Zm9vYmFy | なし |
出力の文字数は、入力のバイト数を3で割って切り上げ、4を掛けた数になります。3,000バイトなら4,000文字で、約4/3倍、つまり約33%の増加です。改行を入れる方式では、さらに改行の分が加わります。画像やファイルをBase64にしてJSONやHTMLに埋め込むと、転送量と保存量がこの割合で増えるため、APIの上限やデータベースの項目の長さを見積もるときに入れておきます。
base64urlとの違い
標準のBase64で使う「+」と「/」は、URLやファイル名の中では特別な意味を持ちます。そこでRFC 4648は、62番目を「-」、63番目を「_」に置き換えた文字表を「base64url」として別に定め、標準のbase64と同じものと見なしたり、単に「base64」と呼んだりすべきではないとしています。URLの中では「=」もパーセントエンコードされることが多いため、データの長さが分かっていればパディングを省いてよいとも書いています。*1
| 方式 | 使う文字 | 1文字のビット数 | パディング |
|---|---|---|---|
| base64 | A〜Z、a〜z、0〜9、+、/ | 6 | 「=」で4文字の組にそろえる |
| base64url | A〜Z、a〜z、0〜9、-、_ | 6 | 長さが分かれば省ける |
| base32 | A〜Z、2〜7 | 5 | 「=」で8文字の組にそろえる |
| base16 | 0〜9、A〜F | 4 | 要らない |
JSON Web Signature(JWS)を定めたRFC 7515は、base64urlから末尾の「=」をすべて除き、改行や空白も入れない形を使うと定義しています。*4 JWT(署名付きのJSON形式のトークン)が「.」で区切った英数字の列に見えるのは、各部分がこの形で符号化されているためです。なお、URLで使えない文字を%XXの形に置き換える仕組みは別のもので、「URLエンコードの仕組み」で扱っています。
言語とコマンドでの変換例
Pythonでは標準ライブラリのbase64モジュールを使います。b64encode()が標準の文字表、urlsafe_b64encode()が「-」と「_」を使う文字表で、urlsafe_b64encode()の結果にも「=」は残ります。b64decode()は、既定では文字表にない文字を捨ててから処理し、validate=Trueを渡すと、そうした文字があれば例外を出します。*5
>>> import base64
>>> base64.b64encode(b'Man')
b'TWFu'
>>> base64.b64encode('日本'.encode('utf-8'))
b'5pel5pys'
>>> data = bytes([0xfb, 0xff])
>>> base64.b64encode(data), base64.urlsafe_b64encode(data)
(b'+/8=', b'-_8=')
>>> base64.b64decode('-_-_')
b''
>>> base64.b64decode('-_-_', validate=True)
binascii.Error: Only base64 data is allowed
上の例では、base64urlの文字列を標準のデコーダーに渡したため、「-」と「_」が捨てられて空のバイト列が返りました。エラーにならずにデータが消える動きなので、受け取る側では文字表を合わせたうえで、validate=Trueで検証しておくと、欠けに気づけます。
ブラウザのJavaScriptでは、btoa()とatob()が使えます。btoa()は1文字を1バイトとして扱う文字列しか受け付けず、コードポイントが0xffを超える文字を渡すと例外になります。*6 日本語はTextEncoderでUTF-8のバイト列にしてから符号化します。Uint8Arrayのメソッドの toBase64() は、文字表とパディングの省略を引数で指定でき、MDNはbtoa()よりこちらを使うよう勧めています。*7 比較的新しい機能なので、動かす環境で使えるかを先に確かめます。
btoa('Man'); // 'TWFu'
btoa('日本'); // InvalidCharacterError
const bytes = new TextEncoder().encode('日本');
btoa(String.fromCharCode(...bytes)); // '5pel5pys'
const b = new Uint8Array([0xfb, 0xff]);
b.toBase64(); // '+/8='
b.toBase64({ alphabet: 'base64url', omitPadding: true }); // '-_8'
コマンドでは、GNU coreutilsのbase64が使えます。既定では76文字ごとに改行を入れ、-w 0で改行をなくせます。デコードは-dで、文字表にない文字を読み飛ばすには-iを付けます。*8
$ printf 'Man' | base64
TWFu
$ head -c 3000 /dev/urandom | base64 -w 0 | wc -c
4000
$ head -c 3000 /dev/urandom | base64 | wc -l
53
$ printf 'Zm9vYg' | base64 -d
foobbase64: invalid input
3,000バイトの乱数を符号化すると、改行なしではちょうど4,000文字になり、既定では76文字ずつの行が53行並びます。パディングの欠けた「Zm9vYg」を-dで戻すと、「foob」を出力したうえでエラーを返しました。途中までの出力が残るため、スクリプトでは出力だけでなく終了コードも確かめます。
実務での使いどころ
Base64がよく使われるのは、次のような場面です。
- メールの添付ファイル:MIMEのBase64転送符号化で本文に入れる
- data URL:小さな画像やフォントをHTMLやCSSに直接埋め込む
- JSONやXMLのAPI:画像やPDFを文字列の項目として送る
- 証明書や鍵:PEM形式のファイルとしてテキストで扱う
- CI/CD(ビルドとデプロイの自動化)のシークレットや環境変数:バイナリのファイルを文字列として登録する
- JWTや署名付きURL:base64urlで値をURLに載せる
data URLはRFC 2397に定められ、「data:[<mediatype>][;base64],<data>」の形で書きます。RFC 2397は、この方式が短い値にだけ向いているとしています。*3 大きな画像をdata URLにすると、HTMLやCSSが約33%増しの大きさで膨らみ、画像だけをキャッシュする使い方もできなくなります。
CI/CDでは、署名用の証明書のようなファイルをBase64にしてシークレットに登録し、ビルドのときに戻す使い方があります。具体的な流れは「モバイルアプリのCI/CD構築の進め方」で触れています。どの場面も、文字しか通らない場所にバイナリを載せるための使い方です。バイナリのまま送れる経路なら、変換しないほうが転送量は小さく済みます。
つまずきやすい点
最も多い誤解は、Base64を暗号化と取り違えることです。RFC 4648は、Base64はパスワードのような情報を見た目の上で隠すだけで、計算上の秘匿性は何も与えないとし、通信の記録を共有してパスワードが漏れた事故が起きていると注意しています。*1 設定ファイルやログにBase64の文字列があっても、誰でも元に戻せます。秘密の情報は暗号化し、Base64はその結果を文字にする工程として使います。
2つ目は改行です。RFC 4648は、参照する仕様が指示しない限り改行を入れてはならないとしていますが、MIMEは76文字、PEMは64文字で改行します。*1 Pythonのencodebytes()も76文字ごとに改行を入れます。改行入りの文字列をHTTPヘッダーやJSONの値、環境変数に入れると、受け取る側で壊れた値として扱われることがあります。
3つ目は文字表とパディングの取り違えです。base64urlで作った値を標準のデコーダーに渡したり、パディングを省いた値をそのまま戻そうとしたりすると失敗します。RFC 7515の付録Cは、標準のBase64の関数でbase64urlを扱う方法として、「=」を除き、「+」を「-」に、「/」を「_」に置き換える手順を示しています。*4 戻すときは逆に置き換え、長さが4の倍数になるまで「=」を足します。
4つ目は、文字表にない文字の扱いです。RFC 4648は、文字表にない文字を含むデータは原則として拒否しなければならないとし、無視すると情報を漏らす隠れた通り道や、文字列の比較をすり抜ける手段になり得ると注意しています。*1 一方でMIMEは、改行など文字表にない文字を無視するよう定めています。受け取るデータがどちらの規則で作られたかを見て、デコーダーの設定を決めます。
外部に委託するときに確認しておきたい点
外部のシステムとの連携やAPIの仕様書では、細部が書かれないまま「Base64で送る」とだけ決まることがあります。開発を委託するときは、仕様書に次の点が書かれているかを確かめます。
- 標準のBase64か、base64urlか
- 末尾の「=」を付けるか、省くか
- 改行を入れるか(入れるなら何文字ごとか)
- 文字列を符号化するときの文字コード
- 受け取る側で、文字表にない文字や長さの誤りをエラーにするか
- 符号化した後のサイズの上限(API、データベースの項目、ログ)
受け入れの試験では、バイト数を3で割った余りが0・1・2になる入力、日本語を含む文字列、「+」と「/」が出る入力(0xfbや0xffを含むバイト列など)を用意して、送る側と受ける側で往復させます。秘密の情報をBase64にしただけで送ったり保存したりしていないかも、設計のレビューで確かめる項目です。
まとめ:Base64で確かめておきたい3つの点
確かめておきたい点は3つです。第一に、Base64は3バイトを4文字にする符号化で、サイズは約4/3倍になること。第二に、標準のBase64とbase64url、パディングの有無、改行の有無はそれぞれ別の取り決めで、送る側と受ける側でそろえる必要があること。第三に、暗号化ではないため秘密を守る手段にはならず、受け取る側では文字表にない文字をエラーにする設定で検証することです。データの受け渡しの方式は、設計の段階で書き出しておきます。
よくある質問
Base64にすると、データはどのくらい大きくなりますか
3バイトごとに4文字になるため、約4/3倍(約33%増)です。出力は4文字単位にそろえるので、入力のバイト数を3で割って切り上げ、4を掛けた文字数になります。MIMEのように改行を入れる方式では、改行の分がさらに増えます。
Base64でパスワードを保存してもよいですか
よくありません。Base64は誰でも元に戻せる符号化で、秘匿の役には立ちません。パスワードは目的に合った方法(保存ならパスワード向けのハッシュ関数など)で扱い、Base64は暗号化やハッシュの結果を文字列にする場面で使います。
「=」が付いていないBase64の文字列を戻せないのはなぜですか
デコーダーが4文字単位の長さを求めているためです。base64urlではパディングを省く使い方が多く、戻すときは長さが4の倍数になるまで「=」を足してから処理します。Pythonのb64decode()は、パディングが正しくないと例外を出します。
base32やbase16はどんなときに使いますか
RFC 4648では、base32は大文字と小文字を区別しなくてよい場面向けの方式、base16は一般的な16進数の表記と同じものとして定められています。Base64より文字列は長くなりますが、大文字・小文字の違いに左右されにくいのが利点です。
Base64を使ったデータ連携の設計のご相談
元請(プライムベンダー)として、APIやシステム間のデータ連携の設計と実装から、システムの保守・運用までご提案します。
Remoguとリラシクなら、データ連携やAPIの開発に加わるITエンジニアも探せます。
Remoguは、リモート前提で全国から即戦力のITプロ人材を調達するサービスです。リラシクは、扱う求人がすべてリモートワークのITエンジニア専門転職エージェントです。どちらもLASSICが運営しています。
出典
- *1 参考:IETF「RFC 4648 The Base16, Base32, and Base64 Data Encodings」(2006年10月)(https://www.rfc-editor.org/rfc/rfc4648)。出典:3.1節(改行、MIMEの76文字とPEMの64文字)・3.2節(パディング)・3.3節(文字表にない文字)・4節(Base64と文字表)・5節(base64url)・6節(base32)・8節(base16)・10節(テストベクター)・12節(セキュリティ上の考慮)を参照(2026年10月確認)
- *2 参考:IETF「RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One」(https://www.rfc-editor.org/rfc/rfc2045)。出典:6.8節(Base64 Content-Transfer-Encoding、約33%の増加、ISO 646での表現、1行76文字、文字表にない文字の無視)を参照(2026年10月確認)
- *3 参考:IETF「RFC 2397 The “data” URL scheme」(https://www.rfc-editor.org/rfc/rfc2397)。出典:2節(data URLの形式、短い値にだけ向くこと)を参照(2026年10月確認)
- *4 参考:IETF「RFC 7515 JSON Web Signature (JWS)」(https://www.rfc-editor.org/rfc/rfc7515)。出典:2節(Base64url Encodingの定義)・付録C(パディングなしのbase64urlの実装)を参照(2026年10月確認)
- *5 参考:Python Software Foundation「base64 — Base16, Base32, Base64, Base85 Data Encodings」(https://docs.python.org/3/library/base64.html)。出典:b64encode()・b64decode()(validate引数)・urlsafe_b64encode()・encodebytes()の説明を参照(2026年10月確認)
- *6 参考:MDN Web Docs「Window: btoa() method」(https://developer.mozilla.org/en-US/docs/Web/API/Window/btoa)。出典:Exceptions と Unicode strings の項(1バイトを超える文字でのInvalidCharacterError)を参照(2026年10月確認)
- *7 参考:MDN Web Docs「Uint8Array.prototype.toBase64()」(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/toBase64)。出典:alphabet と omitPadding の引数、btoa()より優先して使うとする説明を参照(2026年10月確認)
- *8 参考:GNU「GNU Coreutils: base64 invocation」(https://www.gnu.org/software/coreutils/manual/html_node/base64-invocation.html)。出典:-w(既定76文字)・-d・-i の各オプションを参照。内容はGNU coreutils 8.32の base64 –help で確認(2026年10月確認)