> ## Content Index
> Fetch the complete content index at: https://www.tool-cloud.com/blog/ja/llms.txt
> Use this file to discover other available public pages before exploring further.

# JavaScriptでテキストをBase64に変換する方法（およびデコード方法）
- URL: https://www.tool-cloud.com/blog/ja/javascript-base64-encode/
- Published: 2026-10-14T18:18:34.000Z
- Updated: 2026-10-14T18:29:02.000Z
- Description: 正しく動作する一行コード、エラーを投げるコード、その理由 — さらにUTF-8対応の完全な変換サイクル、2025年のネイティブメソッド、そしてNode.jsの違いについて解説します。
- Author: Tool Cloud Team
- Tags: 開発者向け, ガイド

JavaScriptで文字列をBase64エンコードするには、`btoa('Hello, world!')`を呼び出し、`'SGVsbG8sIHdvcmxkIQ=='`を返します。この一行コードはASCIIおよびLatin-1テキストにのみ有効ですが、絵文字、アクセント付き文字、または中国語文字を渡すと、すぐに`InvalidCharacterError`を投げます。このガイドでは、なぜそのようなことが起きるのか、そして2025年の新しいネイティブメソッドを含む、これを修正するUTF-8対応の完全な変換サイクルを紹介します。

## Base64を一行で：btoa()とatob()

最速の答え：エンコードは `btoa('Hello, world!')`、デコードは `atob('SGVsbG8sIHdvcmxkIQ==')` を使います。どちらも検証済みです：`btoa('a')` は `'YQ=='` を返し、`atob('SA==')` は `'S'` を返します。

[btoa()](https://developer.mozilla.org/en-US/docs/Web/API/Window/btoa) が実際にやっていることは、文字列を「バイナリ文字列」として扱い、各文字がバイナリデータの1バイトに相当する文字列として Base64 エンコードすることです。MDNでの使用例は、ASCII制御文字（0〜31）など、テキスト専用のチャンネルを通して運びたいデータです。

テキストがASCIIの場合、この一行で十分です。すべての文字のコードポイントは256未満である必要があり、MDNによると、バイトとコードポイントの対応関係は0x7Fまでしか確実に保たれません。0x80–0xFFの範囲は技術的には動作しますが、これは環境間で移植性のないLatin-1エンコーディングの動作に依存しています。良いルールとして、ASCII以外のものは以下のUTF-8パスを使用してください。

## btoa() が絵文字、アクセント記号、CJK文字で InvalidCharacterError を投げる理由

Base64はバイナリエンコーディングであり、テキストエンコーディングではありません。[MDNの用語集](https://developer.mozilla.org/en-US/docs/Glossary/Base64) は、任意のテキストやHTMLを `btoa()` に渡す習慣を一般的な誤解と呼んでいます：`btoa`/`atob` は型付き配列よりも前に存在するため、バイトを表すために文字列を使用しています。問題は、文字列が1文字1バイトではない場合に始まります。

JavaScriptの文字列はUTF-16なので、コードユニットは常に2バイトであり、BMP外の文字（絵文字など）はサロゲートペアとして4バイトを取ります；UTF-8はコードポイントあたり1〜4バイトを使用します。`btoa()` と `atob()` は単一バイト（Latin-1範囲）の文字のみで動作します。それより広いものをエンコードしようとすると、次のような正確なエラーが発生します。

```
DOMException: Failed to execute 'btoa' on 'Window':
The string to be encoded contains characters outside of the Latin1 range

```

問題となるケースは簡単に再現できます：`btoa('✓')` が例外を投げ、`btoa('a Ā 𐀀 文 🦄')` も同様です。絵文字、Latin-1を超えるアクセント記号、CJK文字はすべて0xFFより上にあるため、1文字1バイトという前提には適合しません。`'✓'` は U+2713 で、0xFFをはるかに超えているため、`btoa()` はデータを静かに壊すのではなく拒否します。この拒否は、APIの最も優れた機能と言えるかもしれません：数週間後にモジバケを発見する代わりに、明示的に失敗します。

これを修正する前に知っておくと役立つこと：Base64はデータを生のバイト数より約33%大きくします。短い文字列、トークン、データURIなら問題ありませんが、大規模なペイロード全体をBase64化しないほうがよい本質的な理由にもなります — エンコードは必要な境界で一度だけ行い、あちこちで行わないようにしましょう。

![左から流れてきて2つのパスに分かれる柔らかい3Dの青いリボン：一方のストランドは整然としたクラスターグループを形成します…](https://www.tool-cloud.com/blog/ja/content/images/2026/10/javascript-base64-encode-utf8-split.webp)

1つのデータストリーム、2つのバイトフットプリント：マルチバイトクラスタ versus 単一バイト。

### 孤立サロゲートのエッジケース（および String.isWellFormed()）

多くの記事はこれを省略していますが、後で痛い目を見ます。UTF-16文字列に孤立サロゲート（絵文字ペアの半分、通常はスライシングバグによるもの）が含まれている場合、それは「壊れた（malformed）」状態になります。[web.devのガイド](https://web.dev/articles/base64-encoding)によると、`TextDecoder`はデフォルトでU+FFFDを静かに置換します。エンコードする前に、`String.prototype.isWellFormed()`でwell-formed（整形式）かどうかを確認するか、孤立サロゲートがあるときに`encodeURIComponent()`が投げる`URIError`をキャッチし、データを拒否するか、意図的に置換を有効にするか、後の分析のために例外を投げるかを明確に決めてください。

## 正しい方法：TextEncoder → UTF-8バイト → Base64

正しい修正方法は、まず`TextEncoder`を使って文字列をUTF-8バイトに変換し、その後、文字列ではなくバイトをBase64エンコードすることです。`new TextEncoder().encode(str)`は任意のJavaScript文字列をUTF-8バイトの`Uint8Array`に変換します（TextEncoderはUTF-8のみを扱います）。復元時は、`new TextDecoder()`はデフォルトでUTF-8を使用し、正確に逆変換します。ここで`atob()`が返すものにご注意ください：これはバイナリ文字列であり、1文字が1バイトに対応しますが、UTF-8テキストではありません。そのため、復元側では`TextDecoder`を使ってバイトを読み取り可能なテキストに戻す必要があります。

### bytesToBase64()およびbase64ToBytes()ヘルパー関数（コピペ用コード）

ここに[MDNの標準的な往復処理](https://developer.mozilla.org/en-US/docs/Web/API/Window/btoa)を示します。これは`TextEncoder`をサポートするすべてのブラウザ（IEを除く）で動作します。

```js
function bytesToBase64(bytes) {
  const binString = Array.from(bytes, (b) => String.fromCodePoint(b)).join('');
  return btoa(binString);
}

function base64ToBytes(base64) {
  const binString = atob(base64);
  return Uint8Array.from(binString, (m) => m.codePointAt(0));
}

```

### 完全な往復処理で検証する

文字列のエンコードは1行で完了します。

```js
const encoded = bytesToBase64(new TextEncoder().encode('a Ā 𐀀 文 🦄'));
// 'YSDEgCDwkICAIOaWhyDwn6aE'

```

デコードはそれを逆に実行します。

```js
const decoded = new TextDecoder().decode(base64ToBytes(encoded));
// 'a Ā 𐀀 文 🦄'

```

web.devが検証した往復処理も同じパターンを確認しています：`'hello⛳❤️🧀'`は`'aGVsbG/im7PinaTvuI/wn6eA'`にエンコードし、絵文字を含めて正確に復元します。

### unescape(encodeURIComponent())というトリックは避ける

`btoa(unescape(encodeURIComponent(str)))`はあちこちでコピーされているのを見かけるでしょう。これは機能しますが、`unescape()`はAnnex Bのレガシー仕様であり、ECMAScript 3以来非推奨です。新しいコードでは代わりに`TextEncoder`を使用すべきです。明示的で標準的であり、非推奨のグローバル関数に依存しないためです。

## 2025年の最新手法：Uint8Array.toBase64()とUint8Array.fromBase64()

2025年9月以降、JavaScriptには`Uint8Array`自体にネイティブのBase64メソッドが実装されており、上記のバイト文字列ヘルパーだけが選択肢というわけではありません。TC39の[Base64提案](https://github.com/tc39/proposal-arraybuffer-base64/blob/main/README.md)はStage 4に到達し、言語の一部となりました。TC39の理由は、Base64はテキストエンコーディングではないため、TextEncoder/TextDecoderは概念的に適切なツールではないということです。

[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global%5FObjects/Uint8Array/toBase64)によると、これらのメソッドは常に利用可能なブラウザ全体で「新規利用可能」としてベースラインに含まれています。リリース前にターゲットランタイムを確認してください：古いブラウザや古いNodeバージョンをサポートする場合は、`TextEncoder` \+ `btoa`のフォールバックを維持してください。MDNは、すでに`Uint8Array`がある場合に、生のバイト文字列を作成する必要がないため、これらのメソッドを`btoa()`/`atob()`よりも優先しています。

### エンコード：bytes.toBase64()

```js
const b64 = new TextEncoder().encode('Hello, world!').toBase64();
// 'SGVsbG8sIHdvcmxkIQ=='

```

UTF-8変換を1回、メソッド呼び出しを1回行うだけで完了です。

### デコード：Uint8Array.fromBase64()

```js
const text = new TextDecoder().decode(Uint8Array.fromBase64(b64));
// 'Hello, world!'

```

MDNのドキュメント `fromBase64()` は、デコードされたデータがASCIIテキストとして意図されていない限り、実際のバイト配列を返すため、 `atob()` よりも優先して使用すべきです。これは base64 アルファベット（A–Z、a–z、0–9、および `+/` または `-_`）のみを受け入れ、オプションの `=` パディングに対応し、ASCIIの空白文字は無視します。アルファベット外の文字が含まれていると、 `SyntaxError` がスローされます。

### オプション: alphabet, omitPadding, lastChunkHandling

[仕様のオプションバッグ](https://tc39.es/proposal-arraybuffer-base64/) により、きめ細かな制御が可能です。

| オプション             | 値                                              | 機能                                                                           |
| ----------------- | ---------------------------------------------- | ---------------------------------------------------------------------------- |
| alphabet          | 'base64' (既定値), 'base64url'                    | +// と \-/\_ の比較                                                              |
| omitPadding       | boolean                                        | 末尾の \= を削除します: new Uint8Array(\[72\]).toBase64() → 'SA=='、omitPadding → 'SA' |
| lastChunkHandling | 'loose' (既定値), 'strict', 'stop-before-partial' | 最終チャンクに対するデコーダーの許容度                                                          |

`'loose'` は、パディング不足や空白を許容します。 `'strict'` は、オーバーフロービットをゼロにした正確な4文字のチャンクを要求します。これは信頼できない入力を検証する際に望ましい挙動です。 `'stop-before-partial'` はストリーミング用です。既定の緩いモードでは、厳格モードが拒否する非ゼロのオーバーフロービットも許容されます。

## Base64 と base64url: どちらのアルファベットが必要か？

標準的な base64 は、 `+` と `/` に加えて `=` パディングを使用し、パスセグメントやクエリ文字列を持たない `data:` URL では問題ありません。base64url（RFC 4648 §5）は、 `-` と `_` に置き換えられ、通常はパディングを省略します。出力がURL内に含まれる場合は必ず必要です。例えば、JWTは3つのセグメントすべてに base64url を使用します。

### base64url を使用するタイミング

エンコードされた文字列がURLのパスまたはクエリパラメータの一部になる場合、 `+` や `/` はエスケープが必要になり、 `=` パディングはクエリ文字列を煩雑にするため、 base64url を使用してください。データURI、JSONペイロードへのバイト埋め込み、URLではないその他の用途には、標準的な base64 を使用します。

### base64url の生成方法

環境に応じて3つの方法があります。

- 最新のブラウザ: `bytes.toBase64({ alphabet: 'base64url' })`
- Node 16以降: `Buffer.from(str).toString('base64url')`
- 後処理: 標準的な出力を取得し、 `+` → `-` 、 `/` → `_` に置換してから、 `=` を削除します。

知っておくと役立つ微妙な点: RFC 4648 では、エンコーダーが最終チャンクのデータ以外のオーバーフロービットをゼロにすることが義務付けられており、厳格なデコーダーはそれがゼロでない場合にエラーをスローする可能性があります。MDNの用語集では、 `'VR=='` の例が示されており、これは `'VQ=='` と同じバイトですが、パディングビットが汚れています。動作が保証されたエンコーダーで base64 を生成すればこの問題は発生しません。独自に実装すると発生する可能性があります。

## ファイルや画像を Base64（データURI）に変換する方法

ファイルの場合、ブラウザでの方法は、 `readAsDataURL()` を使用した `FileReader` で完全なデータURIを作成し、プレフィックスを除去して生の base64 を取得することです。すでにキャンバス上に描画されている画像の場合、 `toDataURL('image/png')` を1回の呼び出しで実行できます。

### FileReader.readAsDataURL() → データURI → 生の base64

```js
function fileToDataURL(file) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.readAsDataURL(file);
  });
}

const dataUrl = await fileToDataURL(fileInput.files[0]);
const rawBase64 = dataUrl.replace(/^data:\w+\/\w+;base64,/, '');

```

### canvas.toDataURL() （画像用）

キャンバスに画像を描画した（リサイズ、切り抜きなど）場合は、FileReader を完全にスキップしてください。

```js
const dataUrl = canvas.toDataURL('image/png');

```

生の Base64 文字列のみが必要な場合も、同様にプレフィックスの除去処理が必要です。

### Data URL からバイト列への変換

逆方向の変換は、fetch と ArrayBuffer の組み合わせで行います。MDN の例では、`new Uint8Array([0,1,2])` から構築された Data URL は `'data:application/octet-stream;base64,AAEC'` となり、以下のようにバイト列を復元できます。

```js
const res = await fetch(dataUrl);
const bytes = new Uint8Array(await res.arrayBuffer());
// [0, 1, 2]

```

そして、この記事が存在する理由に関する重要な注意点：任意のテキストや HTML に対して `btoa()` を呼び出して Data URL を作成しないでください。これはバイナリ単位でのエンコーダーであり、Latin-1 以外の入力ではエラーが発生します。

## Node.js: Buffer.from(str, 'base64') — およびその危険な違い

Node には、TextEncoder を使う面倒な手順を省ける定番の書き方があります。Buffer は最初からバイト単位で動作するため、`Buffer.from('Hello, world! 🌍').toString('base64')` は Unicode を自動的に処理します。デコードには `Buffer.from(encoded, 'base64').toString('utf8')` を使用します。

その他の有用な形式：Node 16 以降で使用可能な `Buffer.from(str).toString('base64url')` や、ファイル全体を対象とする `fs.readFileSync('image.png').toString('base64')` などがあります。

```js
const encoded = Buffer.from('Hello, world! 🌍').toString('base64');
const decoded = Buffer.from(encoded, 'base64').toString('utf8');

```

### Node は Base64 の検証を行いません（エラーが出ずに黙って失敗します）

ここで人々が驚くポイント：Node の Base64 デコーダーは入力を検証しません。`Buffer.from('!!!!', 'base64').toString()` はエラーを返さずに `''` を返し、`Buffer.from('aGVsbG8!!!', 'base64')` は不正なデータを黙って破棄して `'hello'` を返します。これに対し、`atob('aGVsbG8!!!')` は `InvalidCharacterError` をスローします。Base64 がユーザー、API、またはサードパーティから提供される場合は、Node でデコードする前に検証するか、ランタイムがサポートしている場合は `Uint8Array.fromBase64()` に `lastChunkHandling: 'strict'` を組み合わせて使用してください。

### btoa/atob は非推奨ですか？ブラウザと Node の違い

これは確かに矛盾しているように見えるため、正直な解決策を提示します。ブラウザでは、[MDN が btoa() と atob()](https://developer.mozilla.org/en-US/docs/Web/API/Window/btoa) Baseline は 2015 年 7 月以来広く利用可能であり、非推奨ではありません。一方、Node では [型定義](https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/58795) でそれらが `@deprecated` とマークされ、「新しいコードでは決して使用すべきではない」というコメントと共に、代わりに `Buffer.from(str, 'base64')` を推奨しています。

良いルールとして、これらは削除された API ではなくレガシー API です。ブラウザコードでは問題ありませんが、Node 固有のコードでは `Buffer` を優先してください。コミュニティの合意（仕様上の保証ではありませんが）、依存関係なしでブラウザ、Deno、Node で変更せずに実行できる単一のコードパスが必要な場合、`btoa`/`atob` が実用的なクロス環境の選択となります。

## 実際に何を使用すべきか

この記事から一つの推奨事項を選ぶなら、以下の 3 つのワンライナーです。プレーンな ASCII やレガシーなコードベースでは `btoa`/`atob` を維持し、`bytesToBase64` ヘルパーをブラウザのフォールバックとして使用してください。これは、`toBase64()` があなたの全オーディエンスをカバーするまで有効です。

```js
// Modern browsers (2025+)
const enc = new TextEncoder().encode(str).toBase64();
const dec = new TextDecoder().decode(Uint8Array.fromBase64(b64));

// Browser fallback (MDN helper)
const encFallback = bytesToBase64(new TextEncoder().encode(str));

// Node (validate input first if it isn't yours)
const encNode = Buffer.from(str).toString('base64');

```

リリース前に、ブラウザツールで簡単な往復テストを行い、出力を確認してください。`'Hello, world!'` を [Tool Cloud の無料 Base64 エンコーダー / デコーダー](https://www.tool-cloud.com/ja/dev/base64%5Fencoder/) に貼り付け、`'SGVsbG8sIHdvcmxkIQ=='` が得られることを確認してから、再度デコードして同一であることを確認してください。また、スタンドアロンの [テキストから Base64 への変換](https://www.tool-cloud.com/ja/general/text%5Fto%5Fbase64/) や [Base64 からテキストへの変換](https://www.tool-cloud.com/ja/general/base64%5Fto%5Ftext/) も用意されています。ファイルは自動的に削除され、インストールは不要です。

## よくある質問

### なぜbtoa()は絵文字では失敗するのに、英語テキストでは正常に動作するのでしょうか？

btoa()は各文字を1バイトとして扱い、各コードポイントが256未満（確実に0x7Fまで）であることを要求します。絵文字、アクセント付き文字、CJK（中国語・日本語・韓国語）テキストは複数のバイトが必要なため、DOMException: InvalidCharacterErrorが発生します。まずTextEncoderを使ってUTF-8バイトに変換し、その後エンコードしてください。

### btoa()は非推奨になっていますか？

ブラウザ上では非推奨ではありません。MDNによると、btoa()とatob()は2015年7月以降広く利用可能（Baseline widely available）です。ただし、Node.jsの型定義では、Node固有のコードにおいてBuffer.from(str, 'base64')を推奨し、それらを非推奨としています。これらは削除されたAPIではなく、レガシーAPIです。

### ユニコードテキスト（アクセント、中国語、絵文字など）をBase64エンコードするにはどうすればよいですか？

new TextEncoder().encode(str)を使用してUTF-8バイトを取得し、その後バイト列をエンコードします（ブラウザではbtoa()をバイト列ヘルパー経由で使用するか、Uint8Array.toBase64()を使用します）。デコードするには、Uint8Array.fromBase64()またはatob()でバイト列に戻し、その後new TextDecoder().decode(bytes)を実行します。

### base64とbase64urlの違いは何ですか？

base64url（RFC 4648 §5）は'+'と'/'の代わりに'-'と'\_'を使用し、通常'='パディングを省略します。出力結果がURLやJWTに含まれる場合はbase64urlを使用し、パスセグメントやクエリ文字列を持たないdata: URLには標準的なbase64で問題ありません。

### なぜNode.jsは不正なBase64に対してエラーを投げないのですか？

NodeのBuffer.from(str, 'base64')は入力検証を行わず、無効な文字を静かに無視するため、Buffer.from('aGVsbG8!!!', 'base64').toString()はエラーなしで'hello'を返します。一方、ブラウザではatob()が同じ入力でInvalidCharacterErrorを投げます。Nodeで信頼できないBase64をデコードする前に、必ず検証を行ってください。