¿Has visto %20, %3A o %2F en una URL? Son caracteres codificados en porcentaje — el mecanismo que permite a las URL transportar caracteres especiales de forma segura. Esta guía explica exactamente cómo funciona la codificación URL.
Prueba nuestro codificador/decodificador URL para codificar o decodificar cualquier cadena →
¿Qué es la codificación URL (Percent Encoding)?
La codificación URL, llamada formalmente percent encoding, es un mecanismo definido en la RFC 3986 para representar caracteres no permitidos o con significado especial en una URI.
Las URL solo pueden contener un conjunto limitado de caracteres ASCII. Se dividen en caracteres reservados (con significado estructural como /, ?, &) y no reservados (letras, dígitos, -, _, ., ~).
Un espacio (ASCII 32, hex 0x20) se convierte en %20. Dos puntos (ASCII 58, hex 0x3A) se convierte en %3A.
// URL encoding in action
Original: https://example.com/search?q=hello world&lang=en
Encoded: https://example.com/search?q=hello%20world&lang=en
// Reserved characters and their encoded forms:
// space → %20 : → %3A / → %2F
// ? → %3F & → %26 = → %3D
// # → %23 + → %2B @ → %40Tabla de referencia de caracteres codificados
Tabla de referencia rápida de los caracteres más comúnmente codificados.
| Carácter | Codificado | Nombre / Uso |
|---|---|---|
(space) | %20 | Space |
& | %26 | Ampersand / query separator |
? | %3F | Question mark / query start |
/ | %2F | Forward slash / path separator |
: | %3A | Colon / scheme separator |
= | %3D | Equals / key-value separator |
# | %23 | Hash / fragment identifier |
+ | %2B | Plus sign (space in forms) |
@ | %40 | At sign / userinfo separator |
% | %25 | Percent (the escape char itself) |
! | %21 | Exclamation mark |
" | %22 | Double quote |
< | %3C | Less than |
> | %3E | Greater than |
{ | %7B | Left curly brace |
} | %7D | Right curly brace |
[ | %5B | Left square bracket |
] | %5D | Right square bracket |
| | %7C | Pipe / vertical bar |
\ | %5C | Backslash |
Cómo funciona la codificación URL (paso a paso)
El proceso sigue tres pasos: (1) tomar el carácter, (2) convertirlo a secuencia de bytes UTF-8, (3) codificar cada byte como %XX.
Veamos varios ejemplos:
// Step-by-step: How characters become percent-encoded
// Example 1: ASCII character (space)
// Character: " " (space)
// ASCII code: 32 → hex: 0x20
// Encoded: %20
// Example 2: ASCII character (ampersand)
// Character: "&"
// ASCII code: 38 → hex: 0x26
// Encoded: %26
// Example 3: Multi-byte UTF-8 (accented letter)
// Character: "é"
// Unicode: U+00E9
// UTF-8 bytes: 0xC3 0xA9 (2 bytes)
// Encoded: %C3%A9
// Example 4: Multi-byte UTF-8 (Chinese character)
// Character: "中"
// Unicode: U+4E2D
// UTF-8 bytes: 0xE4 0xB8 0xAD (3 bytes)
// Encoded: %E4%B8%AD
// Example 5: Multi-byte UTF-8 (emoji)
// Character: "🚀"
// Unicode: U+1F680
// UTF-8 bytes: 0xF0 0x9F 0x9A 0x80 (4 bytes)
// Encoded: %F0%9F%9A%80Los lenguajes modernos manejan esto automáticamente. Usa las funciones integradas o nuestra herramienta en línea.
Codifica y decodifica con nuestro URL Encoder →
encodeURI vs encodeURIComponent en JavaScript
JavaScript proporciona dos funciones de codificación URL. Elegir la incorrecta es una fuente común de errores.
encodeURI() codifica una URI completa preservando caracteres estructurales.
// encodeURI() — preserves URL structure
const url = 'https://example.com/path name?q=hello world';
encodeURI(url);
// → "https://example.com/path%20name?q=hello%20world"
// ✓ :// / ? = are NOT encoded (structure preserved)encodeURIComponent() codifica un componente de URI, incluyendo caracteres estructurales como & = + /.
// encodeURIComponent() — encodes everything for use as a value
const value = 'price=100&discount=20%';
encodeURIComponent(value);
// → "price%3D100%26discount%3D20%25"
// ✓ = & % ARE encoded (they're data, not structure)
// Correct pattern: build URL piece by piece
const base = 'https://api.example.com/search';
const query = 'Tom & Jerry: The Movie';
const fullUrl = base + '?q=' + encodeURIComponent(query);
// → "https://api.example.com/search?q=Tom%20%26%20Jerry%3A%20The%20Movie"Regla: Usa siempre encodeURIComponent() para valores de parámetros de consulta.
// Comparison table — which characters get encoded?
//
// Character encodeURI() encodeURIComponent()
// ───────── ─────────── ────────────────────
// space %20 %20
// / / (kept) %2F (encoded)
// ? ? (kept) %3F (encoded)
// & & (kept) %26 (encoded)
// = = (kept) %3D (encoded)
// # # (kept) %23 (encoded)
// : : (kept) %3A (encoded)
// + + (kept) %2B (encoded)
// @ @ (kept) %40 (encoded)
// é %C3%A9 %C3%A9
// 中 %E4%B8%AD %E4%B8%ADCodificación URL en diferentes lenguajes
Cada lenguaje principal tiene funciones integradas para codificación URL:
JavaScript
// JavaScript — encodeURIComponent / URLSearchParams
// Encode a query parameter value
encodeURIComponent('hello world&key=val');
// → "hello%20world%26key%3Dval"
// Decode
decodeURIComponent('hello%20world%26key%3Dval');
// → "hello world&key=val"
// URLSearchParams (auto-encodes, uses + for spaces)
const params = new URLSearchParams({ q: 'Tom & Jerry', page: '1' });
params.toString(); // → "q=Tom+%26+Jerry&page=1"Python
# Python 3 — urllib.parse
from urllib.parse import quote, quote_plus, unquote, urlencode
# Path encoding (spaces → %20)
quote('hello world/file') # → "hello%20world/file"
quote('hello world/file', safe='') # → "hello%20world%2Ffile"
# Query value encoding (spaces → +)
quote_plus('hello world&key=val') # → "hello+world%26key%3Dval"
# Build query string from dict
urlencode({'q': 'Tom & Jerry', 'page': '1'})
# → "q=Tom+%26+Jerry&page=1"
# Decode
unquote('%E4%B8%AD%E6%96%87') # → "中文"Java
// Java — URLEncoder (spaces → +)
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
String encoded = URLEncoder.encode(
"hello world&key=val", StandardCharsets.UTF_8
);
// → "hello+world%26key%3Dval"
String decoded = URLDecoder.decode(encoded, StandardCharsets.UTF_8);
// → "hello world&key=val"Go
// Go — net/url package
package main
import "net/url"
// Query value encoding (spaces → +)
url.QueryEscape("hello world&key=val")
// → "hello+world%26key%3Dval"
// Path segment encoding (spaces → %20)
url.PathEscape("hello world/file")
// → "hello%20world%2Ffile"
// Build URL safely with url.Values
vals := url.Values{}
vals.Set("q", "Tom & Jerry")
vals.Encode() // → "q=Tom+%26+Jerry"PHP
<?php
// PHP — urlencode (spaces → +) / rawurlencode (spaces → %20)
urlencode('hello world&key=val');
// → "hello+world%26key%3Dval"
rawurlencode('hello world&key=val');
// → "hello%20world%26key%3Dval"
http_build_query(['q' => 'Tom & Jerry', 'page' => 1]);
// → "q=Tom+%26+Jerry&page=1"
urldecode('hello%20world'); // → "hello world"
?>Ruby
# Ruby — CGI / URI
require 'cgi'
require 'uri'
CGI.escape('hello world&key=val')
# → "hello+world%26key%3Dval"
URI.encode_www_form('q' => 'Tom & Jerry', 'page' => '1')
# → "q=Tom+%26+Jerry&page=1"
CGI.unescape('hello%20world') # → "hello world"Errores comunes de codificación URL
1. Doble codificación
Ocurre al codificar una cadena ya codificada. %20 se convierte en %2520. Codifica siempre una sola vez.
// Double encoding — a very common bug
const value = 'hello world';
const encoded = encodeURIComponent(value); // "hello%20world"
// BUG: encoding again
encodeURIComponent(encoded);
// → "hello%2520world" (%20 → %25 + 20)
// Server decodes to "%20" (literal) instead of " " (space)
// FIX: encode raw values exactly once2. Codificar la URL completa
Pasar una URL completa a encodeURIComponent() rompe la estructura. Solo codifica valores individuales.
// WRONG: encoding entire URL
encodeURIComponent('https://example.com/api?q=test');
// → "https%3A%2F%2Fexample.com%2Fapi%3Fq%3Dtest" (broken!)
// CORRECT: encode only the parameter value
'https://example.com/api?q=' + encodeURIComponent('test value');
// → "https://example.com/api?q=test%20value"3. Espacio: + vs %20
Los formularios HTML usan +. RFC 3986 usa %20. Para APIs, prefiere %20.
// Space encoding: + vs %20
// HTML form submission (application/x-www-form-urlencoded):
// "hello world" → "hello+world"
// RFC 3986 (URI standard):
// "hello world" → "hello%20world"
// JavaScript functions:
encodeURIComponent('hello world'); // → "hello%20world" (RFC 3986)
new URLSearchParams({q: 'hello world'}).toString(); // → "q=hello+world" (form)4. No codificar valores de parámetros
No codificar valores del usuario es un riesgo de seguridad y causa URLs rotas.
// Missing encoding breaks URLs
const search = 'Tom & Jerry';
// WRONG: unencoded & splits the value
'/search?q=' + search;
// → "/search?q=Tom & Jerry"
// Server sees: q="Tom " and Jerry="" (two params!)
// CORRECT: encode the value
'/search?q=' + encodeURIComponent(search);
// → "/search?q=Tom%20%26%20Jerry"
// Server sees: q="Tom & Jerry" (one param)Mejores prácticas para codificación URL
Siempre codifica la entrada del usuario antes de insertarla en cadenas de consulta o segmentos de ruta.
Usa funciones de biblioteca en lugar de reemplazo manual.
Prueba con caracteres especiales: & = ? / # + % y caracteres no-ASCII.
Usa Base64 URL-safe para datos binarios en URLs.
// Best practice: use URL / URLSearchParams API
const url = new URL('https://api.example.com/search');
url.searchParams.set('q', 'Tom & Jerry: The Movie');
url.searchParams.set('lang', 'en');
url.toString();
// → "https://api.example.com/search?q=Tom+%26+Jerry%3A+The+Movie&lang=en"
// All encoding handled automatically!
// URL-safe Base64 (avoids + and / in URLs)
// Standard: "SGVsbG8gV29ybGQ=" (may contain + / =)
// URL-safe: "SGVsbG8gV29ybGQ" (uses - _ instead)Preguntas frecuentes
¿Por qué el espacio se codifica como %20?
El espacio tiene código ASCII 32, que es 0x20 en hexadecimal. El percent encoding representa un byte como % seguido de su valor hex.
¿Cuál es la diferencia entre + y %20?
%20 viene de RFC 3986. + viene del formato de formularios. %20 es más universal.
¿Necesito codificar la URL completa?
No. Solo codifica componentes individuales. Los caracteres estructurales deben permanecer sin codificar.
¿Diferencia entre encodeURI y encodeURIComponent?
encodeURI() preserva caracteres estructurales. encodeURIComponent() los codifica. Para valores de parámetros usa encodeURIComponent().
¿Cómo decodifico una cadena codificada URL?
JavaScript: decodeURIComponent(). Python: urllib.parse.unquote(). PHP: urldecode().
La codificación URL es un concepto web fundamental. Guarda esta guía como referencia rápida.