Cómo decodificar una URL en JavaScript (guía completa)
JavaScript ofrece decodeURIComponent() para decodificar componentes individuales de un URI y decodeURI() para decodificar URIs completos. Usa try-catch para gestionar URIs malformados. Las APIs URL y URLSearchParams ofrecen alternativas más seguras para analizar URLs.
decodeURIComponent() — Decodificar un componente de URI
decodeURIComponent() es la función principal para decodificar cadenas codificadas en URL en JavaScript. Decodifica todas las secuencias percent-encoded, convirtiéndolas de nuevo a sus caracteres originales. Usa esta función cuando decodifiques valores de parámetros de consulta, segmentos de ruta o cualquier componente individual de un URI.
// Decodificación básica
console.log(decodeURIComponent('hello%20world'));
// "hello world"
console.log(decodeURIComponent('price%3D10%26qty%3D2'));
// "price=10&qty=2"
// Decodificar caracteres Unicode
console.log(decodeURIComponent('caf%C3%A9'));
// "cafe" (con acento)
console.log(decodeURIComponent('%E4%B8%AD%E6%96%87'));
// Caracteres chinos
// Decodificar el valor de un parámetro de consulta de una URL
const url = 'https://example.com/search?q=C%2B%2B%20%26%20Java';
const params = url.split('?')[1];
const value = params.split('=')[1];
console.log(decodeURIComponent(value));
// "C++ & Java"
decodeURIComponent() decodifica todas las secuencias percent-encoded, incluidas las que corresponden a caracteres reservados como %2F (/) y %3F (?). Este es el comportamiento correcto cuando se trabaja con componentes individuales de un URI, pero puede causar problemas si se aplica a una URL completa.
decodeURI() — Decodificar un URI completo
decodeURI() decodifica un URI completo preservando su estructura. A diferencia de decodeURIComponent(), no decodifica las secuencias que representan caracteres reservados del URI, como %2F (/), %3F (?), %23 (#) y %26 (&).
// decodeURI preserva la estructura del URI
console.log(decodeURI('https://example.com/my%20page?q=hello%20world'));
// "https://example.com/my page?q=hello world"
// Los espacios se decodifican, pero /, ? y = se preservan
// Compáralo con decodeURIComponent sobre una URL completa
console.log(decodeURIComponent('https%3A%2F%2Fexample.com%2Fpath'));
// "https://example.com/path" - decodifica correctamente si toda la URL estaba codificada
// decodeURI no decodifica las secuencias de caracteres reservados
console.log(decodeURI('path%2Fto%2Ffile'));
// "path%2Fto%2Ffile" - %2F NO se decodifica porque / es un carácter reservado
console.log(decodeURIComponent('path%2Fto%2Ffile'));
// "path/to/file" - %2F SÍ se decodifica
Usa decodeURI() cuando quieras hacer una URL más legible (por ejemplo, para mostrarla) sin alterar su estructura. Para la mayoría de los casos de uso programático, querrás usar decodeURIComponent() aplicado a componentes individuales.
Gestionar URIs malformados
Tanto decodeURI() como decodeURIComponent() lanzan un URIError cuando encuentran secuencias percent-encoded inválidas. Esto ocurre con signos de porcentaje sueltos, secuencias incompletas o secuencias de bytes UTF-8 inválidas. Envuelve siempre las operaciones de decodificación en un bloque try-catch cuando trabajes con URLs proporcionadas por el usuario o externas.
// Estos lanzan URIError: URI malformed
try {
decodeURIComponent('%'); // porcentaje suelto
} catch (e) {
console.error(e.message); // "URI malformed"
}
try {
decodeURIComponent('%2'); // secuencia incompleta
} catch (e) {
console.error(e.message); // "URI malformed"
}
// Función de decodificación segura
function safeDecode(str) {
try {
return decodeURIComponent(str);
} catch (e) {
console.warn('Failed to decode:', str);
return str; // devuelve la cadena original en caso de fallo
}
}
// Corregir secuencias de porcentaje malformadas antes de decodificar
function fixAndDecode(str) {
// Reemplaza los % sueltos por %25 (signo de porcentaje codificado)
const fixed = str.replace(/%(?![0-9A-Fa-f]{2})/g, '%25');
return decodeURIComponent(fixed);
}
console.log(fixAndDecode('100% complete'));
// "100% complete"
Usar la API URL (recomendado)
Las modernas APIs URL y URLSearchParams ofrecen una forma más segura y estructurada de analizar y decodificar URLs. Gestionan la codificación y decodificación de forma automática, reduciendo el riesgo de errores.
// Analiza una URL y accede a sus componentes (decodificados automáticamente)
const url = new URL('https://example.com/path%20here?q=hello%20world&lang=en');
console.log(url.pathname); // "/path here" (decodificado)
console.log(url.search); // "?q=hello%20world&lang=en" (sin procesar)
// URLSearchParams decodifica automáticamente los valores de los parámetros
console.log(url.searchParams.get('q')); // "hello world"
console.log(url.searchParams.get('lang')); // "en"
// Itera sobre todos los parámetros
for (const [key, value] of url.searchParams) {
console.log(key, '=', value);
}
// q = hello world
// lang = en
// URLSearchParams interpreta + como espacio (codificación de formularios)
const formParams = new URLSearchParams('q=hello+world&lang=en');
console.log(formParams.get('q')); // "hello world"
// Construir URLs con codificación automática
const newUrl = new URL('https://example.com/search');
newUrl.searchParams.set('q', 'C++ & Java');
newUrl.searchParams.set('page', '1');
console.log(newUrl.toString());
// "https://example.com/search?q=C%2B%2B+%26+Java&page=1"
Errores comunes al decodificar
Error 1: Decodificar una URL completa con decodeURIComponent(). Esto puede romper la estructura de la URL si contiene caracteres reservados codificados. Un %2F dentro del valor de una consulta se convertiría en un /, lo que podría cambiar el significado de la URL.
Error 2: Doble decodificación. Si una cadena ya se ha decodificado una vez, decodificarla de nuevo puede producir resultados inesperados o errores. Por ejemplo, la cadena %2520 se decodifica primero a %20 y luego a un espacio. Si solo esperas un nivel de codificación, la doble decodificación corrompe los datos.
// Problema de la doble decodificación
const encoded = '%2520'; // Esto es un %20 codificado
console.log(decodeURIComponent(encoded)); // "%20" (correcto - un nivel)
console.log(decodeURIComponent(decodeURIComponent(encoded))); // " " (¡doblemente decodificado!)
// Comprueba si una cadena necesita decodificarse antes de hacerlo
function needsDecoding(str) {
return str !== decodeURIComponent(str);
}
Error 3: No gestionar el signo +. decodeURIComponent() no convierte + en espacios. Si estás decodificando datos con codificación form-urlencoded, debes reemplazar primero los + por espacios, o usar URLSearchParams, que lo gestiona automáticamente.
// decodeURIComponent NO decodifica + como espacio
console.log(decodeURIComponent('hello+world'));
// "hello+world" (¡no "hello world"!)
// Solución: reemplaza + antes de decodificar
function decodeFormValue(str) {
return decodeURIComponent(str.replace(/\+/g, ' '));
}
console.log(decodeFormValue('hello+world'));
// "hello world"
// O usa URLSearchParams (gestiona + automáticamente)
const params = new URLSearchParams('q=hello+world');
console.log(params.get('q'));
// "hello world"