本文へ移動
ZEKILO Dev
エンコード

日本語URLが%E6…になる理由とShift_JIS

2026.10.03 更新 · 4分で読めます

URLにはASCIIの一部しか使えないため、日本語はバイト列にしてから%XXで書きます。UTF-8とShift_JISで結果が違う理由、encodeURIComponentとencodeURIの違い、二重エンコードの問題を説明します。

URLエンコード・デコードをすぐに使う

日本語のURLが%E6%97%A5…のように変わるのは、文字化けではなくパーセントエンコーディングです。URLにはASCIIの一部の文字しか使えないため、日本語はまずバイト列(通常はUTF-8)に変換し、各バイトを%と16進数2桁で書きます。「日」はUTF-8で3バイトのE6 97 A5なので、%E6%97%A5になります。URLエンコード・デコードで方向を「デコード」にして貼り付ければ元の文字に戻せます。文字コードをShift_JISにすれば、Shift_JISでエンコードされたURLも読めます。

パーセントエンコーディングの規則

RFC 3986の規則を整理すると、URLで使う文字は3つに分かれます。

区分 文字 扱い
非予約文字 英字、数字、- . _ ~ そのまま書く
予約文字 :/?#[]@ と !$&'()*+,;= 区切り文字。値として入れるときはエンコード
それ以外 日本語などの非ASCII文字、スペース、"<>などの一部のASCII文字 バイト列にして%XXで書く

16進数は大文字が推奨されており、%e6と%E6は同じバイトを表します。

入力 結果(UTF-8、encodeURIComponent)
日本語 %E6%97%A5%E6%9C%AC%E8%AA%9E
日本語 dev&tools=1 %E6%97%A5%E6%9C%AC%E8%AA%9E%20dev%26tools%3D1

よく使う漢字やかなは1文字がUTF-8で3バイトなので、エンコードすると9文字になります。日本語を含むURLが長くなるのはこのためです。

UTF-8とShift_JISでは結果が違う

パーセントエンコーディングはバイトの書き方にすぎません。文字をどのバイトにするかは、文字コードが決めます。同じ「日本語」でも結果が異なります。

文字コード バイト列 パーセントエンコーディング
UTF-8 E6 97 A5 E6 9C AC E8 AA 9E(9個) %E6%97%A5%E6%9C%AC%E8%AA%9E
Shift_JIS(CP932) 93 FA 96 7B 8C EA(6個) %93%FA%96%7B%8C%EA
EUC-JP C6 FC CB DC B8 EC(6個) %C6%FC%CB%DC%B8%EC

RFC 3986は、新しいURIスキームでは文字データを先にUTF-8に変換してからエンコードするよう勧めています。ブラウザが従うWHATWG URL標準も、パスは常にUTF-8でエンコードします。ただしクエリ文字列は文書の文字コードに従うため、Shift_JISで作られたページのリンクやフォームからは%93%FA…のような値が送られます。Shift_JISで動いている古いシステムと連携するときに、パラメーターをShift_JISでエンコードするよう求められるのはこのためです。

見分け方と注意点は次のとおりです。

  • 漢字やかな1文字が%XX3つならUTF-8、2つならShift_JISかEUC-JPの可能性が高いです。
  • Shift_JISの結果をUTF-8として戻そうとすると失敗します。JavaScriptのdecodeURIComponent('%93%FA%96%7B%8C%EA')はURIErrorを投げます。
  • 逆に、UTF-8のバイト列をShift_JISとして読むと文字化けします。「ゼキロ」は繧シ繧ュ繝ュになります。
  • Shift_JISの2バイト目は、ASCIIと同じ値になることがあります。「ゼキロ」は83 5B 83 4C 83 8Dで、4CはASCIIのLです。そのため%83%5B%83L%83%8Dのように、結果に英字が混ざる場合があります。

相手のシステムがどの文字コードを使っているかは、推測せずに連携仕様書で確認してください。

encodeURIComponent・encodeURI・フォーム形式

方式 そのまま残す文字 スペース 使う場面
encodeURIComponent 英字、数字、-_.!~*'() %20 クエリの値、パスの1区切り
encodeURI 上の文字と;/?:@&=+$,# %20 URL全体
フォーム形式 英字、数字、*-._ + HTMLフォーム、URLSearchParams
  • URL全体:https://dev.zekilo.com/ja/検索?q=a bはhttps://dev.zekilo.com/ja/%E6%A4%9C%E7%B4%A2?q=a%20bになります。:、/、?、=は区切り文字として残ります。
  • フォーム形式:URLSearchParamsでqに日本語 URLを入れると、q=%E6%97%A5%E6%9C%AC%E8%AA%9E+URLになります。スペースが+に変わります。
  • !'()*~は、encodeURIComponentでは変わりません。

値の中に&や=があるのにencodeURIを使うと、その文字が区切りとして読まれ、パラメーターが分かれてしまいます。クエリの値を1つ入れるときは、encodeURIComponentかURLSearchParamsを使ってください。

よくある問題

  • 二重エンコード:エンコード済みの文字列をもう一度エンコードすると、%が%25になります。%E6%97%A5は%25E6%2597%25A5になります。RFC 3986は、同じ文字列を2回以上エンコードまたはデコードしてはならないとしています。
  • 途中で切れたシーケンス:URLが途中で切れて%E0%A4%Aのように終わっていると、デコードはエラーになります。チャットやメールで長いURLの末尾が欠けていないか確認してください。
  • +とスペース:デコードのときに+をスペースとして読むのは、フォーム形式だけです。decodeURIComponent('a+b')はa+bをそのまま返します。
  • 日本語ドメイン:ホスト名はパーセントエンコーディングではなく、Punycodeに変換されます。https://日本語.jp/のホストはxn--wgv71a119e.jpになります。

まとめ

  • %E6%97%A5は「日」のUTF-8のバイトを書いたものです。デコードすれば元の文字に戻ります。
  • 新しく作るシステムではUTF-8を使います。Shift_JISやEUC-JPは、相手のシステムが求めるときだけ使います。
  • 値にはencodeURIComponent、URL全体にはencodeURIを使い、エンコードは1回だけにします。
  • URLを確認するときはURLエンコード・デコードを使ってください。入力はブラウザ内だけで処理されます。

この記事に関連するツール

出典と基準

ほかのガイド