ブログ

Base64 画像が表示されない?よくある 10 の原因と修正方法

2026 年 4 月 28 日公開 · 約 8 分で読めます

画像を Base64 に変換し、data URI を HTML に挿入した──なのに何も表示されない。壊れた画像アイコンがぽつんと表示されるだけ。さらに厄介なことに、Chrome では表示されるのに Safari では真っ白、ローカルでは動くのに本番ではダメ、ということもあります。

Base64 画像の表示失敗がもどかしいのは、文字列が一見正しく見えるからです。本当の原因は細部に潜んでいます──プレフィックスの 1 文字の欠落、コピペ時に紛れ込む不可視の空白、バックエンドが知らぬ間に行う二重エンコード。この記事では 10 の原因すべてをコード例と修正方法付きで解説します。

クイックリファレンス:症状 → 原因 → 修正

まずここから。自分の症状を見つけ、原因を特定し、下の詳細な修正方法にジャンプしてください。

# 症状 原因 修正方法
1 404 / 壊れた画像アイコンdata: プレフィックスがないdata:image/...;base64, を追加
2 空白 / 表示されない; を , と誤記プレフィックスのセミコロンを修正
3 空白 / 表示されないbase64 の後にカンマがないカンマを追加: base64,
4 画像が途中で切れる / 破損文字列の切り詰めTEXT 型カラムを使用
5 InvalidCharacterError空白 / 不正な文字の混入str.replace(/\s/g, '')
6 コードでは正常、HTML で壊れる改行 \n の混入\r\n を除去
7 ブラウザ間で動作が不一致パディング = が消失URL エンコードまたはパディング補完
8 通常は問題なしMIME タイプ不一致正しく直すべきだが原因ではない
9 壊れたアイコン、文字列が ~33% 長い二重エンコード余分なエンコード処理を削除
10 壊れたアイコン、文字列に \/JSON / URL エスケープ汚染JSON.parse() を使用

プレフィックスの誤り:data: URI が不正

data URI の構文は厳密です。1 文字間違えるだけで、ブラウザは Base64 文字列を画像データではなく壊れた URL として扱います。

原因 1:data URI プレフィックスがまるごと欠落

生の Base64 文字列を data:image/...;base64, プレフィックスなしで直接 src に設定すると、ブラウザはそれを相対 URL パスと解釈し、結果は 404 になります。

❌ <img src="iVBORw0KGgo..." />
✅ <img src="data:image/png;base64,iVBORw0KGgo..." />

原因 2:セミコロンをカンマと誤記

data:image/png;base64,... ではなく data:image/png,base64,... と書くと、ブラウザは base64,... を Base64 エンコードの指示ではなくプレーンテキストとして扱います。

❌ data:image/png,base64,iVBORw0KGgo...
✅ data:image/png;base64,iVBORw0KGgo...

原因 3:"base64" の後のカンマが欠落

base64 と実際のデータの間のカンマは必須です。data:image/png;base64iVBOR... のように省略すると、ブラウザは base64iVBOR... を文字セット名と解釈します。

❌ data:image/png;base64iVBORw0KGgo...
✅ data:image/png;base64,iVBORw0KGgo...

エンコーディング破損:Base64 文字列自体が壊れている

プレフィックスが正しくても、エンコード済みデータは保存・転送・コピペの過程で知らぬ間に破損することがあります。

原因 4:文字列の切り詰め

データベースのカラムに文字数またはバイト数の制限(例: VARCHAR(65535))があると、Base64 文字列が切り詰められることがあります。100KB の PNG は約 136,000 文字になります。65,535 バイトで切られると、デコード後の画像は壊れます。修正:データベースとエンコーディングに十分な型を選び、MySQL なら MEDIUMTEXT や LONGTEXT を検討し、切り詰めを検出してください。

原因 5:不正な文字の混入(空白・特殊文字)

有効な Base64 は A-Z、a-z、0-9、+、/、= のみで構成されます。コピペ時に混入した空白は atob() の InvalidCharacterError を引き起こします。修正:使用前にすべての空白を除去: str.replace(/\s/g, '')。

原因 6:改行文字の混入

openssl base64 はデフォルトで 76 文字ごとに \n を挿入します(RFC 2045 準拠)。これらの改行は HTML の data URI を壊します。修正:openssl base64 -A(一行出力)を使うか、改行を除去: str.replace(/[\r\n]/g, '')。

原因 7:URL 解析でパディングが消失

Base64 の = は URL やフォームの処理で誤って扱われることがあり、+ が空白に変換される場合もあります。修正:URL に入れる前に値をエンコードし、必要に応じて URL-safe Base64 を使い、受信側でパディングを検証してください。

MIME タイプ不一致:本当に壊れるのか?

意外かもしれませんが、MIME タイプを間違えて宣言しても、ほとんどの場合画像は正常に表示されます。

原因 8:宣言した MIME と実際のファイル形式が不一致

data:image/png;base64,/9j/4AAQ...(JPEG データに PNG の MIME を宣言)でも表示される場合はありますが、結果は処理系の MIME 対応に依存します。厳格なクライアントやサーバー側の変換では失敗することがあります。結論:MIME と実際のバイト列を一致させ、普遍的な原因ではなく候補の一つとして確認してください。

パイプラインの問題:ブラウザに届く前にデータが壊れている

このカテゴリは最も診断が難しい──コード上の Base64 文字列は正しく見えるのに、シリアライズや転送の過程で破損が発生しています。

原因 9:Base64 の二重エンコード

バックエンドがすでにエンコード済みのデータをさらに Base64 エンコードすると、Base64 文字列をもう一度 Base64 したものが生成されます。長さが想定より ~33% 多くなり、一度デコードしてもバイナリ画像データではなくテキストが得られます。見分け方:一度デコードし、結果がまた Base64 文字列のように見える(英字で始まり = で終わる)なら二重エンコードです。修正:バックエンド処理から余分なエンコードを削除してください。

原因 10:JSON エスケープまたは URL エンコーディング汚染

シリアライズ済み JSON や URL データを生の文字列として扱うと、Base64 が壊れることがあります。\/ は正しく JSON.parse() すれば問題ありませんが、フォーム処理では + が空白になる場合があります。修正:JSON を解析し、URL 値をエンコードして、受信側でデコード後のバイト列を検証してください。

体系的デバッグテンプレート

上記のどれにも該当しない場合、以下の手順で切り分けてください:

  1. ブラウザのアドレスバーで data URI をテスト ── 完全な data:image/...;base64,... 文字列をアドレスバーに直接貼り付けます。表示されれば、アプリケーション側の文字列注入に問題があります。
  2. ブラウザコンソールを確認 ── F12 を押して Console タブで net::ERR_INVALID_URL や CSP 違反のエラーを探します。
  3. 文字列の長さを照合 ── ソース(バックエンド)とフロントエンドで受け取った Base64 文字列の長さを比較します。不一致があれば転送中の切り詰めか破損です。
  4. デコードして検査 ── コンソールで atob() を使い最初の数文字をデコードします。InvalidCharacterError が出れば不正な文字が混入しています。
  5. 二重エンコードを検出 ── 一度デコードし、結果がまだ Base64 文字列のように見えたらもう一度デコードします。二回目で二進データが得られれば、処理パイプラインに余分なエンコード工程があります。

ViewJSON で Base64 を即座に検証

Base64 文字列を手動で検証する代わりに、JSON を ViewJSON に貼り付けてください。マジックナンバー検出で Base64 エンコードメディアを自動識別し、インラインプレビューを表示します──プレビューが表示されれば Base64 は有効。表示されなければ、どのフィールドが壊れているか正確に特定できます。

関連記事

JSON API レスポンス内の Base64 画像をデバッグする最適な方法 →

今すぐ試す

Base64 文字列を貼り付けて、正しくレンダリングされるか即座に確認──ブラウザ内で完結、アップロード不要。

ViewJSON を開く →