🏦

【初心者向け】ブラウザのエンコーディングについて

2025/02/18に公開

こんにちは、ワニかず@40歳 出戻りエンジニアです。

FlutterとDjangoの開発の勉強をしていたのですが、

  • ブラウザ側(HTML + JavaScript)では文字化けしない
  • Flutterアプリ側では文字化けする

という現象が起きた中で、
ブラウザのエンコーディングについて調べたのでまとめました。

盛大に文字化けしています。

構成

原因

  • レスポンスに明示的にcontent_type='charset=utf-8'を指定しなかったが
  • ブラウザ側が、独自のエンコーディング検出アルゴリズムを持っている
  • そのため、ブラウザ側では文字化けしなかった

ということでした。
※Djangoのデフォルト文字コードはutf-8のようですが、プロジェクト内で上手く機能していない。
 これに関しては別途時間があるときに調べたい。

ブラウザの文字コード判定処理

Content-Type charset が指定されていない場合、以下の順序で文字コードを判定します。

  1. BOMチェック(優先順位: 最高)
  • ファイルの先頭バイトをチェックし、BOM (Byte Order Mark) の有無を確認
  • BOMが見つかった場合、それに応じた文字コードを使用
    • EF BB BF → UTF-8
    • FE FF → UTF-16BE
    • FF FE → UTF-16LE
  1. HTMLのメタタグチェック(優先順位: 2番目)
<meta charset="UTF-8">
// または古い形式
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  1. ヒューリスティック解析(優先順位: 最低)
  • バイトパターン分析を行い、文字コードを推測
  • 例えば:
    • 特定のバイトシーケンスがUTF-8として有効かチェック
    • 各文字コードでデコードを試み、エラー率が最も低いものを選択
    • 言語固有の文字の出現頻度を分析

主要なブラウザ(Chrome、Firefox、Safari)は、それぞれ独自のエンコーディング検出アルゴリズムを持っています:

  • Chrome: Compact Language Detector (CLD)
  • Firefox: Universal Character Set Detector
  • Safari: WebKit's character encoding detector

このため、Content-Type charset がなくても正常に日本語が表示される理由は:

  1. HTMLファイル内にmetaタグで文字コードが指定されている
  2. または、ブラウザの文字コード判定アルゴリズムが日本語のパターンを正しく認識している

ベストプラクティスとしては、以下が推奨されます:

  1. Content-Type charset を明示的に指定する
  2. HTMLファイルの先頭にmeta charset タグを配置する
  3. 可能であればBOMを付与する

これにより、ブラウザの推測に頼ることなく、確実に意図した文字コードで表示されます。

おしまいに

ブラウザの大半は優しさでできているようです。

Discussion