% だらけになった日本語 URL を解読してみる【パーセントエンコーディング】

2025/2/28

日本語の入った URL をコピーしたときに、% がたくさん入った文字列になってなぜだろうと思ったことはありませんか?

例えば Wikipedia の URL などは日本語が入っているので、

https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0

コピーをした際などにこのような文字列になってしまうことがあります。

今回はなぜそのようなことが起こるのか、またそのような文字列を解読する方法を探ってみます。

なぜこのようなことが起こるのか

URL の中で使用できる文字は限られています。使用できない文字は、何らかの方法で使用できる文字に変換してあげないといけません。

例えば : (コロン) のような文字は、http: のように URL の中で特別な意味で使われるので、: という文字そのものを URL の中で使うことはできません。

試しに、アルファベットで「colon」と検索するときと、記号で「:」と検索するときを比べてみましょう。

アルファベットと記号の検索の比較

アルファベットで検索した際は文字列がそのまま入っていますが、記号で検索した際は %3A に変わっているのがわかります。

次は、日本語で検索してみます。検索した段階では日本語で表示されていますが、コピーして貼り付けると % を含む文字列に変わってしまいました。

日本語でコロンと検索

このように、URL の中で使えない文字を、使える文字に変換して表現することを一般に URL エンコード などというようです。URL エンコードの手法として、% の後に 2 桁の 16 進数を置くことで文字を表現する方法は パーセントエンコーディング と呼ばれます。

% の文字列を解読してみる

では、冒頭の URL の

%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0

という文字列を解読してみましょう。

準備: 16 進数 → 2 進数 の変換

パーセントエンコーディングでは、% の後に 2 桁の 16 進数を並べているのでした。

あとで扱いやすいよう、この 16 進数を 2 進数に変換しておきます。

最初は E3 です。

  • E は 10 進数の 14 ですから、2 進数だと 1110 となります。
  • 3 は 10 進数の 3 ですから、2 進数だと 0011 となります。

よって E311100011 となります。

この要領で全て変換すると下のようになります。1 バイト (= 8 ビット、2 進数の 8 桁) ごとに空白で区切っています。

11100011 10000011 10010111 11100011 10000011 10101101
11100011 10000010 10110000 11100011 10000011 10101001
11100011 10000011 10011111 11100011 10000011 10110011
11100011 10000010 10110000

変換のステップ

では、この 11100011... のような数字がどのように「あ」などの実際の文字に結びついているのでしょうか?

その方法は本来さまざまですが、ここでは現在多くの環境で使われていると思われる UTF-8 による方法を紹介します。やや複雑ですが、文字と数字を対応づけている Unicode というルールがあり、さらにその数字の並びを変形する UTF-8 という仕組みが存在します。

したがって、解読する際は、UTF-8 → Unicode → 実際の文字 という順を辿る必要があります。

UTF-8 → Unicode の変換

UTF-8 で表された数字の列を Unicode に変換するやり方ですが、

  1. 0xxxxxxx
  2. 110xxxxx 10xxxxxx
  3. 1110xxxx 10xxxxxx 10xxxxxx
  4. 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

のいずれかのパターンに当てはめた後、x の部分だけを取り出して並べればよいです。

今回の数字列の最初を見てみると 11100011 となっています。上の表を見れば、これは 3. のパターンに合致するので、3 バイト分をひとまとまりとしてみれば良いことがわかります。

3 バイト取り出すと 11100011 10000011 10010111 でした。

ここから x の部分を抜き出せば 0011 000011 010111 です。16 進数に変換すれば、30 D7 となります。

これで Unicode が得られました。

この要領で全て変換すると下のようになります。

UTF-8 (2 進数)Unicode (2 進数)Unicode (16 進数)
11100011 10000011 1001011100110000 1101011130 D7
11100011 10000011 1010110100110000 1110110130 ED
11100011 10000010 1011000000110000 1011000030 B0
11100011 10000011 1010100100110000 1110100130 E9
11100011 10000011 1001111100110000 1101111130 DF
11100011 10000011 1011001100110000 1111001130 F3
11100011 10000010 1011000000110000 1011000030 B0

Unicode → 文字 の変換

あとは Unicode に対応する文字を対応表から探せば良いだけです。

対応表はこちらを参照しましょう。

https://ja.wikipedia.org/wiki/Unicode一覧表

30 D7 ならば U+30D7 のように表されているので、「Unicode一覧 3000-3FFF(U+3000からU+3FFFまで)」に進んで探していきます。

U+30D7 に対応する文字を探していくと、それは「プ」でした!

・・・というわけで、この要領で変換を行っていくと文字をすべて解読することができます。

今回の解読結果
元の文字列Unicode実際の文字
%E3%83%9730 D7
%E3%83%AD30 ED
%E3%82%B030 B0
%E3%83%A930 E9
%E3%83%9F30 DF
%E3%83%B330 F3
%E3%82%B030 B0

参考