¿Un valor o una dirección entera?
Los dos modos se diferencian en cinco caracteres: &, =, ?, / y #.
Un valor los escapa todos. Úsalo para lo que va dentro de un parámetro: un término de búsqueda, un destino de redirección. Pon una URL sin escapar detrás de ?next= y el & que lleva dentro se leerá como el comienzo de un parámetro nuevo, cortando tu valor.
Dirección entera deja intactos los caracteres estructurales. Sirve cuando ya tienes una URL que funciona y solo quieres limpiar espacios y caracteres no ASCII. Al pasar una dirección completa por este modo, las barras de https:// sobreviven y el enlace sigue funcionando.
Una regla lo resuelve: si estás construyendo parte de una dirección, un valor; si ya tienes la dirección, dirección entera.
Espacios: ¿+ o %20?
Verás los dos, pero pertenecen a sitios distintos. %20 es la forma estándar y vale en cualquier punto de una URL. + viene de la codificación antigua de formularios HTML y solo cuenta como espacio dentro de una query string.
Un + en la ruta es un signo más literal. Si decodificas un nombre de archivo con las reglas de formulario, lo renombras sin darte cuenta. Esta herramienta sigue el estándar y produce %20.
Valores codificados dos veces
Si al decodificar te queda %2520 o %253A, el valor se codificó dos veces: en la segunda pasada el propio % se convirtió en %25.
Suele pasar cuando el código codifica un valor que ya venía codificado. Decodificar otra vez te devuelve el texto, pero el arreglo de verdad es decidir dónde se codifica: una sola vez, en el punto donde el valor entra en la URL, y texto plano en todo lo demás.
Caracteres que no cambian
A-Z, a-z, 0-9 y -, ., _, ~ forman el conjunto no reservado: la especificación los marca como seguros y pasan tal cual. Verlos sin cambios no es un fallo.
Los caracteres no ASCII se expanden: una vocal acentuada ocupa dos bytes UTF-8, un carácter chino tres y un emoji cuatro, y cada byte se convierte en un par %XX. Por eso una dirección codificada se ve de pronto tan larga.