URLエンコードの早見表と変換
貼った文字はこの画面の中だけで変換します。外の機械に問い合わせることも、 どこかに送ることもありません。文字数の上限もありません。
「%」と16進2桁の並びが見つからないので、エンコード(URLに置ける形にする)として読みました。もとに戻したいときは上の3つから選び直してください。
| 文字 | 文字番号 | バイト(16進) | %表記 | 種類 |
|---|---|---|---|---|
| h | U+0068 | 68 | %68 | そのまま書ける |
| t | U+0074 | 74 | %74 | そのまま書ける |
| t | U+0074 | 74 | %74 | そのまま書ける |
| p | U+0070 | 70 | %70 | そのまま書ける |
| s | U+0073 | 73 | %73 | そのまま書ける |
| : | U+003A | 3A | %3A | 大きな区切り |
| / | U+002F | 2F | %2F | 大きな区切り |
| / | U+002F | 2F | %2F | 大きな区切り |
| p | U+0070 | 70 | %70 | そのまま書ける |
| o | U+006F | 6F | %6F | そのまま書ける |
| t | U+0074 | 74 | %74 | そのまま書ける |
| a | U+0061 | 61 | %61 | そのまま書ける |
| m | U+006D | 6D | %6D | そのまま書ける |
| o | U+006F | 6F | %6F | そのまま書ける |
| . | U+002E | 2E | %2E | そのまま書ける |
| n | U+006E | 6E | %6E | そのまま書ける |
| e | U+0065 | 65 | %65 | そのまま書ける |
| t | U+0074 | 74 | %74 | そのまま書ける |
| / | U+002F | 2F | %2F | 大きな区切り |
| 道 | U+9053 | E9 81 93 | %E9%81%93 | ASCIIの外 |
| 具 | U+5177 | E5 85 B7 | %E5%85%B7 | ASCIIの外 |
| ? | U+003F | 3F | %3F | 大きな区切り |
| q | U+0071 | 71 | %71 | そのまま書ける |
| = | U+003D | 3D | %3D | 小さな区切り |
| ト | U+30C8 | E3 83 88 | %E3%83%88 | ASCIIの外 |
| ム | U+30E0 | E3 83 A0 | %E3%83%A0 | ASCIIの外 |
| & | U+0026 | 26 | %26 | 小さな区切り |
| ジ | U+30B8 | E3 82 B8 | %E3%82%B8 | ASCIIの外 |
| ェ | U+30A7 | E3 82 A7 | %E3%82%A7 | ASCIIの外 |
| リ | U+30EA | E3 83 AA | %E3%83%AA | ASCIIの外 |
| ー | U+30FC | E3 83 BC | %E3%83%BC | ASCIIの外 |
| & | U+0026 | 26 | %26 | 小さな区切り |
| p | U+0070 | 70 | %70 | そのまま書ける |
| = | U+003D | 3D | %3D | 小さな区切り |
| 2 | U+0032 | 32 | %32 | そのまま書ける |
| # | U+0023 | 23 | %23 | 大きな区切り |
| t | U+0074 | 74 | %74 | そのまま書ける |
| o | U+006F | 6F | %6F | そのまま書ける |
| p | U+0070 | 70 | %70 | そのまま書ける |
この 39 文字を全部バイトにすると 55 バイトです。
| かけら | はたらき |
|---|---|
| https | しくみの名前(スキーム) |
| : | ここまでがしくみの名前ここが区切り |
| // | ここから住所ここが区切り |
| potamo.net | 住所(ホスト) |
| / | 道の区切りここが区切り |
| 道具 | 道(パス) |
| ? | ここから問い合わせここが区切り |
| q | 項目の名前 |
| = | 名前と値の境目ここが区切り |
| トム | 項目の値 |
| & | 項目の切れ目ここが区切り |
| ジェリー | 問い合わせ(クエリ) |
| & | 項目の切れ目ここが区切り |
| p | 項目の名前 |
| = | 名前と値の境目ここが区切り |
| 2 | 項目の値 |
| # | ここからページの中の位置ここが区切り |
| top | ページの中の位置(フラグメント) |
ASCII 128文字の早見表
0から127までを、1つも飛ばさずに並べました。目に見えない制御文字33個も、空欄にせず名前で出しています。 右の3列は「その形にしたとき、どう出るか」です ── そのまま残る文字はその文字が、 化ける文字は %XX が入ります。
- そのまま書ける英字52・数字10と、そのほか4つ
- 66 文字
- 大きな区切りURLを大きく区切る記号
- 7 文字
- 小さな区切り問い合わせの中などを区切る記号
- 11 文字
- どこでも要変換区切りの役も無く、そのままでは置けない
- 11 文字
- 制御文字画面に出ない文字(0x00〜0x1F と 0x7F)
- 33 文字
足し算にすると 66+7+11+11=95(印字できるASCII)、95+33=128。 この表は条文の集合の決まりから組み立てているので、行を書き写す作業がありません。
| 16進 | 10進 | 文字 | %表記 | URLのかけら向き | URL丸ごと向き | フォームが送る形 | 種類 |
|---|---|---|---|---|---|---|---|
| 00 | 0 | NUL Null | %00 | %00 | %00 | %00 | 制御文字 |
| 01 | 1 | SOH Start of Heading | %01 | %01 | %01 | %01 | 制御文字 |
| 02 | 2 | STX Start of Text | %02 | %02 | %02 | %02 | 制御文字 |
| 03 | 3 | ETX End of Text | %03 | %03 | %03 | %03 | 制御文字 |
| 04 | 4 | EOT End of Transmission | %04 | %04 | %04 | %04 | 制御文字 |
| 05 | 5 | ENQ Enquiry | %05 | %05 | %05 | %05 | 制御文字 |
| 06 | 6 | ACK Acknowledge | %06 | %06 | %06 | %06 | 制御文字 |
| 07 | 7 | BEL Bell | %07 | %07 | %07 | %07 | 制御文字 |
| 08 | 8 | BS Backspace | %08 | %08 | %08 | %08 | 制御文字 |
| 09 | 9 | HT Horizontal Tabulation | %09 | %09 | %09 | %09 | 制御文字 |
| 0A | 10 | LF Line Feed | %0A | %0A | %0A | %0A | 制御文字 |
| 0B | 11 | VT Vertical Tabulation | %0B | %0B | %0B | %0B | 制御文字 |
| 0C | 12 | FF Form Feed | %0C | %0C | %0C | %0C | 制御文字 |
| 0D | 13 | CR Carriage Return | %0D | %0D | %0D | %0D | 制御文字 |
| 0E | 14 | SO Shift Out | %0E | %0E | %0E | %0E | 制御文字 |
| 0F | 15 | SI Shift In | %0F | %0F | %0F | %0F | 制御文字 |
| 10 | 16 | DLE Data Link Escape | %10 | %10 | %10 | %10 | 制御文字 |
| 11 | 17 | DC1 Device Control 1 | %11 | %11 | %11 | %11 | 制御文字 |
| 12 | 18 | DC2 Device Control 2 | %12 | %12 | %12 | %12 | 制御文字 |
| 13 | 19 | DC3 Device Control 3 | %13 | %13 | %13 | %13 | 制御文字 |
| 14 | 20 | DC4 Device Control 4 | %14 | %14 | %14 | %14 | 制御文字 |
| 15 | 21 | NAK Negative Acknowledge | %15 | %15 | %15 | %15 | 制御文字 |
| 16 | 22 | SYN Synchronous Idle | %16 | %16 | %16 | %16 | 制御文字 |
| 17 | 23 | ETB End of Transmission Block | %17 | %17 | %17 | %17 | 制御文字 |
| 18 | 24 | CAN Cancel | %18 | %18 | %18 | %18 | 制御文字 |
| 19 | 25 | EM End of Medium | %19 | %19 | %19 | %19 | 制御文字 |
| 1A | 26 | SUB Substitute | %1A | %1A | %1A | %1A | 制御文字 |
| 1B | 27 | ESC Escape | %1B | %1B | %1B | %1B | 制御文字 |
| 1C | 28 | FS File Separator | %1C | %1C | %1C | %1C | 制御文字 |
| 1D | 29 | GS Group Separator | %1D | %1D | %1D | %1D | 制御文字 |
| 1E | 30 | RS Record Separator | %1E | %1E | %1E | %1E | 制御文字 |
| 1F | 31 | US Unit Separator | %1F | %1F | %1F | %1F | 制御文字 |
| 20 | 32 | SP Space | %20 | %20 | %20 | + | どこでも要変換 |
| 21 | 33 | ! | %21 | ! | ! | %21 | 小さな区切り |
| 22 | 34 | " | %22 | %22 | %22 | %22 | どこでも要変換 |
| 23 | 35 | # | %23 | %23 | # | %23 | 大きな区切り |
| 24 | 36 | $ | %24 | %24 | $ | %24 | 小さな区切り |
| 25 | 37 | % | %25 | %25 | %25 | %25 | どこでも要変換 |
| 26 | 38 | & | %26 | %26 | & | %26 | 小さな区切り |
| 27 | 39 | ' | %27 | ' | ' | %27 | 小さな区切り |
| 28 | 40 | ( | %28 | ( | ( | %28 | 小さな区切り |
| 29 | 41 | ) | %29 | ) | ) | %29 | 小さな区切り |
| 2A | 42 | * | %2A | * | * | * | 小さな区切り |
| 2B | 43 | + | %2B | %2B | + | %2B | 小さな区切り |
| 2C | 44 | , | %2C | %2C | , | %2C | 小さな区切り |
| 2D | 45 | - | %2D | - | - | - | そのまま書ける |
| 2E | 46 | . | %2E | . | . | . | そのまま書ける |
| 2F | 47 | / | %2F | %2F | / | %2F | 大きな区切り |
| 30 | 48 | 0 | %30 | 0 | 0 | 0 | そのまま書ける |
| 31 | 49 | 1 | %31 | 1 | 1 | 1 | そのまま書ける |
| 32 | 50 | 2 | %32 | 2 | 2 | 2 | そのまま書ける |
| 33 | 51 | 3 | %33 | 3 | 3 | 3 | そのまま書ける |
| 34 | 52 | 4 | %34 | 4 | 4 | 4 | そのまま書ける |
| 35 | 53 | 5 | %35 | 5 | 5 | 5 | そのまま書ける |
| 36 | 54 | 6 | %36 | 6 | 6 | 6 | そのまま書ける |
| 37 | 55 | 7 | %37 | 7 | 7 | 7 | そのまま書ける |
| 38 | 56 | 8 | %38 | 8 | 8 | 8 | そのまま書ける |
| 39 | 57 | 9 | %39 | 9 | 9 | 9 | そのまま書ける |
| 3A | 58 | : | %3A | %3A | : | %3A | 大きな区切り |
| 3B | 59 | ; | %3B | %3B | ; | %3B | 小さな区切り |
| 3C | 60 | < | %3C | %3C | %3C | %3C | どこでも要変換 |
| 3D | 61 | = | %3D | %3D | = | %3D | 小さな区切り |
| 3E | 62 | > | %3E | %3E | %3E | %3E | どこでも要変換 |
| 3F | 63 | ? | %3F | %3F | ? | %3F | 大きな区切り |
| 40 | 64 | @ | %40 | %40 | @ | %40 | 大きな区切り |
| 41 | 65 | A | %41 | A | A | A | そのまま書ける |
| 42 | 66 | B | %42 | B | B | B | そのまま書ける |
| 43 | 67 | C | %43 | C | C | C | そのまま書ける |
| 44 | 68 | D | %44 | D | D | D | そのまま書ける |
| 45 | 69 | E | %45 | E | E | E | そのまま書ける |
| 46 | 70 | F | %46 | F | F | F | そのまま書ける |
| 47 | 71 | G | %47 | G | G | G | そのまま書ける |
| 48 | 72 | H | %48 | H | H | H | そのまま書ける |
| 49 | 73 | I | %49 | I | I | I | そのまま書ける |
| 4A | 74 | J | %4A | J | J | J | そのまま書ける |
| 4B | 75 | K | %4B | K | K | K | そのまま書ける |
| 4C | 76 | L | %4C | L | L | L | そのまま書ける |
| 4D | 77 | M | %4D | M | M | M | そのまま書ける |
| 4E | 78 | N | %4E | N | N | N | そのまま書ける |
| 4F | 79 | O | %4F | O | O | O | そのまま書ける |
| 50 | 80 | P | %50 | P | P | P | そのまま書ける |
| 51 | 81 | Q | %51 | Q | Q | Q | そのまま書ける |
| 52 | 82 | R | %52 | R | R | R | そのまま書ける |
| 53 | 83 | S | %53 | S | S | S | そのまま書ける |
| 54 | 84 | T | %54 | T | T | T | そのまま書ける |
| 55 | 85 | U | %55 | U | U | U | そのまま書ける |
| 56 | 86 | V | %56 | V | V | V | そのまま書ける |
| 57 | 87 | W | %57 | W | W | W | そのまま書ける |
| 58 | 88 | X | %58 | X | X | X | そのまま書ける |
| 59 | 89 | Y | %59 | Y | Y | Y | そのまま書ける |
| 5A | 90 | Z | %5A | Z | Z | Z | そのまま書ける |
| 5B | 91 | [ | %5B | %5B | %5B | %5B | 大きな区切り |
| 5C | 92 | \ | %5C | %5C | %5C | %5C | どこでも要変換 |
| 5D | 93 | ] | %5D | %5D | %5D | %5D | 大きな区切り |
| 5E | 94 | ^ | %5E | %5E | %5E | %5E | どこでも要変換 |
| 5F | 95 | _ | %5F | _ | _ | _ | そのまま書ける |
| 60 | 96 | ` | %60 | %60 | %60 | %60 | どこでも要変換 |
| 61 | 97 | a | %61 | a | a | a | そのまま書ける |
| 62 | 98 | b | %62 | b | b | b | そのまま書ける |
| 63 | 99 | c | %63 | c | c | c | そのまま書ける |
| 64 | 100 | d | %64 | d | d | d | そのまま書ける |
| 65 | 101 | e | %65 | e | e | e | そのまま書ける |
| 66 | 102 | f | %66 | f | f | f | そのまま書ける |
| 67 | 103 | g | %67 | g | g | g | そのまま書ける |
| 68 | 104 | h | %68 | h | h | h | そのまま書ける |
| 69 | 105 | i | %69 | i | i | i | そのまま書ける |
| 6A | 106 | j | %6A | j | j | j | そのまま書ける |
| 6B | 107 | k | %6B | k | k | k | そのまま書ける |
| 6C | 108 | l | %6C | l | l | l | そのまま書ける |
| 6D | 109 | m | %6D | m | m | m | そのまま書ける |
| 6E | 110 | n | %6E | n | n | n | そのまま書ける |
| 6F | 111 | o | %6F | o | o | o | そのまま書ける |
| 70 | 112 | p | %70 | p | p | p | そのまま書ける |
| 71 | 113 | q | %71 | q | q | q | そのまま書ける |
| 72 | 114 | r | %72 | r | r | r | そのまま書ける |
| 73 | 115 | s | %73 | s | s | s | そのまま書ける |
| 74 | 116 | t | %74 | t | t | t | そのまま書ける |
| 75 | 117 | u | %75 | u | u | u | そのまま書ける |
| 76 | 118 | v | %76 | v | v | v | そのまま書ける |
| 77 | 119 | w | %77 | w | w | w | そのまま書ける |
| 78 | 120 | x | %78 | x | x | x | そのまま書ける |
| 79 | 121 | y | %79 | y | y | y | そのまま書ける |
| 7A | 122 | z | %7A | z | z | z | そのまま書ける |
| 7B | 123 | { | %7B | %7B | %7B | %7B | どこでも要変換 |
| 7C | 124 | | | %7C | %7C | %7C | %7C | どこでも要変換 |
| 7D | 125 | } | %7D | %7D | %7D | %7D | どこでも要変換 |
| 7E | 126 | ~ | %7E | ~ | ~ | %7E | そのまま書ける |
| 7F | 127 | DEL Delete | %7F | %7F | %7F | %7F | 制御文字 |
RFC 20(ASCII の規格そのもの)は、脚注で「In the strict sense, DEL is not a control character.(厳密にいえば DEL は制御文字ではない)」と自分で断っています。規格が書いているのはもう1つ、「紙テープの、まちがった文字や要らない文字を消すのに使う」ところまでです。0x7F は2進で 1111111 ── 紙テープなら穴が全部あいた形にあたります。
%XX の英字を大文字にしているのは、RFC 3986 §2.1 が 「URI producers and normalizers should use uppercase hexadecimal digits」 (作る側は16進の英字に大文字を使うべき)と書いているからです。小文字の %e3 も読む側は同じものとして扱いますが、 このページは作る側なので大文字で出します。
やってみる
1問目 / 全5問
よくある質問
URLエンコードとパーセントエンコーディングは同じものですか
ほとんど同じですが、正確には少し違います。パーセントエンコーディングは RFC 3986 が決めている「バイトを %XX の形にする」しくみそのものです。いっぽう「URLエンコード」と呼ぶとき、HTMLのフォームが使う application/x-www-form-urlencoded まで含めていることがよくあります。この2つは半角スペースの扱いが違い、前者では %20、後者では + になります。このページは3つの形を同時に出すので、迷ったら結果の見出しで選んでください。
日本語が %E3%81%82 のように3つ並ぶのはなぜですか
% のうしろの2桁は文字の番号ではなく、バイトの値だからです。UTF-8 という決まりでは、U+0800 から U+FFFF までの文字が3バイトになると RFC 3629 の表で決められています。ひらがな・カタカナ・CJK統合漢字はまるごとこの範囲に入ります。このページはその 21,183 文字を1つずつバイトにして数えていて、3バイト以外だったものは 0 件でした。「あ」は U+3042 で、バイトにすると E3 81 82。それを1バイトずつ %XX にして %E3%81%82 です。
空白が %20 になるときと + になるときがあるのはなぜですか
決まりが2つあって、どちらも正しいからです。URLの道の部分などで使うパーセントエンコーディング(RFC 3986)には + の特別扱いが無く、半角スペースは %20 になります。検索フォームなどが送るときに使う application/x-www-form-urlencoded は、1995年の RFC 1866 が空白を + にすると決めていて、いまの WHATWG URL Standard にもその規則が残っています。注意点が1つあります。戻すときは先に + を空白に直してから %XX をほどく決まりなので、%2B は空白ではなく + そのものに戻ります。
encodeURI と encodeURIComponent はどちらを使えばいいですか
URLを丸ごと渡すときは encodeURI、?q= のうしろに入れる値だけを渡すときは encodeURIComponent です。違いは、変換しない文字がちょうど 11 個ぶん多いか少ないかだけで、その文字は # $ & + , / : ; = ? @ 。どれもURLの区切り記号なので、丸ごと渡すときに化けさせると区画が読めなくなり、値だけ渡すときに残すと値がそこで切れます。0から127までを1文字ずつ通して数えると、そのまま残る文字は encodeURIComponent が71・encodeURI が82で、差はぴったり 11 でした。
%82%A0 を貼ったら「読めません」と出ました
それは Shift_JIS でバイトにされたものを、UTF-8 として読もうとしたためです。%XX はバイトの値でしかないので、どの文字コードでバイトにしたかが分からないと文字に戻せません。%82%A0 は Shift_JIS の「あ」で、UTF-8 の「あ」は %E3%81%82 です。2000年代の日本のサイトのURLには Shift_JIS のものが残っています。この道具は読めなかったときに空欄を返さず、何バイト目でつまずいたかを出して、実際に読めた文字コードとその結果を並べます。どれが読みたかったものかは、こちらでは決めません。
~ や ! が変換されないのは間違いですか
間違いではありませんが、古い決まりの名残です。JavaScript の encodeURIComponent は ! ' ( ) * - . _ ~ を変換せずに残します。これは1998年の RFC 2396 が「mark」としてこの9文字をそのまま使ってよいと決めていたためで、ECMA-262 の本文にも「この予約文字の集合は RFC 2396 にもとづいており、より新しい RFC 3986 の変更を反映していない」という但し書きが付いています。いまの RFC 3986 でそのまま置けるのは英数字と - . _ ~ の66種類だけ。フォームが送る形で残るのは * - . _ の4つだけです。この道具は3つの形を同時に出すので、どこが食い違うかが並べて見えます。
%2520 になってしまいました
2回エンコードが掛かっています。%20(半角スペース)をもう一度エンコードすると、先頭の % が %25 になって %2520 になります。1回ほどけば %20、2回ほどいてやっと空白です。RFC 3986 §2.4 は「実装は同じ文字列を2回以上エンコードしてもデコードしてもならない」と書いていて、データとしての % がエンコードの始まりと読み違えられるからだと理由も添えています。ただし2回ほどくのも危険で、%253F を2回ほどくと ? という区切り記号になってしまいます。この道具は %25 を見つけたら二重の可能性を文字で伝え、1回ほどいた結果と2回ほどいた結果の両方を並べます。勝手に片方を選びません。
ブラウザのアドレス欄では日本語のまま見えるのに、コピーすると %E3 で始まる並びになるのはなぜですか
見せている姿と、送っている姿が違うからです。実際に通信で送られているのは %XX の並びで、URL Standard が決めているのもその送る形のほうです。人が読みにくいので、ブラウザは画面に出すときだけ読める姿に直して見せています。どう見せるかは規格ではなくブラウザごとの工夫なので、ブラウザによって見え方が変わります。なお Google 検索セントラルは、URLに日本語の単語を使うこと自体はすすめたうえで、リンクを書くときは ASCII 以外の文字をパーセントエンコードする必要がある、としています。
貼った文字はどこかに送られますか
送られません。変換はすべてこの画面の中(お使いの機器の中)で行っていて、外の機械に問い合わせることもありません。文字数の上限もありません。同じことをするページの中には、入力をサーバーに送って処理し、1回あたりのバイト数に上限を設けていると自分で書いているものもあります。未公開のURLや社内の検索語をそのまま貼れるかどうかは、そこで変わります。
URLの中にそのまま書ける文字は、英数字62種と - . _ ~ を足した66種類だけです。それ以外は「%」と2桁の数字に 化けます。ASCII 128文字ぶんの早見表と、貼った文字の変換を、 同じ1枚に置きました。日本語1文字が %XX 3つになる理由も、 バイトを並べて見せます。
URLにそのまま書ける文字は、たった66種類しかない
URLの決まりを書いた RFC 3986 は、そのまま置いてよい文字をunreserved(予約されていない文字)として名指ししています ── 英字52・数字10・そして - . _ ~ の4つ、 合わせて66文字だけ。残りは2つに分かれます。
1つは区切りの役を持つ文字で、大きな区切りが # / : ? @ [ ] の7つ、 小さな区切りが ! $ & ' ( ) * + , ; = の11個。もう1つは、どちらの役も無くて居場所が無い11文字 ── 半角スペース " % < > \ ^ ` { | } です。
印字できるASCIIは95文字なので、66+7+11+11=95 でぴったり埋まります。 この足し算は条文の集合の定義から数えたもので、よそから写した数ではありません (単体テストが固定しています)。だから「URLを人に送ったら壊れた」の正体はいつも同じで、66種類の外にある文字が、化けないまま置かれています。
日本語1文字が %XX 3つになるのは、UTF-8が3バイトだから
% のうしろの2桁は文字番号ではなく、バイトの値です。UTF-8はコードポイントの大きさでバイト数を変えていて、 RFC 3629 の表では U+0080〜U+07FF が2バイト、U+0800〜U+FFFF が3バイト(1110xxxx 10xxxxxx 10xxxxxx)、 U+10000以上が4バイトと決まっています。
ひらがな(U+3041〜309F)・カタカナ(U+30A0〜30FF)・CJK統合漢字(U+4E00〜9FFF)は まるごと3バイトの範囲に入ります ── この3つの範囲の21,183文字を全部通して数え、 3バイト以外が0件であることを確かめました。 だから「あ」は U+3042 → E3 81 82 → %E3%81%82。1文字が9文字になります。絵文字はもう一段大きく、🦙(U+1F999)は4バイトで %F0%9F%A6%99 と4つ並びます。 上の道具は 文字ごとに「文字 → 文字番号 → バイト → %表記」の4段を並べて出すので、 なぜ3つなのかを自分で数えて確かめられます。
半角スペースが %20 になるときと + になるときがある
同じ半角スペースなのに、URLの道の部分では %20、 検索フォームが送るときは + になります。どちらかが間違いなのではなく、決まりが2つあるからです。 パーセントエンコーディング(RFC 3986)に + の 特別扱いは無く、空白は %20 になります。いっぽう HTMLのフォームが使う application/x-www-form-urlencoded は、1995年の RFC 1866 が 「space characters are replaced by +(空白は + に置き換える)」と決めていて、 いまの WHATWG URL Standard にも「spaceAsPlus が true なら 0x20 は U+002B (+) に する」という形で残っています。
ここに落とし穴があります。戻すときは、先に + を空白に直してから %XX をほどくのが決まりです(URL Standard のパーサの手順がその順番)。だから %2B はほどいた結果の + であって、空白にはなりません。順番を逆にすると 1%2B2+3 が「1 2 3」になり、足し算が消えます。上の道具は + を空白として読むかどうかを選べて、 どちらで読んだかを画面に出します。
encodeURI と encodeURIComponent の違いは、ちょうど11文字
JavaScriptの2つの関数は、変換しない文字の集合が違うだけです。ECMA-262 の Encode を読むと、どちらも英数字と ! ' ( ) * - . _ ~ を常に残し、encodeURI だけが追加で ;/?:@&=+$,# を残します (仕様の中にこの文字列がそのまま書いてあります)。
0から127までを1文字ずつ通して数えると、そのまま残る文字は encodeURIComponent が71・encodeURI が82で、差は ちょうど11 ── 条文と数が合います。 使い分けもここから決まります。URLを丸ごと渡すなら encodeURI(区切り記号まで 化けさせると壊れる)、?q= のうしろに入れる値なら encodeURIComponent(区切り記号を残すと値がそこで切れる)。
ただし ECMA-262 自身が「この予約文字の集合は RFC 2396 にもとづいており、より新しい RFC 3986 の変更を反映していない」と但し書きを付けています。! ' ( ) * - . _ ~ を残すのは1998年の古い規格の名残で、 いまのフォームの決まりで残るのは * - . _ の4つだけ。 上の早見表を右へ3列たどると、その食い違いが行ごとに見えます。
同じ「あ」でも %E3%81%82 と %82%A0 の2通りがある
%XX はバイトの値でしかないので、どの文字コードでバイトにしたかが決まらないと元の文字に戻せません。 RFC 3986 §2.5 は、新しい方式が文字を扱うときはまず UTF-8 でバイトにしてから %エンコードすべきだと書いていて、 その例としてカタカナの「ア」=%E3%82%A2 を 挙げています(この値も、手で書かずにこの道具に作らせています)。
しかし2000年代の日本のサイトは Shift_JIS でページを作っていたので、そのころのURLでは 同じ「あ」が %82%A0 になっています。EUC-JP なら %A4%A2。だから %82%A0 を UTF-8 として読もうとすると必ず失敗します。この道具は失敗を空欄で返しません。何バイト目が読めなかったかを言い、 実際に読めた文字コードとその結果を並べて、どれが読みたかったかを人に選んでもらいます。
読めてしまうことがあるのが、いちばん怖いところです。EUC-JP の 「あ」(%A4%A2)を Shift_JIS として読むと、 エラーにならずに半角カナ2文字になります。だから「この文字コードです」と 1つだけ名指しはせず、読めたものを全部並べています。 文字化けそのものを読み解きたいときは、文字化け復元の ページのほうが向いています。
? と & と # は区切りの役。文字として書きたいなら化けさせる
URLは記号で区画が分かれています。: と // のうしろが住所、? から先が問い合わせ、& が項目の切れ目、= が名前と値の境目、# から先はページの中の位置です。
だから値の中に & を素で書くと、そこで項目が切れます。 「トム&ジェリー」を検索語にしたつもりが「トム」と「ジェリー」の2項目として送られ、 受け取った側は「ジェリー」を知らない名前として捨ててしまう ── これが実際に起きる壊れ方です。文字として渡したいなら %26 に化けさせます。同じ理由で ? は %3F、# は %23、/ は %2F、= は %3D。そして % 自身は %25 です ── RFC 3986 §2.4 が「% は %エンコードの目印なので、データとして使うには %25 に しなければならない」と明記しています。
上の道具は貼られたURLを区画に割って、どの記号がいま区切りとして働いているかを、色ではなく文字の名札で示します。割るのは「英字ではじまる名前と :」がある文字列だけです。RFC 3986 の付録Bに載っている 正規表現はどんな文字列にも当たってしまうので、それだけで判断すると 「10:30」の「10」までしくみの名前だと言ってしまいます。 §3.1 の決まりを満たさないときは、当てずっぽうで割らずに「URLの形になっていません」と 言います。
2回エンコードすると %2520 になって、戻し方が1通りでなくなる
%20(半角スペース)をもう一度エンコードすると、 先頭の % が %25 に化けて %2520 になります。1回ほどけば %20、2回ほどいてやっと空白。プログラムの受け渡しで 「念のためもう一度」と掛けると、こうして二重になります。
RFC 3986 §2.4 は「実装は同じ文字列を2回以上エンコードしても、デコードしてもならない」 と書き、理由も添えています ── データとしての % が、 %エンコードの始まりと読み違えられるからです。逆に、深く考えずに2回ほどくのも 危険です。%253F を2回ほどくと ? になり、値だったはずのものが区切り記号に変わってしまいます。
だからこの道具は、貼られた文字列に %25 があれば 「二重の可能性があります」と文字で伝え、1回ほどいた結果と2回ほどいた結果を並べます。 勝手に2回ほどいて1つの答えを返すことはしません。
Googleは「ASCII以外の文字はパーセントエンコードを行う必要があります」と書いている
URLに日本語を使ってよいのか、という問いには、検索側の公式な答えがあります。 Google 検索セントラルの「URL構造のベストプラクティス」は、読み手の言語の単語をURLに使うことをすすめたうえで、リンクの href では「予約されていないASCII文字はエンコードされない 形式のまま残る可能性があります。さらに、ASCII以外の文字はパーセントエンコードを行う 必要があります」としています。
同じページに載っている例が 🦙✨ → %F0%9F%A6%99%E2%9C%A8 と gemüse → gem%C3%BCse で、 どちらもこの道具が出す値と一致します(絵文字2つで %XX が7つ ── 🦙 は4バイト、✨ は3バイト)。つまり「日本語のURLを使う」と「%エンコードする」は対立しません ──人が読む姿は日本語のまま、送る姿は %XX の並び、というのが正しい形です。 あわせて Google は、単語の区切りにアンダースコアではなくハイフンを使うようすすめています。_ も - も どちらも66文字の中にあって化けませんが、意味の伝わり方が違います。
文字をURLに置くためではなく、そのまま送れる形にまとめたいときはBase64のページのほうが向いています(あちらにも URLエンコードの変換が付いています)。バイトの値そのものを見たいときはn進数へどうぞ。
出どころ: RFC 3986(新しいタブで開きます)(§2.1 の大文字・§2.2 の区切り・§2.3 の unreserved・§2.4 の %25 と二重禁止・§2.5 の 「ア」の例・§3.1 のスキーム・付録B)、RFC 3629(新しいタブで開きます)(UTF-8のバイト割り当て表)、WHATWG URL Standard(新しいタブで開きます)(§1.3 の percent-encode set と、+ を先に空白へ直す段の順番)、ECMA-262 19.2.6(新しいタブで開きます)(encodeURI の ;/?:@&=+$,# と、RFC 2396 にもとづくという但し書き)、RFC 2396(新しいタブで開きます)(§2.3 の mark)、RFC 1866(新しいタブで開きます)(§8.2.1 の + と %0D%0A)、RFC 20(新しいタブで開きます)(制御文字33個の名前と、DELについての断り)、WHATWG Encoding Standard(新しいタブで開きます)(Shift_JIS の並べ方)、Google 検索セントラル「URL構造のベストプラクティス」(新しいタブで開きます)。 確かめられなかったこと ──【1】同じ題材の道具として 調べようとした tools.studioasari.co.jp の URLエンコードのページは、HTTP 404 で開けませんでした(404のページが返ります)。だからそこを根拠にした記述は1つも書いていません。【2】RFC 3986 の正誤表に、§2.3 の unreserved にバックスラッシュが抜けているのではという指摘 (Errata ID 9147・2026年8月27日報告)が出ていますが、まだ受理されていない(Status: Reported)ので、 この表の66種類は動かしていません。規格が変わったわけではありません。 【3】Shift_JIS の並びを確かめるのに使った WHATWG の索引データそのものは、 転載の条件が付くのでこのサイトには置いていません ── 変換は お使いのブラウザが持っている表から作っています。数(66・7・11・11・33・71・82・66・21,183)は、このページがその場で数えたもので、よそから写した数字は1つもありません。