文字與開發者 指南
URL 編碼是什麼?%20、+、%2F、中文網址與 encodeURIComponent 完整指南
URL 中的空格、&、=、#、斜線都有語法角色,真正的重點不是全部編碼,而是編對 component。
更新日期:
你可能看過 hello%20world、%E5%8F%B0%E7%81%A3 或 q=hello+world。這些都和 URL encoding 有關,但 %20 和 + 並不是在所有位置都完全等價。
速答:URL 編碼是什麼? URL percent-encoding 會把不能直接或不應直接出現在某個 URI component 的 bytes 表示成
%HH。空格常見為%20;UTF-8 中文會先轉成 UTF-8 bytes,再逐 byte percent-encode。Query form encoding 中,URLSearchParams序列化空格時常使用+。最安全的做法是只編碼參數值或特定 component,不要把完整https://...?...整條網址無差別丟進encodeURIComponent(),也不要重複編碼。
一、什麼是 Percent-Encoding?
形式:
%HH
HH 是一個 byte 的 16 進位值。
ASCII space 是 hex 20,所以常見為 %20。
二、中文為什麼變成很多 %E5...?
中文是 Unicode。常見流程是:
Unicode → UTF-8 bytes → Percent-Encoding
一個中文字在 UTF-8 通常不只一個 byte,所以會看到數個 %HH。
三、%20 是什麼?
通常代表空格。
hello world
可表示為:
hello%20world
四、那 + 也是空格嗎?
在 application/x-www-form-urlencoded 與 URLSearchParams query serialization 中,space 常序列化為 +。
所以:
q=hello+world
常被解析為 hello world。
但不要把這個規則套到 URL 所有位置。
五、真正的 Plus 號怎麼辦?
如果 value 真的是 C++,form-style parser 可能把 + 當空格。
真正 plus 可 percent-encode 為:
%2B
例如:
q=C%2B%2B
六、%2F 是什麼?
Slash /。
Slash 在 path 裡常有結構意義,例如:
/users/123
如果 slash 是資料值的一部分,是否 encode 要看它所在 component 與 server routing。
七、%3F、%26、%3D、%23
| 字元 | 常見 encoded | URL 中常見角色 |
|---|---|---|
? |
%3F |
query 起點 |
& |
%26 |
query parameter 分隔 |
= |
%3D |
key/value 分隔 |
# |
%23 |
fragment 起點 |
如果 value 本身含這些字元,就要避免它們被誤認成 URL 結構。
八、為什麼 A&B 必須注意?
如果 query 是:
?name=A&B
parser 可能把 B 當下一個 parameter。
若 value 本身是 A&B,應安全表示成:
A%26B
九、# 為什麼常造成參數被截掉?
URL 中 # 後面通常是 fragment,而且 fragment 通常不會作為 HTTP request query 傳給 server。
如果 query value 本身含 #,應正確 encode 為 %23。
十、encodeURIComponent() 適合什麼?
JavaScript:
encodeURIComponent(value)
主要適合單一 URI component,例如 query parameter value。
encodeURIComponent("A&B")
可以避免 & 被誤解為 parameter separator。
十一、為什麼不應把整條網址丟 encodeURIComponent?
原網址:
https://example.com/search?q=hello
整條編碼後:
https%3A%2F%2Fexample.com%2Fsearch%3Fq%3Dhello
這已不是可直接導覽的完整 URL,而是「被編碼的一段字串」。
十二、encodeURI() 與 encodeURIComponent() 差別
概念上:
encodeURI()保留較多 URL 結構字元;encodeURIComponent()對單一 component 更積極。
但在現代 JavaScript 中,通常更推薦使用 URL / URLSearchParams API 正確組裝網址,而不是手動串字串。
十三、URLSearchParams 的好處
const params = new URLSearchParams();
params.set("q", "C++ & 台灣");
你提供未編碼值,API 會處理 query serialization。
不要先自己 encode,再丟進 URLSearchParams,否則可能 double encode。
十四、Double Encoding 是什麼?
原始:
hello world
第一次:
hello%20world
第二次把 % 又 encode:
hello%2520world
因為 %25 就是 %。
常見症狀:
%252F%2520%253A
十五、怎麼判斷是否 encode 兩次?
你預期 %2F,卻看到 %252F,通常表示 %2F 這串文字本身又被 encode。
十六、Decode 也可能報錯
不完整 percent sequence:
%
%2
%GG
decoder 可能失敗。不要對任何任意字串無條件 decode。
十七、URL Decode 不代表安全
Decode 只是把內容變可讀,不會:
- 驗證 domain;
- 檢查 phishing;
- 判斷 malware;
- 驗證 redirect。
未知連結仍需檢查。
十八、不要把 Secret 放 Query String
即使 encode 後看起來像亂碼,secret 仍可能進入:
- browser history;
- server logs;
- analytics;
- referrer;
- proxy logs。
Encoding ≠ Encryption。
十九、常見表
| 字元 | Encoded |
|---|---|
| space | %20 |
+ |
%2B |
/ |
%2F |
? |
%3F |
& |
%26 |
= |
%3D |
# |
%23 |
% |
%25 |
二十、推薦 Debug 流程
- 取得原始未編碼 value。
- 確認它位於 path、query 還是 fragment。
- 使用 URL / URLSearchParams。
- 只 encode 一次。
- 看 Network tab 的 final request。
- Server 端確認實際收到的值。
- 看見
%25疊加時檢查 double encoding。
二十一、path、query 與 fragment 的差別
同一個字元放在 URL 不同位置,責任也不同。path 通常代表資源階層,query 是傳給伺服器的參數,fragment 則由瀏覽器在收到頁面後處理。不要把整條已經含有 ?、& 的網址當成一個 query value 再 encode;應先組合結構,再對每個 value 編碼。這樣才能保留分隔符的功能,也能避免 %3F、%26 出現在錯誤層級。
測試時準備包含空格、中文、斜線、問號、井號與百分比符號的資料。送出後在瀏覽器 Network tab 查看實際 request URL,再在伺服器端確認收到的值。若來源資料本身可能已經編碼,先標記它的狀態並只解碼一次,否則 double encoding 會讓錯誤一路累積。
還要特別區分「顯示文字」與「傳輸值」。網址列可能把字元重新顯示成可讀形式,開發者工具也可能提供 decode 後的預覽,因此除錯時應同時記錄原始 value、組合後的 URL,以及伺服器解析出的參數。對搜尋、登入或檔案名稱等敏感流程,則要另外確認 encode 之後沒有改變大小寫、斜線或保留字元的語意,並測試空值與超長值的邊界行為。
二十二、FAQ
%20 是空格嗎?
通常是 percent-encoded space。
+ 一定是空格嗎?
不一定;在 form-style query parsing 中常代表 space。
%2F 是什麼?
Slash /。
為什麼看到 %252F?
常見原因是 %2F 又被 encode 一次。
URL encoding 是加密嗎?
不是,可以解碼。
二十三、延伸閱讀
下一步
要編碼的是 query value,不是整條網址? 把單一 component 放進 FunnyTools URL 編碼工具;如果你正在寫程式,優先用 URL / URLSearchParams。
重點速記
Raw value → Identify component → Percent encode once → Build URL → Verify request