Guía8 min de lectura

¿Qué es el codificado por porcentaje? (RFC 3986 explicado de forma sencilla)

El codificado por porcentaje es un mecanismo definido en el RFC 3986 para codificar caracteres especiales en los URI reemplazándolos por un signo de porcentaje (%) seguido de dos dígitos hexadecimales. Garantiza que las URL contengan únicamente caracteres ASCII válidos que puedan transmitirse de forma segura a través de internet.

¿Qué es el codificado por porcentaje?

El codificado por porcentaje, también llamado codificación de URL, es la forma estándar de representar caracteres en un URI (Identificador Uniforme de Recursos) que no están permitidos o que tienen un significado especial. Funciona reemplazando cada carácter que necesita codificarse por un signo de porcentaje (%) seguido de dos dígitos hexadecimales que representan el valor de byte del carácter.

Por ejemplo, el carácter de espacio (valor de byte 0x20) se codifica como %20. El signo arroba @ (valor de byte 0x40) se codifica como %40. Este mecanismo garantiza que cualquier dato pueda incrustarse de forma segura en un URI sin entrar en conflicto con la sintaxis del URI.

El término "percent encoding" proviene del uso del carácter de porcentaje como prefijo de escape. La especificación formal está definida en el RFC 3986, publicado por el Grupo de Trabajo de Ingeniería de Internet (IETF) en enero de 2005 y redactado por Tim Berners-Lee, Roy Fielding y Larry Masinter.

Cómo funciona el codificado por porcentaje

El proceso de codificación sigue estos pasos: primero, el carácter se convierte a su representación en bytes usando una codificación de caracteres (casi siempre UTF-8 en la web moderna). Luego, cada byte se representa como un signo de porcentaje seguido de dos dígitos hexadecimales (usando mayúsculas A-F por convención, aunque los decodificadores deberían aceptar minúsculas).

// Codificación paso a paso de un carácter de espacio
// Carácter: ' ' (espacio)
// Valor de byte ASCII/UTF-8: 0x20 (decimal 32)
// Codificado por porcentaje: %20

// Codificación paso a paso de un carácter multibyte: e con acento agudo
// Carácter: e con acento agudo (U+00E9)
// Bytes UTF-8: 0xC3 0xA9
// Codificado por porcentaje: %C3%A9

// Codificación paso a paso de un carácter de 3 bytes
// Carácter: ideograma CJK (U+4E2D)
// Bytes UTF-8: 0xE4 0xB8 0xAD
// Codificado por porcentaje: %E4%B8%AD

Los dígitos hexadecimales siempre deben ir en pares. Un signo de porcentaje solitario o un signo de porcentaje seguido de caracteres que no son hexadecimales es inválido y provocará un error de decodificación. Esta es una causa habitual del error "URI malformed" en JavaScript.

El codificado por porcentaje siempre es reversible. El decodificador lee el signo de porcentaje, toma los dos caracteres siguientes como un valor de byte hexadecimal y lo convierte de nuevo al carácter original. En el caso de los caracteres UTF-8 multibyte, los bytes codificados consecutivos se combinan y se decodifican juntos.

¿Qué caracteres deben codificarse?

No todos los caracteres necesitan codificado por porcentaje. El RFC 3986 define dos categorías: los caracteres no reservados, que nunca necesitan codificarse, y los caracteres reservados, que deben codificarse cuando no se utilizan para su propósito reservado. Todos los demás caracteres (incluidos los espacios, los caracteres no ASCII y los caracteres de control) deben codificarse siempre.

Caracteres que NO necesitan codificarse (no reservados): letras mayúsculas (A-Z), letras minúsculas (a-z), dígitos (0-9), guion (-), punto (.), guion bajo (_) y virgulilla (~). Estos 66 caracteres pueden aparecer en cualquier parte de un URI sin codificarse.

Caracteres que a veces necesitan codificarse (reservados): : / ? # [ ] @ ! $ & ' ( ) * + , ; =. Estos caracteres tienen un significado sintáctico especial en los URI. Solo necesitan codificarse cuando se usan como datos en lugar de como delimitadores.

Caracteres que siempre necesitan codificarse: los espacios, los caracteres no ASCII (cualquier carácter por encima de 127), los caracteres de control (0-31 y 127) y los caracteres inseguros como < > { } | \ ^ ` ".

Caracteres reservados frente a no reservados en el RFC 3986

La distinción entre caracteres reservados y no reservados es fundamental para entender cómo funcionan los URI. Los caracteres reservados actúan como delimitadores que definen la estructura de un URI. Por ejemplo, :// separa el esquema de la autoridad, / separa los segmentos de la ruta, ? inicia la cadena de consulta y # inicia el fragmento.

Categoría Caracteres Cuándo codificar
No reservados A-Z a-z 0-9 - . _ ~ Nunca
Delimitadores generales : / ? # [ ] @ Cuando se usan como datos, no como delimitadores
Subdelimitadores ! $ & ' ( ) * + , ; = Cuando se usan como datos en componentes que les asignan un significado
Todos los demás caracteres Espacios, no ASCII, caracteres de control, etc. Siempre

Un principio crítico del RFC 3986 es que los URI que difieren únicamente en si un carácter reservado está codificado por porcentaje o aparece literalmente no son equivalentes. Por ejemplo, /path/to y /path%2Fto son URI diferentes, aunque %2F se decodifique como /. El primero tiene dos segmentos de ruta; el segundo tiene un único segmento de ruta que contiene una barra literal.

Codificado por porcentaje frente a codificación de URL: ¿son lo mismo?

"Codificado por porcentaje" y "codificación de URL" suelen usarse indistintamente y, en la mayoría de los contextos, significan lo mismo. Sin embargo, existe una sutil distinción histórica. La "codificación de URL" puede referirse a veces al antiguo formato application/x-www-form-urlencoded usado por los formularios HTML, que codifica los espacios como + en lugar de %20.

El formato application/x-www-form-urlencoded se definió en la especificación de HTML y es anterior al RFC 3986. Tiene reglas ligeramente distintas: los espacios se convierten en + y el conjunto de caracteres que no se codifican es algo diferente. El uso moderno del término "codificación de URL" casi siempre se refiere al codificado por porcentaje del RFC 3986, donde los espacios son %20.

En la práctica, deberías usar el codificado por porcentaje del RFC 3986 para todos los contextos de URI (segmentos de ruta, parámetros de consulta en las API REST, identificadores de fragmento). Usa el formato application/x-www-form-urlencoded únicamente cuando trabajes con envíos de formularios HTML o cuando una API específica lo requiera.

// Codificado por porcentaje del RFC 3986 (recomendado para URI)
encodeURIComponent('hello world')  // "hello%20world"

// application/x-www-form-urlencoded (formularios HTML)
new URLSearchParams({q: 'hello world'}).toString()  // "q=hello+world"

// Equivalente en Python
from urllib.parse import quote, quote_plus
quote('hello world', safe='')   # "hello%20world"
quote_plus('hello world')       # "hello+world"

Artículos relacionados

Prueba nuestras herramientas gratuitas