URL Decode JavaScript — decodeURIComponent()
Usa il Decodificatore URL Online gratuito direttamente nel tuo browser — nessuna installazione.
Prova Decodificatore URL Online online →Le stringhe codificate in percentuale appaiono costantemente nel codice JavaScript — una query di ricerca arriva come q=standing+desk%26price%3A200, un reindirizzamento OAuth come next=https%3A%2F%2Fdashboard.internal%2F, un percorso di archiviazione come reports%2F2025%2Fq1.pdf. Come fare l'URL decode in JavaScript si riduce alla scelta della funzione integrata giusta tra tre opzioni: decodeURIComponent(), decodeURI() e URLSearchParams — e la scelta tra esse è la causa principale della maggior parte delle corruzioni silenziose di dati che ho visto in codebase di produzione, in particolare il caso limite del + come spazio e la doppia decodifica. Per una decodifica rapida senza scrivere codice, il Decodificatore URL di ToolDeck lo gestisce istantaneamente nel browser. Questo tutorial sulla decodifica URL in JavaScript copre le tre funzioni in profondità (ES2015+ / Node.js 10+): quando usare ciascuna, come differiscono per spazi e caratteri riservati, decodifica da file e richieste HTTP, gestione sicura degli errori e i quattro errori che causano i bug di produzione più subdoli.
- ✓decodeURIComponent() decodifica tutte le sequenze codificate in percentuale — è la scelta giusta per i valori dei singoli parametri di query e i segmenti di percorso
- ✓decodeURI() preserva i caratteri strutturali dell'URI come / ? & = # : — usalo solo per decodificare una stringa URL completa, mai per valori singoli
- ✓URLSearchParams.get() restituisce valori già decodificati — chiamare decodeURIComponent() sul risultato causa una doppia decodifica
- ✓decodeURIComponent() NON decodifica + come spazio — per i dati codificati come form (application/x-www-form-urlencoded), usa URLSearchParams o sostituisci + prima di decodificare
- ✓Avvolgi sempre decodeURIComponent() in try/catch quando l'input proviene da dati utente — un % isolato o una sequenza incompleta genera un URIError
Cos'è la decodifica URL?
La codifica percentuale (formalmente definita nella RFC 3986) sostituisce i caratteri non sicuri o strutturalmente significativi in un URL con un segno % seguito da due cifre esadecimali — il valore in byte UTF-8 del carattere. La decodifica URL inverte questa trasformazione: ogni sequenza %XX viene riconvertita nel suo byte originale, e la sequenza di byte risultante viene interpretata come testo UTF-8. Uno spazio decodificato da %20, una barra da %2F, il carattere non ASCII ü da %C3%BC (la sua rappresentazione UTF-8 di due byte).
I caratteri che non vengono mai codificati — chiamati caratteri non riservati — sono le lettere A–Z e a–z, le cifre 0–9 e - _ . ~. Tutto il resto ha un ruolo strutturale nell'URL (come / che separa i segmenti di percorso o & che separa i parametri di query) o deve essere codificato quando usato come dato. Il risultato pratico: un filtro di ricerca come status=active&tier=premiumcodificato come valore di un singolo parametro di query arriva senza alcuna somiglianza con l'originale.
// Codificato in percentuale — come ricevuto in una richiesta HTTP o payload webhook "q=price%3A%5B200+TO+800%5D%20AND%20brand%3ANorthwood%20%26%20status%3Ain-stock"
// Dopo la decodifica URL — il filtro Elasticsearch originale "q=price:[200 TO 800] AND brand:Northwood & status:in-stock"
decodeURIComponent() — La funzione standard per decodificare i valori
decodeURIComponent() è il motore della decodifica URL in JavaScript. Decodifica ogni sequenza %XX nella stringa di input — inclusi i caratteri che hanno significato strutturale in un URL, come %2F (barra), %3F (punto interrogativo), %26 (e commerciale) e %3D (segno uguale). Questo la rende la scelta giusta per decodificare i valori dei singoli parametri di query e i segmenti di percorso, ma la scelta sbagliata per decodificare un URL completo — dove quei caratteri strutturali devono rimanere codificati. È una funzione globale: nessuna importazione è necessaria in nessun ambiente JavaScript.
Esempio minimo funzionante
// Decodificare i valori dei singoli parametri di query — il caso più comune
const city = decodeURIComponent('S%C3%A3o%20Paulo') // 'São Paulo'
const district = decodeURIComponent('It%C3%A1im%20Bibi') // 'Itáim Bibi'
const category = decodeURIComponent('office%20furniture') // 'office furniture'
const filter = decodeURIComponent('price%3A%5B200+TO+800%5D') // 'price:[200+TO+800]'
// Nota: + NON viene decodificato come spazio — vedere la sezione + nella tabella di confronto
console.log(city) // São Paulo
console.log(district) // Itáim Bibi
console.log(category) // office furniture
console.log(filter) // price:[200+TO+800]Decodifica di un URL di reindirizzamento estratto da un parametro di query
// L'URL di reindirizzamento era codificato in percentuale quando è stato incorporato come valore di parametro
// lato ricevente: estrarlo e usarlo — nessuna decodifica manuale necessaria con URLSearchParams
const incomingUrl = 'https://auth.company.com/callback' +
'?next=https%3A%2F%2Fdashboard.internal%2Freports%3Fview%3Dweekly%26team%3Dplatform' +
'&session_id=sid_7x9p2k'
const url = new URL(incomingUrl)
const rawNext = url.searchParams.get('next') // Decodificato automaticamente da URLSearchParams
const sessionId = url.searchParams.get('session_id') // 'sid_7x9p2k'
// rawNext è già decodificato: 'https://dashboard.internal/reports?view=weekly&team=platform'
// NON chiamare decodeURIComponent(rawNext) di nuovo — sarebbe una doppia decodifica
const nextUrl = new URL(rawNext!)
console.log(nextUrl.hostname) // dashboard.internal
console.log(nextUrl.searchParams.get('view')) // weekly
console.log(nextUrl.searchParams.get('team')) // platformDecodifica di segmenti di percorso non ASCII e Unicode
// API REST con segmenti di percorso internazionalizzati
// Ogni byte UTF-8 del carattere originale è stato codificato in percentuale separatamente
const encodedSegments = [
'%E6%9D%B1%E4%BA%AC', // 東京 (Tokyo) — 3 byte per carattere
'M%C3%BCnchen', // München — ü codificata come 2 byte
'caf%C3%A9', // café — é come NFC precomposto
'S%C3%A3o%20Paulo', // São Paulo
]
encodedSegments.forEach(seg => {
console.log(decodeURIComponent(seg))
})
// 東京
// München
// café
// São Paulo
// Estrazione di una chiave file da un URL di API di archiviazione
// La chiave oggetto conteneva / quindi è stata codificata come %2F nel segmento di percorso
const storageUrl = 'https://storage.api.example.com/v1/objects/reports%2F2025%2Fq1-financials.pdf'
const rawKey = new URL(storageUrl).pathname.replace('/v1/objects/', '')
// .pathname decodifica la codifica a livello URL ma %2F (come %252F a livello URL) rimane
// Usare decodeURIComponent per il passo finale:
const fileKey = decodeURIComponent(rawKey) // 'reports/2025/q1-financials.pdf'
console.log(fileKey)decodeURIComponent() lancia un URIError quando l'input contiene un % non seguito da due cifre esadecimali valide — per esempio un % isolato alla fine di una stringa o una sequenza come %GH. Avvolgila sempre in try/catchquando si decodifica un input fornito dall'utente. I pattern di decodifica sicura sono trattati nella sezione Gestione degli errori qui sotto.Funzioni di decodifica URL in JavaScript — Riferimento caratteri
Le tre funzioni di decodifica integrate differiscono esattamente nelle sequenze codificate che decodificano. La tabella mostra il comportamento per i caratteri più importanti in pratica:
| Codificato | Carattere | decodeURIComponent() | decodeURI() | URLSearchParams |
|---|---|---|---|---|
| %20 | spazio | spazio ✅ | spazio ✅ | spazio ✅ |
| + | più (form) | + (mantenuto) | + (mantenuto) | spazio ✅ |
| %2B | + letterale | + ✅ | + ✅ | + ✅ |
| %26 | & | & ✅ | & (mantenuto) ❌ | & ✅ |
| %3D | = | = ✅ | = (mantenuto) ❌ | = ✅ |
| %3F | ? | ? ✅ | ? (mantenuto) ❌ | ? ✅ |
| %23 | # | # ✅ | # (mantenuto) ❌ | # ✅ |
| %2F | / | / ✅ | / (mantenuto) ❌ | / ✅ |
| %3A | : | : ✅ | : (mantenuto) ❌ | : ✅ |
| %40 | @ | @ ✅ | @ (mantenuto) ❌ | @ ✅ |
| %25 | % | % ✅ | % ✅ | % ✅ |
| %C3%BC | ü | ü ✅ | ü ✅ | ü ✅ |
Le due righe critiche sono + e i caratteri strutturali (%26, %3D, %3F). URLSearchParams decodifica + come spazio perché segue la specifica application/x-www-form-urlencoded — corretto per i form HTML, ma diverso da ciò che fa decodeURIComponent() con lo stesso carattere. E decodeURI() ignora silenziosamente %26, %3D e %3F — il che sembra corretto finché un valore contiene effettivamente una e commerciale o un segno uguale codificato.
decodeURI() — Decodificare un URL completo senza romperne la struttura
decodeURI() è il complemento di encodeURI(). Decodifica una stringa URL completa preservando i caratteri che hanno significato strutturale in una URI: ; , / ? : @ & = + $ #. Questi vengono lasciati nella loro forma codificata in percentuale (o come caratteri letterali se apparivano non codificati nell'input). Questo rende decodeURI()sicuro per sanificare URL completi che possono contenere caratteri non ASCII nel percorso o nell'hostname, senza collassare accidentalmente la struttura della query string.
Sanificazione di un URL con segmenti di percorso non ASCII
// Un URL CDN con segmenti di percorso internazionalizzati e una query string strutturata // decodeURI() decodifica il percorso non ASCII ma preserva ? & = intatti const encodedUrl = 'https://cdn.example.com/assets/%E6%9D%B1%E4%BA%AC%2F2025%2Fq1-report.pdf' + '?token=eyJ0eXAiOiJKV1QiLCJhbGci&expires=1735689600' const readable = decodeURI(encodedUrl) console.log(readable) // https://cdn.example.com/assets/東京/2025/q1-report.pdf?token=eyJ0eXAiOiJKV1QiLCJhbGci&expires=1735689600 // ↑ Non ASCII decodificato; ? & = preservati — l'URL rimane strutturalmente valido // decodeURIComponent distruggerebbe l'URL — : / ? & = tutti decodificati in una volta const broken = decodeURIComponent(encodedUrl) // 'https://cdn.example.com/assets/東京/2025/q1-report.pdf?token=eyJ0eXAiOiJKV1QiLCJhbGci&expires=1735689600' // Sembra uguale qui, ma un URL come 'https%3A%2F%2F...' verrebbe distrutto
URL rispetto a decodeURI()quando hai anche bisogno di accedere ai componenti individuali dell'URL. new URL(str)normalizza l'input, ne valida la struttura ed espone .pathname, .searchParams e .hostname come proprietà già decodificate. Riserva decodeURI() per i casi in cui hai bisogno solo di un risultato stringa e non puoi usare il costruttore URL (ad esempio, in ambienti molto vecchi di Node.js 6 senza la classe globale URL).URLSearchParams — Decodifica automatica per le query string
URLSearchParams è il modo idiomatico per analizzare le query string in JavaScript moderno. Ogni valore restituito da .get(), .getAll()o dall'iterazione è automaticamente decodificato — incluso + come spazio per i dati codificati come form. È disponibile globalmente in tutti i browser moderni e Node.js 10+, non richiede importazioni e gestisce i casi limite che la divisione manuale delle stringhe sbaglia.
Analisi di una query string in ingresso
// Analisi di una query string di callback webhook o di reindirizzamento OAuth
const rawSearch =
'?event_id=evt_9c2f4a1b' +
'&product_name=Standing+Desk+Pro' +
'&filter=price%3A%5B200+TO+800%5D' +
'&tag=ergonomic&tag=adjustable' +
'&redirect=https%3A%2F%2Fdashboard.internal%2Forders%3Fview%3Dpending'
const params = new URLSearchParams(rawSearch)
console.log(params.get('event_id')) // 'evt_9c2f4a1b'
console.log(params.get('product_name')) // 'Standing Desk Pro' ← + decodificato come spazio
console.log(params.get('filter')) // 'price:[200+TO+800]' ← %3A e %5B decodificati
console.log(params.getAll('tag')) // ['ergonomic', 'adjustable']
console.log(params.get('redirect')) // 'https://dashboard.internal/orders?view=pending'
// Iterazione di tutti i parametri
for (const [key, value] of params) {
console.log(`${key}: ${value}`)
}
// event_id: evt_9c2f4a1b
// product_name: Standing Desk Pro
// filter: price:[200+TO+800]
// tag: ergonomic
// tag: adjustable
// redirect: https://dashboard.internal/orders?view=pendingAnalisi dei parametri di query dall'URL corrente del browser
// URL corrente: https://app.example.com/search
// ?q=standing+desk
// &category=office+furniture
// &sort=price_asc
// &page=2
interface SearchFilters {
query: string | null
category: string | null
sort: string
page: number
}
function getSearchFilters(): SearchFilters {
const params = new URLSearchParams(window.location.search)
return {
query: params.get('q'), // 'standing desk'
category: params.get('category'), // 'office furniture'
sort: params.get('sort') ?? 'relevance',
page: Number(params.get('page') ?? '1'),
}
}
const filters = getSearchFilters()
console.log(filters.query) // standing desk (+ decodificato automaticamente)
console.log(filters.category) // office furnitureDecodifica di dati codificati URL da file e risposte API
Due scenari ricorrono costantemente nei progetti reali: elaborare un file su disco che contiene dati codificati in percentuale (log di accesso, esportazioni di dati, file di acquisizione webhook) e analizzare l'URL di una richiesta HTTP in ingresso in un server Node.js. Entrambi seguono lo stesso principio — usa il costruttore URL o URLSearchParams invece della divisione manuale delle stringhe — ma i dettagli differiscono.
Lettura e decodifica di record codificati URL da un file
import { createReadStream } from 'fs'
import { createInterface } from 'readline'
// File: orders-export.txt — un record codificato URL per riga
// customer_name=Marco+Rossi&order_id=ord_9c2f4a&product=Standing+Desk+Pro&total=149.99%20EUR
// customer_name=Giulia+Ferrari&order_id=ord_7b3a1c&product=Ergonomic+Chair&total=89.00%20EUR
// customer_name=Luca+Bianchi&order_id=ord_2e8d5f&product=Monitor+Arm&total=59.00%20EUR
interface Order {
customerName: string | null
orderId: string | null
product: string | null
total: string | null
}
async function parseOrdersFile(filePath: string): Promise<Order[]> {
const fileStream = createReadStream(filePath, { encoding: 'utf-8' })
const rl = createInterface({ input: fileStream, crlfDelay: Infinity })
const orders: Order[] = []
for await (const line of rl) {
if (!line.trim()) continue
// URLSearchParams decodifica + come spazio e le sequenze %XX automaticamente
const params = new URLSearchParams(line)
orders.push({
customerName: params.get('customer_name'), // 'Marco Rossi'
orderId: params.get('order_id'), // 'ord_9c2f4a'
product: params.get('product'), // 'Standing Desk Pro'
total: params.get('total'), // '149.99 EUR'
})
}
return orders
}
const orders = await parseOrdersFile('./orders-export.txt')
console.log(orders[0])
// { customerName: 'Marco Rossi', orderId: 'ord_9c2f4a', product: 'Standing Desk Pro', total: '149.99 EUR' }Analisi di un log di accesso Nginx per decodificare le query di ricerca
import { createReadStream } from 'fs'
import { createInterface } from 'readline'
// Le righe del log di accesso Nginx hanno questo aspetto:
// 192.168.1.42 - - [11/Mar/2026:10:23:01 +0000] "GET /api/search?q=standing%20desk%26brand%3ANorthwood&sort=price_asc HTTP/1.1" 200 1842
async function extractSearchQueries(logFile: string): Promise<string[]> {
const rl = createInterface({ input: createReadStream(logFile), crlfDelay: Infinity })
const queries: string[] = []
for await (const line of rl) {
// Estrarre il percorso della richiesta dalla riga del log
const match = line.match(/"GET ([^ ]+) HTTP/)
if (!match) continue
try {
const requestUrl = new URL(match[1], 'http://localhost')
const query = requestUrl.searchParams.get('q')
if (query) queries.push(query) // URLSearchParams decodifica automaticamente
} catch {
// Ignorare le righe malformate — i log di accesso possono contenere voci troncate
}
}
return queries
}
const queries = await extractSearchQueries('/var/log/nginx/access.log')
console.log(queries)
// ['standing desk&brand:Northwood', 'ergonomic chair', 'monitor arm 27 inch']Analisi dei parametri di query in un server HTTP Node.js
import http from 'http'
// URL in ingresso: /api/products?q=standing+desk&warehouse=eu%2Dwest%2D1&minStock=10&cursor=eyJpZCI6MTIzfQ%3D%3D
const server = http.createServer((req, res) => {
// Costruire un URL completo — il secondo argomento è la base richiesta dal costruttore URL
const requestUrl = new URL(req.url!, 'http://localhost')
const searchQuery = requestUrl.searchParams.get('q') // 'standing desk'
const warehouseId = requestUrl.searchParams.get('warehouse') // 'eu-west-1'
const minStock = Number(requestUrl.searchParams.get('minStock') ?? '0')
const cursor = requestUrl.searchParams.get('cursor') // 'eyJpZCI6MTIzfQ=='
if (!warehouseId) {
res.writeHead(400, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ error: 'warehouse parameter is required' }))
return
}
const cursorData = cursor ? JSON.parse(Buffer.from(cursor, 'base64').toString()) : null
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ searchQuery, warehouseId, minStock, cursorData }))
})
server.listen(3000)Quando hai bisogno di ispezionare un URL codificato durante lo sviluppo — per capire cosa sta inviando un webhook prima di scrivere il codice di analisi — incollalo direttamente nel Decodificatore URL di ToolDeck per vedere la forma decodificata istantaneamente senza eseguire uno script.
Decodifica URL dalla riga di comando
Per script shell, pipeline CI o ispezione rapida di stringhe codificate, diversi approcci funzionano senza scrivere uno script completo. I one-liner di Node.js sono multipiattaforma; su macOS e Linux, python3 è sempre disponibile.
# ── One-liner Node.js ──────────────────────────────────────────────────
# Decodificare un singolo valore codificato in percentuale
node -e "console.log(decodeURIComponent(process.argv[1]))" "S%C3%A3o%20Paulo%20%26%20Rio"
# São Paulo & Rio
# Analizzare una query string e stampare ogni coppia chiave=valore (decodificata)
node -e "
const params = new URLSearchParams(process.argv[1])
for (const [k, v] of params) console.log(`${k} = ${v}`)
" "q=standing+desk&warehouse=eu%2Dwest%2D1&minStock=10"
# q = standing desk
# warehouse = eu-west-1
# minStock = 10
# Decodificare e formattare un corpo JSON codificato URL (comune nel debug dei webhook)
node -e "
const raw = decodeURIComponent(process.argv[1])
console.log(JSON.stringify(JSON.parse(raw), null, 2))
" '%7B%22event%22%3A%22purchase%22%2C%22amount%22%3A149.99%2C%22currency%22%3A%22EUR%22%7D'
# {
# "event": "purchase",
# "amount": 149.99,
# "currency": "EUR"
# }
# ── One-liner Python (disponibile sulla maggior parte dei sistemi macOS/Linux) ─────────────
# unquote_plus decodifica anche + come spazio — corretto per i dati codificati come form
python3 -c "
from urllib.parse import unquote_plus
import sys
print(unquote_plus(sys.argv[1]))
" "Standing+Desk+%26+Ergonomic+Chair"
# Standing Desk & Ergonomic Chair
# ── curl — registrare e decodificare un URL di reindirizzamento da un header di risposta ──────────
curl -sI "https://api.example.com/short/abc123" | grep -i location | node -e "
const line = require('fs').readFileSync('/dev/stdin', 'utf8')
const url = line.replace(/^location:s*/i, '').trim()
console.log(decodeURIComponent(url))
"Decodifica tollerante con decode-uri-component
Il decodeURIComponent() integrato lancia un URIError su qualsiasi sequenza malformata — incluso un %finale senza due cifre esadecimali seguenti. Nel codice di produzione che elabora URL forniti dall'utente o da terze parti — log di query di ricerca, URL di click da campagne email, dati web scrappati — le sequenze malformate sono abbastanza comuni da causare crash. Il pacchetto decode-uri-component (~30 milioni di download settimanali su npm) gestisce le sequenze malformate in modo tollerante restituendo la sequenza originale invariata invece di lanciare un errore.
npm install decode-uri-component # o pnpm add decode-uri-component
import decodeUriComponent from 'decode-uri-component'
// La funzione nativa lancia un errore con input malformato — può mandare in crash un request handler
try {
decodeURIComponent('product%name%') // ❌ URIError: URI malformed
} catch (e) {
console.error('Nativa ha lanciato:', (e as Error).message)
}
// decode-uri-component restituisce la sequenza raw invece di lanciare
console.log(decodeUriComponent('product%name%'))
// product%name% ← le sequenze malformate vengono lasciate invariate, senza errori
// Le sequenze valide vengono decodificate correttamente
console.log(decodeUriComponent('S%C3%A3o%20Paulo%20%26%20Rio'))
// São Paulo & Rio
// Misto: sequenze valide decodificate, non valide preservate
console.log(decodeUriComponent('Berlin%20Office%20%ZZ%20HQ'))
// Berlin Office %ZZ HQ ← %ZZ non è hex valido — mantenuto invariato
// Uso pratico in un pipeline di elaborazione log
const rawSearchQueries = [
'standing%20desk%20ergonomic',
'price%3A%5B200+TO+800%5D',
'50%25+off', // ← lancerebbe un errore con decodeURIComponent (% isolato)
'wireless%20keyboard%20%26%20mouse',
]
const decoded = rawSearchQueries.map(q => decodeUriComponent(q))
console.log(decoded)
// ['standing desk ergonomic', 'price:[200+TO+800]', '50%25+off', 'wireless keyboard & mouse']Usa decodeURIComponent() con try/catch nel codice applicativo dove vuoi sapere immediatamente se arriva un input inatteso. Ricorri a decode-uri-componentnei pipeline di dati, nei processori di log e negli handler webhook dove vuoi continuare l'elaborazione anche quando alcuni input contengono codifiche non valide.
Gestione di stringhe codificate in percentuale malformate
Un % isolato, una sequenza incompleta come %A o una coppia non valida come %GH fanno sì che decodeURIComponent() lanci URIError: URI malformed. Qualsiasi input controllato dall'utente — query di ricerca, frammenti URL, campi form contenenti URL, parametri da link di campagne email — può contenere queste sequenze. Un wrapper sicuro è indispensabile per qualsiasi codice esposto esternamente.
Wrapper di decodifica sicura per scenari comuni
// ── 1. Decodifica sicura base — restituisce la stringa originale in caso di errore ─────────────
function safeDecode(encoded: string): string {
try {
return decodeURIComponent(encoded)
} catch {
return encoded // restituire l'input raw se la decodifica fallisce — non crashare mai
}
}
// ── 2. Decodifica sicura + gestione di + come spazio (per valori codificati come form) ─────────
function safeFormDecode(formEncoded: string): string {
try {
return decodeURIComponent(formEncoded.replace(/+/g, ' '))
} catch {
return formEncoded.replace(/+/g, ' ') // almeno sostituire + anche se il resto fallisce
}
}
// ── 3. Parser sicuro di query string completa → oggetto semplice ──────────────────────
function parseQueryString(queryString: string): Record<string, string> {
const result: Record<string, string> = {}
try {
const params = new URLSearchParams(queryString)
for (const [key, value] of params) {
result[key] = value // URLSearchParams gestisce tutta la decodifica internamente
}
} catch {
// Restituire silenziosamente vuoto per input completamente malformato
}
return result
}
// Utilizzo
console.log(safeDecode('S%C3%A3o%20Paulo')) // São Paulo
console.log(safeDecode('search%20for%2050%25+off')) // search for 50% off (% isolato)
// → in realtà corretto; % qui è %25
console.log(safeDecode('malformed%string%')) // malformed%string% (senza errori)
console.log(safeFormDecode('standing+desk+pro')) // standing desk pro
console.log(parseQueryString('q=hello+world&tag=node%20js&page=2'))
// { q: 'hello world', tag: 'node js', page: '2' }Errori comuni
Ho visto questi quattro pattern causare corruzioni silenziose di dati o crash imprevisti in produzione — di solito solo quando un valore contiene un carattere speciale, il che significa che passano attraverso i test unitari e emergono con dati utente reali.
Errore 1 — Doppia decodifica di un valore URLSearchParams
Problema: URLSearchParams.get() restituisce una stringa già decodificata. Chiamare decodeURIComponent() sul risultato decodifica il valore due volte — convertendo qualsiasi % rimasto nell'output decodificato in %25, corrompendo i dati. Soluzione: usa il valore di URLSearchParams.get() direttamente — nessuna decodifica aggiuntiva è necessaria.
// ❌ URLSearchParams ha già decodificato — decodificare di nuovo corrompe i valori con %
const qs = new URLSearchParams('rate=50%25&redirect=https%3A%2F%2Fdashboard.internal%2F')
const rawRate = qs.get('rate') // '50%' ← già decodificato
const wrongRate = decodeURIComponent(rawRate)
// '50%25' ← % è stato decodificato in %25 al secondo passaggio — ora sbagliato di nuovo// ✅ Usare URLSearchParams.get() direttamente — la decodifica è automatica
const qs = new URLSearchParams('rate=50%25&redirect=https%3A%2F%2Fdashboard.internal%2F')
const rate = qs.get('rate') // '50%' ← corretto, nessun passaggio aggiuntivo necessario
const redirect = qs.get('redirect') // 'https://dashboard.internal/'
const parsed = new URL(redirect!) // Sicuro da costruire — già decodificato
console.log(parsed.hostname) // dashboard.internalErrore 2 — Non decodificare + come spazio per i dati codificati come form
Problema: I form e alcune librerie OAuth codificano gli spazi come + (application/x-www-form-urlencoded). Chiamare decodeURIComponent() su questi dati lascia + come segno più letterale. Soluzione: usa URLSearchParams per analizzare i dati codificati come form, o sostituisci + con uno spazio prima di chiamare decodeURIComponent().
// ❌ decodeURIComponent tratta + come segno più letterale, non come spazio
// L'endpoint del token OAuth invia: grant_type=authorization_code&code=SplxlOBeZQQYb...
// &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
// Alcune implementazioni OAuth legacy usano anche + per gli spazi nei codici
const formBody = 'customer_name=Marco+Rossi&product=Standing+Desk+Pro&qty=2'
const [, rawVal] = formBody.split('&')[0].split('=')
const name = decodeURIComponent(rawVal)
console.log(name) // 'Marco+Rossi' ← + non convertito in spazio// ✅ Usare URLSearchParams — segue la specifica application/x-www-form-urlencoded
const formBody = 'customer_name=Marco+Rossi&product=Standing+Desk+Pro&qty=2'
const params = new URLSearchParams(formBody)
console.log(params.get('customer_name')) // 'Marco Rossi' ← + correttamente decodificato come spazio
console.log(params.get('product')) // 'Standing Desk Pro'Errore 3 — Usare decodeURI() per i valori dei singoli parametri di query
Problema: decodeURI() non decodifica %26 (&), %3D (=) né %3F(?) — caratteri comunemente codificati all'interno dei valori dei parametri. Usarlo per decodificare un singolo valore lascia quelle sequenze intatte, producendo silenziosamente un output errato. Soluzione: usa decodeURIComponent() per i valori singoli; riserva decodeURI() per le stringhe URL complete.
// ❌ decodeURI non decodifica & e = — il valore rimane rotto const encodedFilter = 'status%3Dactive%26tier%3Dpremium%26region%3Deu-west' const filter = decodeURI(encodedFilter) console.log(filter) // 'status%3Dactive%26tier%3Dpremium%26region%3Deu-west' ← %3D e %26 non decodificati
// ✅ decodeURIComponent decodifica tutte le sequenze inclusi & e = const encodedFilter = 'status%3Dactive%26tier%3Dpremium%26region%3Deu-west' const filter = decodeURIComponent(encodedFilter) console.log(filter) // 'status=active&tier=premium®ion=eu-west' ← correttamente decodificato
Errore 4 — Non avvolgere decodeURIComponent in try/catch per l'input utente
Problema: Un %isolato non seguito da due cifre esadecimali — comune nelle query di ricerca digitate dagli utenti (“50% di sconto”, “100% cotone”) — fa sì che decodeURIComponent() lanci URIError: URI malformed, mandando in crash il request handler se non catturato. Soluzione: avvolgi sempre in try/catchquando l'input proviene da dati utente, frammenti URL o sistemi esterni.
// ❌ L'utente ha digitato '100% cotton' in una casella di ricerca — il % isolato manda in crash il server
// GET /api/search?q=100%25+cotton ← Questo caso specifico è corretto (%25 = %)
// GET /api/search?q=100%+cotton ← Questo crasha (% non seguito da 2 cifre hex)
app.get('/api/search', (req, res) => {
const query = decodeURIComponent(req.query.q as string)
// ↑ lancia URIError: URI malformed per '100% cotton' → errore 500 non gestito
})// ✅ Avvolgere in try/catch — tornare all'input raw se la decodifica fallisce
app.get('/api/search', (req, res) => {
let query: string
try {
query = decodeURIComponent(req.query.q as string)
} catch {
query = req.query.q as string // usare il valore raw invece di crashare
}
// continuare l'elaborazione in sicurezza — query è decodificata o raw
})decodeURIComponent vs decodeURI vs URLSearchParams — Confronto rapido
| Metodo | Decodifica %XX | Decodifica + come spazio | Lancia su malformato | Decodifica & = ? # | Caso d'uso | Richiede installazione |
|---|---|---|---|---|---|---|
| decodeURIComponent() | ✅ tutti | ❌ no | ✅ URIError | ✅ sì | Valori singoli e segmenti di percorso | No |
| decodeURI() | ✅ maggior parte | ❌ no | ✅ URIError | ❌ no | Stringhe URL complete | No |
| URLSearchParams | ✅ tutti | ✅ sì | ❌ silenzioso | ✅ sì | Analisi query string con decodifica automatica | No |
| Costruttore URL | ✅ tutti | ✅ sì | ✅ TypeError | ✅ sì | Analisi e normalizzazione di URL completi | No |
| decode-uri-component | ✅ tutti | ❌ no | ❌ silenzioso | ✅ sì | Decodifica in batch con tolleranza a input malformati | npm install |
| querystring.unescape() | ✅ tutti | ❌ no | ❌ silenzioso | ✅ sì | Node.js legacy (deprecato dalla v16) | No (integrato) |
Per la stragrande maggioranza dei casi, la scelta si riduce a tre scenari. Usa URLSearchParams per analizzare le query string — gestisce la decodifica, la regola del + come spazio e le chiavi ripetute automaticamente. Usa decodeURIComponent() (avvolto in try/catch) per un singolo valore o segmento di percorso, soprattutto quando ti aspetti barre codificate come %2F all'interno di un segmento. Usa decodeURI() solo quando hai una stringa URL completa con caratteri non ASCII nel percorso e hai bisogno che i caratteri strutturali (/ ? & =) rimangano codificati nell'output.
Domande frequenti
Strumenti correlati
Per una decodifica con un clic senza scrivere codice, incolla la tua stringa codificata in percentuale direttamente nel Decodificatore URL di ToolDeck — decodifica istantaneamente nel browser, con il risultato pronto per essere copiato nel tuo codice o terminale.
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.
Marcus specialises in JavaScript performance, build tooling, and the inner workings of the V8 engine. He has spent years profiling and optimising React applications, working on bundler configurations, and squeezing every millisecond out of critical rendering paths. He writes about Core Web Vitals, JavaScript memory management, and the tools developers reach for when performance really matters.