Giải mã URL

Dán một URL hay query string đã mã hóa phần trăm để lấy lại văn bản gốc, kèm bảng liệt kê từng key và value tách riêng.

File không bao giờ rời khỏi thiết bị của bạn

Component mã hóa gần như mọi ký tự, dùng cho một giá trị riêng lẻ. URI đầy đủ giữ nguyên các ký tự đặc biệt như / và ?. Form còn đổi dấu cách thành +.

Chuỗi mã hóa phần trăm ẩn ở ba nơi: cả một URL, một giá trị riêng lẻ, và một query string ghép từ nhiều giá trị. Trang này đọc ngược cả ba, từng byte một, và tách query thành các cặp key/value để bạn không phải tự dò từng dấu &.

Đọc một escape bằng tay

Một bộ ba phần trăm là một byte viết dưới dạng hex: %20 là byte 0x20, dấu cách. %2B0x2B, dấu cộng thật. Ký tự nhiều byte cần nhiều bộ ba hơn — %E1%BA%BF là ba byte ghép thành một ký tự UTF-8, chữ ế. Đặt cạnh chữ ASCII, Ti%E1%BA%BFng%20Vi%E1%BB%87t giải mã ra Tiếng Việt: chữ ASCII đi qua nguyên vẹn, mỗi chữ có dấu tốn ba bộ ba, %20 thành dấu cách giữa hai từ.

Chọn chế độ Component, Full URI hay Form

Ba chế độ giải mã một lượng ký tự khác nhau, chọn sai chế độ thì hoặc escape bị bỏ sót, hoặc cấu trúc vốn không nên đụng vào lại bị phá. Component giải mã mọi ký tự đã mã hóa mà nó nhận ra, phù hợp cho một giá trị đơn lẻ đứng riêng — một tham số query, một đoạn path, một cookie. Full URI dành cho cả một địa chỉ dán nguyên khối: nó cố tình giữ nguyên dạng đã mã hóa của / ? # & = + $ , : ; @, để một dấu / từng bị mã hóa hợp lệ bên trong tên file (%2F) không bị giải mã ngược thành dấu / thật rồi bị đọc nhầm thành một đoạn path mới. Form hoạt động như Component nhưng đọc thêm dấu + thành dấu cách, đúng cách một trình duyệt mã hóa dữ liệu form HTML khi gửi đi — dùng chế độ này cho bất cứ thứ gì đến từ một body application/x-www-form-urlencoded hay một query string, vì dấu + thật không còn cách nào khác để sống sót qua vòng mã hóa đó.

Hai kiểu lỗi khi giải mã

100% lỗi ngay ký tự cuối — không có gì theo sau dấu % để đọc thành chữ số hex thứ hai. 50%2 off lỗi sớm hơn một ký tự, ngay tại dấu %, vì %2 tiếp theo là dấu cách chứ không phải chữ số hex. Cả hai báo là chuỗi percent-encode không hợp lệ, kèm đúng vị trí dấu % gây lỗi.

Kiểu lỗi thứ hai xảy ra khi escape đúng cú pháp nhưng byte tạo ra không ghép thành văn bản hợp lệ. %E1 một mình mở đầu một ký tự UTF-8 ba byte mà không có byte tiếp theo — không có văn bản nào để tạo ra. %FF%FE cùng kiểu. Cả hai báo không phải UTF-8 hợp lệ: byte chưa từng là văn bản, không phải bạn gõ sai.

Mẹo: Vị trí 0 trong lỗi escape hỏng luôn đếm từ đầu đúng những gì bạn đã dán — nếu bạn dán cả một URL, hãy đếm từ ký tự đầu tiên, không phải từ chỗ query string bắt đầu.

Tách một query string

Dán https://example.com/search?q=hello+world&lang=vi#frag vào, bảng bên dưới hiện hai dòng: qhello world, langvi. Path trước dấu ?#frag sau đó đều bị bỏ qua — cả hai không thuộc query — còn dấu + trong hello+world giải mã ra dấu cách, theo quy ước form.

Một query string cũng có nhiều cách viết khác nhau mà vẫn hợp lệ: dấu cách có thể viết là + hay %20, còn dấu . giải mã ra giống hệt nhau dù có bị mã hóa thành %2E hay không — nên viết lại một chuỗi từ các mảnh đã giải mã có thể trông khác chuỗi bạn từng dán, dù mang đúng ý nghĩa.

Câu hỏi thường gặp

Lỗi "chuỗi percent-encode không hợp lệ" nghĩa là gì?
Nghĩa là một dấu % trong chuỗi bạn dán không có đủ hai chữ số hex đi kèm — bản thân chuỗi mã hóa bị sai cú pháp. `100%` lỗi vì không có gì sau dấu %; `50%2 off` lỗi vì %2 tiếp theo là dấu cách chứ không phải chữ số hex thứ hai. Thông báo lỗi nêu đúng vị trí ký tự % gây lỗi, để bạn tìm ra ngay chứ không phải dò cả chuỗi.
Lỗi "không phải UTF-8 hợp lệ" khác lỗi escape hỏng thế nào?
Đây là trường hợp cú pháp hoàn toàn ổn — mọi dấu % đều có đủ hai chữ số hex — nhưng các byte mà những bộ ba đó tạo ra không ghép thành văn bản UTF-8 hợp lệ. `%E1` một mình là ví dụ: một byte mở đầu chuỗi UTF-8 ba byte nhưng không có byte tiếp theo, nên không có ký tự nào để giải mã ra. Escape hỏng là lỗi gõ trong cách mã hóa; UTF-8 không hợp lệ là byte chưa từng là văn bản ngay từ đầu.
Vì sao dấu + trong chuỗi tôi dán lại biến thành dấu cách?
Chỉ khi chuỗi trông giống một query string hay bạn đang ở chế độ form — trong ngữ cảnh đó dấu + luôn nghĩa là dấu cách, đúng quy ước một form HTML dùng khi gửi đi. Ở chế độ component hay URI đầy đủ, dấu + giải mã ra đúng dấu +, vì quy ước đổi dấu cách chỉ áp dụng cho dữ liệu form-urlencoded.
Nếu cùng một key xuất hiện hai lần, như `a=1&a=2`, thì sao?
Cả hai dòng đều hiện ra. Bộ tách không gộp hay loại trùng key — một query string vốn được phép lặp key, giống cách một nhóm checkbox hay ô chọn nhiều giá trị hoạt động — nên mọi cặp hiện đúng như bạn đã dán, theo đúng thứ tự.
Vì sao dán cả một URL vào chỉ hiện ra phần query?
Vì phần query thường là thứ bạn thật sự muốn đọc. Dán cả địa chỉ vào, mọi thứ trước dấu ? và sau dấu # đều bị bỏ qua — path và fragment không thuộc về query, để lọt vào sẽ làm hỏng giá trị cuối cùng. Dán một query string trần không có dấu ? thì được đọc thẳng, không cần cả địa chỉ.
Văn bản tôi dán vào đây có bị gửi lên đâu không?
Không. Việc giải mã chạy bằng JavaScript ngay trong tab trình duyệt, ngay khi bạn gõ hay dán, và không có request nào mang văn bản rời khỏi máy. Điều này quan trọng khi thứ bạn đang giải mã là một session token, một link nội bộ, hay query string bạn không muốn đưa lên server chỉ để đọc.
Sao không gộp hai lỗi trên thành một thông báo chung?
Vì chúng chỉ tới hai cách sửa khác nhau. Escape hỏng nghĩa là hãy tìm dấu % và sửa lại chữ số sau nó — vị trí báo ra chính xác chỗ cần sửa. UTF-8 không hợp lệ nghĩa là các byte bên dưới vốn không phải văn bản, thường vì bạn dán nhầm dữ liệu nhị phân tình cờ chứa ký tự %.