URL Encode JavaScript — Guía encodeURIComponent()
Usa el Codificador de URL Online gratuito directamente en tu navegador — sin instalación.
Probar Codificador de URL Online online →Cuando construyes una URL de búsqueda, pasas una ruta de redirección como parámetro de consulta, o construyes una solicitud de autorización OAuth, los caracteres especiales como &, = y los espacios corromperán silenciosamente la URL a menos que los codifiques primero. JavaScript ofrece tres enfoques integrados — encodeURIComponent(), encodeURI() y URLSearchParams — cada uno diseñado para un caso de uso diferente, y elegir el incorrecto es la causa principal de la mayoría de los errores de codificación que he encontrado en revisiones de código. Para una codificación rápida sin ningún código, el Codificador de URL de ToolDeck lo gestiona al instante en el navegador. Esta guía cubre los tres enfoques en profundidad (JavaScript ES2015+ / Node.js 10+): cuándo usar cada uno, cómo difieren en espacios y caracteres reservados, patrones reales con Fetch y API, uso desde CLI, y los cuatro errores que causan los bugs de producción más sutiles.
- ✓encodeURIComponent() es la opción correcta para codificar valores de parámetros individuales — codifica todos los caracteres excepto A–Z, a–z, 0–9 y - _ . ! ~ * ' ( )
- ✓encodeURI() codifica una URL completa preservando los caracteres estructurales (/ ? # & = :) — nunca la uses para valores individuales
- ✓URLSearchParams codifica pares clave-valor automáticamente usando el formato application/x-www-form-urlencoded, donde los espacios se convierten en + en lugar de %20
- ✓La doble codificación es el error de producción más común: encodeURIComponent(encodeURIComponent(value)) convierte %20 en %2520
- ✓La librería qs maneja objetos anidados y arrays en cadenas de consulta de forma nativa — URLSearchParams de la stdlib no lo hace
¿Qué es la codificación de URL?
La codificación de URL (formalmente llamada codificación porcentual, definida en RFC 3986) convierte caracteres que no están permitidos o que tienen un significado especial en una URL en una representación segura. Cada byte inseguro se reemplaza con un signo de porcentaje seguido de dos dígitos hexadecimales — el código ASCII del carácter. Un espacio se convierte en %20, un ampersand se convierte en %26, una barra diagonal se convierte en %2F.
Los caracteres que siempre son seguros y nunca se codifican se llaman caracteres no reservados: letras A–Z y a–z, dígitos 0–9, y los cuatro símbolos - _ . ~. Todo lo demás debe codificarse cuando se usa como dato, o tiene un rol estructural en la URL (como / separando segmentos de ruta o &separando parámetros de consulta). La consecuencia práctica: un nombre de producto como “Teclado Inalámbrico & Ratón” en un parámetro de consulta destruye la estructura de la URL si se pasa sin codificar.
https://shop.example.com/search?q=Wireless Keyboard & Mouse&category=peripherals
https://shop.example.com/search?q=Wireless%20Keyboard%20%26%20Mouse&category=peripherals
encodeURIComponent() — La función correcta para parámetros de consulta
encodeURIComponent() es el motor de la codificación de URL en JavaScript. Codifica todos los caracteres excepto el conjunto no reservado (A–Z, a–z, 0–9, - _ . ! ~ * ' ( )). De forma crítica, codifica todos los caracteres que tienen significado estructural en las URLs — &, =, ?, #, / — lo que la hace segura para usar en los valores de parámetros. No se necesita ninguna importación; es una función global disponible en todos los entornos JavaScript.
Ejemplo mínimo funcional
// Encode a search query parameter that contains special characters
const searchQuery = 'Wireless Keyboard & Mouse'
const filterStatus = 'in-stock'
const maxPrice = '149.99'
const searchUrl = `https://shop.example.com/products?` +
`q=${encodeURIComponent(searchQuery)}` +
`&status=${encodeURIComponent(filterStatus)}` +
`&maxPrice=${encodeURIComponent(maxPrice)}`
console.log(searchUrl)
// https://shop.example.com/products?q=Wireless%20Keyboard%20%26%20Mouse&status=in-stock&maxPrice=149.99Codificar una URL de redirección como parámetro de consulta
// The redirect destination is itself a URL — it must be fully encoded
// or the outer URL parser will misinterpret its ? and & as its own
const redirectAfterLogin = 'https://dashboard.internal/reports?view=weekly&team=platform'
const loginUrl = `https://auth.company.com/login?next=${encodeURIComponent(redirectAfterLogin)}`
console.log(loginUrl)
// https://auth.company.com/login?next=https%3A%2F%2Fdashboard.internal%2Freports%3Fview%3Dweekly%26team%3Dplatform
// Decoding on the receiving end
const params = new URLSearchParams(window.location.search)
const next = params.get('next') // Automatically decoded
const nextUrl = new URL(next!) // Safe to parse
console.log(nextUrl.hostname) // dashboard.internalCodificar caracteres no ASCII y Unicode
// encodeURIComponent handles Unicode natively in all modern environments
// Each UTF-8 byte of the character is percent-encoded
const customerName = 'García, Carlos'
const productTitle = '東京 wireless adapter'
const reviewText = 'Muy bueno — funciona perfectamente'
console.log(encodeURIComponent(customerName))
// Garc%C3%ADa%2C%20Carlos
console.log(encodeURIComponent(productTitle))
// %E6%9D%B1%E4%BA%AC%20wireless%20adapter
console.log(encodeURIComponent(reviewText))
// Muy%20bueno%20%E2%80%94%20funciona%20perfectamente
// Decoding back
console.log(decodeURIComponent('Garc%C3%ADa%2C%20Carlos'))
// García, CarlosencodeURIComponent() usa la codificación interna UTF-16 del motor JavaScript, y luego codifica cada byte UTF-8 del carácter por separado. Un carácter como ü (U+00FC) se codifica como %C3%BC porque su representación UTF-8 es de dos bytes: 0xC3 y 0xBC. Esto es correcto y sigue el estándar URI — se espera que los servidores decodifiquen la secuencia de bytes UTF-8 de vuelta al punto de código original.Funciones de codificación de URL en JavaScript — Referencia de caracteres
Los tres enfoques de codificación nativos difieren exactamente en qué caracteres codifican. La tabla a continuación muestra la salida para los caracteres más problemáticos habitualmente:
| Carácter | Rol en la URL | encodeURIComponent() | encodeURI() | URLSearchParams |
|---|---|---|---|---|
| Space | separador de palabras | %20 | %20 | + |
| & | separador de parámetros | %26 | conservado | %26 |
| = | clave=valor | %3D | conservado | %3D |
| + | espacio codificado (form) | %2B | %2B | %2B |
| ? | inicio de consulta | %3F | conservado | %3F |
| # | fragmento | %23 | conservado | %23 |
| / | separador de ruta | %2F | conservado | %2F |
| : | esquema / puerto | %3A | conservado | %3A |
| @ | separador de autenticación | %40 | conservado | %40 |
| % | literal porcentaje | %25 | %25 | %25 |
| ~ | no reservado | conservado | conservado | conservado |
La columna crítica es encodeURIComponent() frente a encodeURI() para & y =: encodeURI() los deja intactos, lo cual es correcto cuando se codifica una URL completa, pero catastrófico cuando se codifica un valor que contiene estos caracteres.
encodeURI() — Cuándo preservar la estructura de la URL
encodeURI() está diseñada para codificar una URL completa— preserva todos los caracteres que son partes estructurales válidas de una URI: el esquema (https://), el host, los separadores de ruta, los delimitadores de consulta y el identificador de fragmento. Úsala cuando recibas una URL que puede contener espacios o caracteres no ASCII en sus segmentos de ruta, pero necesitas mantener su estructura intacta.
Saneamiento de una URL proporcionada por el usuario
// A URL pasted from a document with spaces in the path and non-ASCII chars const rawUrl = 'https://cdn.example.com/assets/product images/München chair.png' const safeUrl = encodeURI(rawUrl) console.log(safeUrl) // https://cdn.example.com/assets/product%20images/M%C3%BCnchen%20chair.png // encodeURIComponent would break it — it encodes the :// and all / characters const broken = encodeURIComponent(rawUrl) console.log(broken) // https%3A%2F%2Fcdn.example.com%2Fassets%2Fproduct%20images%2FM%C3%BCnchen%20chair.png // ↑ Not a valid URL — the scheme and slashes are destroyed
URL suele ser una mejor opción que encodeURI() para manejar cadenas de URL proporcionadas por el usuario — normaliza la URL, valida la estructura y te ofrece una API limpia para acceder a cada componente. Reserva encodeURI() para casos donde necesites un resultado en cadena y ya sepas que la entrada es estructuralmente una URL válida.URLSearchParams — El enfoque moderno para cadenas de consulta
URLSearchParams es la forma idiomática de construir y analizar cadenas de consulta en JavaScript moderno. Está disponible globalmente en todos los navegadores modernos y Node.js 10+, y gestiona la codificación automáticamente — trabajas con pares clave-valor simples y produce la salida correcta. Un detalle importante: sigue la especificación application/x-www-form-urlencoded, que codifica los espacios como + en lugar de %20. Esto es correcto y ampliamente compatible, pero debes tenerlo en cuenta cuando tu servidor espera un formato específico.
Construyendo una URL de solicitud de búsqueda
// Building a search API URL with multiple parameters
const filters = {
query: 'standing desk',
category: 'office-furniture',
minPrice: '200',
maxPrice: '800',
inStock: 'true',
sortBy: 'price_asc',
}
const params = new URLSearchParams(filters)
const apiUrl = `https://api.example.com/v2/products?${params}`
console.log(apiUrl)
// https://api.example.com/v2/products?query=standing+desk&category=office-furniture&minPrice=200&maxPrice=800&inStock=true&sortBy=price_asc
// Appending additional params after construction
params.append('page', '2')
params.append('tag', 'ergonomic & adjustable')
console.log(params.toString())
// query=standing+desk&...&tag=ergonomic+%26+adjustableAnalizando una cadena de consulta entrante
// Both browser (window.location.search) and Node.js (req.url) scenarios
function parseWebhookCallbackUrl(rawSearch: string) {
const params = new URLSearchParams(rawSearch)
return {
eventId: params.get('event_id'), // null if missing
timestamp: Number(params.get('ts')),
signature: params.get('sig'),
redirectUrl: params.get('redirect'), // Automatically decoded
tags: params.getAll('tag'), // Handles repeated keys
}
}
const callbackQuery = '?event_id=evt_9c2f&ts=1717200000&sig=sha256%3Dabc123&redirect=https%3A%2F%2Fdashboard.internal%2F&tag=payment&tag=webhook'
const parsed = parseWebhookCallbackUrl(callbackQuery)
console.log(parsed.redirectUrl) // https://dashboard.internal/
console.log(parsed.tags) // ['payment', 'webhook']Cómo codificar parámetros de URL en solicitudes Fetch de JavaScript
El lugar más común donde aparece la codificación de URL en código de producción es dentro de llamadas fetch() — ya sea construyendo la URL de la solicitud o enviando datos de formulario en el cuerpo de la solicitud. Cada escenario tiene su propio enfoque correcto.
Solicitud GET — codificación de parámetros de consulta
async function searchInventory(params: {
sku?: string
warehouse: string
minStock: number
updatedAfter?: Date
}): Promise<{ items: unknown[]; total: number }> {
const searchParams = new URLSearchParams()
if (params.sku) searchParams.set('sku', params.sku)
searchParams.set('warehouse', params.warehouse)
searchParams.set('min_stock', String(params.minStock))
if (params.updatedAfter) searchParams.set('updated_after', params.updatedAfter.toISOString())
const url = `https://inventory.internal/api/items?${searchParams}`
const res = await fetch(url, {
headers: {
'Authorization': `Bearer ${process.env.INVENTORY_API_KEY}`,
'Accept': 'application/json',
},
})
if (!res.ok) {
throw new Error(`Inventory API ${res.status}: ${await res.text()}`)
}
return res.json()
}
const results = await searchInventory({
warehouse: 'eu-west-1',
minStock: 10,
updatedAfter: new Date('2025-01-01'),
})
console.log(`Found ${results.total} items`)Solicitud POST — codificando el cuerpo de un formulario en URL
// application/x-www-form-urlencoded POST — used by OAuth token endpoints,
// legacy form-submission APIs, and some webhook providers
async function requestOAuthToken(
clientId: string,
clientSecret: string,
code: string,
redirectUri: string,
): Promise<{ access_token: string; expires_in: number }> {
const body = new URLSearchParams({
grant_type: 'authorization_code',
client_id: clientId,
client_secret: clientSecret,
code,
redirect_uri: redirectUri, // URLSearchParams encodes this automatically
})
const res = await fetch('https://oauth.provider.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: body.toString(),
// body: body — also works directly in modern environments (Fetch spec accepts URLSearchParams)
})
if (!res.ok) {
const err = await res.json()
throw new Error(`OAuth error: ${err.error_description ?? err.error}`)
}
return res.json()
}Cuando necesites probar o depurar una URL codificada sin configurar un script, pega el valor sin procesar directamente en el Codificador de URL — codifica y decodifica al instante, mostrándote exactamente lo que verán el navegador y el servidor. Útil para inspeccionar URIs de redirección OAuth, URLs de callback de webhooks y parámetros de solicitudes firmadas de CDN.
Codificación de URL desde la línea de comandos con Node.js y Shell
Para scripts de shell, pipelines de CI, o depuración rápida, varios enfoques de línea de comandos funcionan sin escribir un script completo.
# ── Node.js one-liners — cross-platform (macOS, Linux, Windows) ────────
# encodeURIComponent — encode a single value
node -e "console.log(encodeURIComponent(process.argv[1]))" "Wireless Keyboard & Mouse"
# Wireless%20Keyboard%20%26%20Mouse
# Build a complete query string
node -e "console.log(new URLSearchParams(JSON.parse(process.argv[1])).toString())" '{"q":"standing desk","category":"office-furniture","page":"1"}'
# q=standing+desk&category=office-furniture&page=1
# Decode a percent-encoded string
node -e "console.log(decodeURIComponent(process.argv[1]))" "Wireless%20Keyboard%20%26%20Mouse"
# Wireless Keyboard & Mouse
# ── curl — automatic encoding ───────────────────────────────────────────
# curl --data-urlencode encodes values automatically in GET and POST
curl -G "https://api.example.com/search" --data-urlencode "q=Wireless Keyboard & Mouse" --data-urlencode "category=office furniture"
# ── Python one-liner (available on most systems) ─────────────────────────
python3 -c "from urllib.parse import quote; print(quote(input(), safe=''))"
# (type the string and press Enter)
# ── jq + bash: encode every value in a JSON object ───────────────────────
echo '{"q":"hello world","tag":"node & express"}' | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(new URLSearchParams(d).toString())"
# q=hello+world&tag=node+%26+expressAlternativa de alto rendimiento: qs
El URLSearchParams integrado no admite objetos anidados ni arrays — la forma de las cadenas de consulta que usan muchas APIs y frameworks. La librería qs (más de 30M de descargas semanales en npm) maneja toda la gama de patrones de cadenas de consulta usados en la práctica: objetos anidados con notación de corchetes (filters[status]=active), claves repetidas, codificadores personalizados y formatos de serialización de arrays configurables.
npm install qs # or pnpm add qs
import qs from 'qs'
// URLSearchParams cannot represent this structure natively
const reportFilters = {
dateRange: {
from: '2025-01-01',
to: '2025-03-31',
},
status: ['published', 'archived'],
author: { id: 'usr_4f2a9c1b', role: 'editor' },
workspace: 'ws-platform-eu',
}
// qs produces bracket-notation query strings used by Express, Rails, Django REST
const query = qs.stringify(reportFilters, { encode: true })
console.log(query)
// dateRange%5Bfrom%5D=2025-01-01&dateRange%5Bto%5D=2025-03-31&status%5B0%5D=published&status%5B1%5D=archived&author%5Bid%5D=usr_4f2a9c1b&author%5Brole%5D=editor&workspace=ws-platform-eu
// Human-readable (no encoding) — useful for debugging
console.log(qs.stringify(reportFilters, { encode: false }))
// dateRange[from]=2025-01-01&dateRange[to]=2025-03-31&status[0]=published&status[1]=archived...
// Parsing back
const parsed = qs.parse(query)
console.log(parsed.dateRange) // { from: '2025-01-01', to: '2025-03-31' }
console.log(parsed.status) // ['published', 'archived']Para parámetros planos de clave-valor, URLSearchParams es siempre la opción correcta — está integrado, tiene coste cero y es universalmente compatible. Recurre a qs solo cuando necesites estructuras anidadas, formatos de serialización de arrays distintos a claves repetidas, o cuando te integres con un framework de back-end que espera cadenas de consulta en notación de corchetes.
Errores comunes
He visto estos cuatro errores repetidamente en bases de código de producción — la mayoría son fallos silenciosos que solo afloran cuando un valor contiene un carácter especial, que es exactamente el tipo de bug que se cuela en las pruebas unitarias y solo aparece con datos reales de usuarios.
Error 1 — Usar encodeURI() para valores de parámetros de consulta
Problema: encodeURI() no codifica &, = ni +. Cuando un valor contiene estos caracteres, se interpretan como sintaxis de cadena de consulta, dividiendo o sobrescribiendo parámetros silenciosamente. Solución: usa siempre encodeURIComponent() para valores individuales.
// ❌ encodeURI does not encode & and = in the value
// "plan=pro&promo=SAVE20" is treated as two separate params
const planName = 'Pro Plan (save=20% & free trial)'
const url = `/checkout?plan=${encodeURI(planName)}`
// /checkout?plan=Pro%20Plan%20(save=20%%20&%20free%20trial)
// ↑ & breaks the query string// ✅ encodeURIComponent encodes & and = safely
const planName = 'Pro Plan (save=20% & free trial)'
const url = `/checkout?plan=${encodeURIComponent(planName)}`
// /checkout?plan=Pro%20Plan%20(save%3D20%25%20%26%20free%20trial)
// ↑ = and & are both encodedError 2 — Doble codificación de una cadena ya codificada
Problema: Llamar a encodeURIComponent() sobre un valor que ya está codificado en porcentaje convierte el % en %25, por lo que %20 se convierte en %2520. El servidor decodifica una vez y recibe un literal %20 en lugar de un espacio. Solución: decodifica primero y luego vuelve a codificar, o asegúrate de que el valor nunca se codifique dos veces.
// ❌ encodedParam already contains %20 — encoding again produces %2520
const encodedParam = 'Berlin%20Office'
const url = `/api/locations/${encodeURIComponent(encodedParam)}`
// /api/locations/Berlin%2520Office
// Server sees: "Berlin%20Office" (a literal percent-twenty, not a space)// ✅ Decode first if the value may already be encoded
const maybeEncoded = 'Berlin%20Office'
const clean = decodeURIComponent(maybeEncoded) // 'Berlin Office'
const url = `/api/locations/${encodeURIComponent(clean)}`
// /api/locations/Berlin%20Office — correctError 3 — No tener en cuenta la diferencia entre + / %20 de URLSearchParams y encodeURIComponent
Problema: URLSearchParams codifica los espacios como + (application/x-www-form-urlencoded), mientras que encodeURIComponent() usa %20. Mezclar ambos en la misma URL — por ejemplo, añadir una cadena precodificada a una salida de URLSearchParams — produce una codificación inconsistente que confunde a algunos analizadores. Solución: elige un enfoque y úsalo de forma consistente en toda una función de construcción de URL.
// ❌ Mixed: URLSearchParams uses + for spaces, but we're appending
// a manually-encoded segment that uses %20
const base = new URLSearchParams({ category: 'office furniture' })
const extra = `sort=${encodeURIComponent('price asc')}`
const url = `/api/products?${base}&${extra}`
// /api/products?category=office+furniture&sort=price%20asc
// ↑ two different space encodings in the same URL// ✅ Use URLSearchParams exclusively — consistent encoding throughout
const params = new URLSearchParams({
category: 'office furniture',
sort: 'price asc',
})
const url = `/api/products?${params}`
// /api/products?category=office+furniture&sort=price+ascError 4 — Olvidar codificar segmentos de ruta que contienen barras diagonales
Problema: Un identificador de recurso como una ruta de archivo (reports/2025/q1.pdf) usado como segmento de ruta REST contiene caracteres / que el enrutador del servidor interpreta como separadores de ruta, enrutando a un endpoint inexistente. Solución: usa siempre encodeURIComponent() para segmentos de ruta que pueden contener barras diagonales.
// ❌ The file path contains / — the server receives a 3-segment path
// instead of a single resource ID
const filePath = 'reports/2025/q1-financials.pdf'
const url = `https://storage.example.com/objects/${filePath}`
// https://storage.example.com/objects/reports/2025/q1-financials.pdf
// → Server routes to /objects/:year/:filename — 404 or wrong resource// ✅ encodeURIComponent encodes / as %2F — single path segment
const filePath = 'reports/2025/q1-financials.pdf'
const url = `https://storage.example.com/objects/${encodeURIComponent(filePath)}`
// https://storage.example.com/objects/reports%2F2025%2Fq1-financials.pdf
// → Server receives the full file path as one resource identifierMétodos de codificación de URL en JavaScript — Comparación rápida
| Método | Codifica espacios como | Codifica & = ? | Codifica # / : | Caso de uso | Requiere instalación |
|---|---|---|---|---|---|
| encodeURIComponent() | %20 | ✅ sí | ✅ sí | Codificar valores de parámetros individuales | No |
| encodeURI() | %20 | ❌ no | ❌ no | Sanear una cadena de URL completa | No |
| URLSearchParams | + | ✅ sí | ✅ sí | Construir y analizar cadenas de consulta | No |
| Constructor URL | auto por componente | auto | auto | Construir y normalizar URLs completas | No |
| librería qs | %20 (configurable) | ✅ sí | ✅ sí | Objetos anidados y arrays en cadenas de consulta | npm install qs |
Para la gran mayoría de casos, la elección se reduce a tres escenarios. Usa URLSearchParams cuando construyas cadenas de consulta con múltiples parámetros a partir de datos estructurados — es la opción más segura y legible. Usa encodeURIComponent() para codificar un único valor en una URL con template literal, para segmentos de ruta, o para valores en sistemas que esperan %20 en lugar de + para los espacios (como las URLs firmadas de AWS S3). Recurre a qs solo cuando tu cadena de consulta lleve objetos anidados o arrays que URLSearchParams no puede representar de forma nativa.
Preguntas frecuentes
Herramientas relacionadas
Para codificar o decodificar con un solo clic sin escribir ningún código, pega tu cadena directamente en el Codificador de URL — gestiona la codificación porcentual y la decodificación al instante en tu navegador, con la salida codificada lista para copiar en una llamada fetch o en el terminal.
Alex is a front-end and Node.js developer with extensive experience building web applications and developer tooling. He is passionate about web standards, browser APIs, and the JavaScript ecosystem. In his spare time he contributes to open-source projects and writes about modern JavaScript patterns, performance optimisation, and everything related to the web platform.
Sophie is a full-stack developer focused on TypeScript across the entire stack — from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.