Scommetto che hai avuto almeno un bug causato da spazi o caratteri speciali in un URL. Magari una ricerca con & ha provocato un comportamento strano. O hai visto %20 in un URL chiedendoti cosa fosse. Facciamo chiarezza una volta per tutte.

Perché gli URL hanno bisogno di codifica

Gli URL possono contenere solo un insieme limitato di caratteri. La specifica RFC 3986 definisce i caratteri "non riservati" che sono sempre sicuri: A-Z, a-z, 0-9, -, _, . e ~. Tutto il resto — spazi, &, =, ?, caratteri non-ASCII come ñ o 日本語 — deve essere codificato in percentuale.

Come funziona la codifica percentuale

È piuttosto semplice: prendi il valore in byte UTF-8 del carattere e rappresenti ogni byte come % seguito da due cifre esadecimali.

Esempi:

  • Spazio → %20
  • &%26
  • =%3D
  • é%C3%A9 (due byte in UTF-8)
  • %E6%97%A5 (tre byte in UTF-8)

Quindi Hello World diventa Hello%20World nel percorso di un URL.

Il bug numero 1: la doppia codifica

Questo è l'errore di codifica URL più comune che vedo, ed è subdolo. Codifichi una stringa, poi la passi a una funzione che la codifica di nuovo. Ora %20 (uno spazio già codificato) diventa %2520 perché il % stesso viene codificato.

Esempio del problema:

javascript

La soluzione: codificare i valori una sola volta, al livello giusto. Non codificare cose che sono già codificate.

Segno più vs. %20 — Sì, è confuso

Nelle query string degli URL, gli spazi possono essere + o %20. La convenzione del + viene dalla codifica dei form HTML (application/x-www-form-urlencoded). Nei percorsi URL, solo %20 è valido.

Quindi https://example.com/hello world → il percorso si codifica come https://example.com/hello%20world

Ma https://example.com/search?q=hello world → la query può essere ?q=hello+world o ?q=hello%20world

encodeURI vs. encodeURIComponent

JavaScript ti offre due funzioni, e usare quella sbagliata è un errore classico:

  • encodeURI() — Codifica un URL completo. Lascia intatti :, /, ?, #, &, = perché sono parti strutturali dell'URL.
  • encodeURIComponent() — Codifica un componente URL (come il valore di un parametro di query). Codifica ANCHE :, /, ?, #, &, = perché potrebbero far parte dei dati.

Regola pratica: usa encodeURIComponent() per i valori, mai per URL interi. La documentazione MDN spiega la differenza magnificamente.

Altri linguaggi

  • Python: urllib.parse.quote() per i percorsi, urllib.parse.urlencode() per le query string — documentazione qui
  • Java: URLEncoder.encode() (usa + per gli spazi — attenzione!)
  • PHP: urlencode() per le query string, rawurlencode() per i percorsi

Consigli rapidi

  • Codifica sempre i valori dei parametri, mai URL interi
  • Decodifica una sola volta lato ricezione — non passare valori codificati attraverso più livelli
  • Testa con casi limite: spazi, &, =, #, caratteri non-ASCII e emoji

Costruire URL in modo sicuro in JavaScript

Il modo corretto di costruire URL con parametri di query è usare le API native URL e URLSearchParams. Gestiscono tutta la codifica per te:

javascript

Nota come URLSearchParams usa + per gli spazi (convenzione della codifica form HTML) e codifica correttamente il & nel valore perché non venga confuso con il & che separa i parametri. Questo è molto più sicuro della concatenazione di stringhe.

Errori comuni nella codifica URL

1. Codificare l'intero URL invece dei soli valori. Se esegui encodeURIComponent() su un URL completo, codificherà i caratteri ://, /, ? e & — rendendo l'URL completamente inutilizzabile. Codifica solo i singoli valori dei parametri.

2. Dimenticare di codificare i frammenti hash. Il carattere # in un URL inizia un identificatore di frammento. Se i tuoi dati contengono un # e non lo codifichi, tutto ciò che segue scompare dal punto di vista del server. Il server non vede mai gli identificatori di frammento — sono solo lato client.

3. Non gestire i nomi di dominio internazionalizzati (IDN). I nomi di dominio con caratteri non-ASCII come example.日本 necessitano di un trattamento speciale chiamato codifica Punycode. Questa è separata dalla codifica percentuale e si applica solo alla parte hostname dell'URL.

4. Codificare gli spazi in modo incoerente. Alcune parti del tuo sistema potrebbero codificare gli spazi come + e altre come %20. Questo di solito funziona bene per la decodifica, ma può causare problemi con il confronto degli URL e la cache. Scegli una convenzione e mantienila.

Riferimento rapido codifica percentuale

CarattereCodificatoPerché necessita di codifica
Spazio%20 o +Non permesso negli URL
&%26Separa i parametri di query
=%3DSepara chiave da valore
?%3FInizia la query string
#%23Inizia l'identificatore di frammento
%%25Il carattere di escape stesso
/%2FSeparatore di percorso
@%40Usato nella sezione userinfo

Codifica URL in diversi contesti

La codifica URL non è solo per gli URL del browser. La incontrerai in queste situazioni comuni:

  • Richieste API: I parametri di query nelle chiamate API REST necessitano di codifica appropriata, specialmente se contengono input dell'utente
  • URL di reindirizzamento: Quando passi un URL di ritorno come parametro (come ?redirect=https://...), l'intero URL di reindirizzamento deve essere codificato come valore
  • Flussi OAuth: Gli URL di callback OAuth e i parametri state sono notoriamente complicati perché coinvolgono più livelli di codifica URL
  • Deep link: I deep link mobili seguono le stesse regole di codifica URL, ma alcune piattaforme hanno requisiti aggiuntivi

Debug dei problemi di codifica URL

Quando qualcosa va storto con la codifica URL, ecco la mia checklist di debug:

1. Controlla la doppia codifica — Cerca %25 nell'URL, il che significa che un % è stato codificato due volte

2. Controlla la richiesta grezza — Usa la scheda Network dei DevTools del browser per vedere esattamente quale URL è stato inviato, prima che il browser mostri la versione decodificata

3. Confronta codificato vs. decodificato — Incolla l'URL problematico in un decoder per vedere cosa contiene effettivamente

4. Controlla la decodifica lato server — Alcuni framework decodificano automaticamente i parametri URL, e farlo manualmente in aggiunta causa problemi

L'anatomia di un URL

Ok, facciamo un passo indietro. Prima di approfondire la codifica, devi davvero capire di cosa è fatto un URL. Lo so, lo so — usi gli URL da tutta la carriera. Ma scommetto che non conosci tutte le parti con i loro nomi ufficiali. La maggior parte degli sviluppatori no, ed è lì che inizia la confusione sulla codifica.

Secondo RFC 3986, un URL ha questa struttura:

plaintext

Lascia che ti guidi attraverso ogni parte:

  • Scheme (https, ftp, mailto) — Il protocollo. Nessuna codifica necessaria qui, sono sempre lettere ASCII.
  • Authority — Questo include l'opzionale user:password@ (che nel 2026 non dovresti praticamente mai usare), l'host (nome di dominio o IP) e un numero di porta opzionale.
  • Path (/search/results) — La parte gerarchica. Le barre / separano i segmenti. All'interno di ogni segmento, devi codificare i caratteri speciali, ma NON codifichi le barre stesse.
  • Query (?q=hello&lang=en) — Coppie chiave-valore dopo il ?. Il & separa le coppie, = separa le chiavi dai valori. Codifichi le chiavi e i valori, ma non i & e = strutturali.
  • Fragment (#section-2) — La parte dopo #. Questa è interessante — non viene mai inviata al server. È puramente lato client. Ma devi comunque codificare i caratteri speciali al suo interno.

Ecco cosa confonde le persone: diverse parti dell'URL hanno diverse regole di codifica. Una / va benissimo nel percorso (è un separatore!) ma deve essere codificata come %2F se appare all'interno del valore di un parametro di query. Un @ va bene nella sezione authority ma dovrebbe essere codificato nel percorso. Ecco perché le funzioni di codifica generiche causano così tanti bug.

Pensala così: l'URL è una frase con regole grammaticali. I caratteri speciali sono la punteggiatura. Non codificheresti una virgola che viene effettivamente usata come virgola — codifichi solo una virgola che fa parte dei dati e potrebbe essere confusa con la punteggiatura.

encodeURI vs. encodeURIComponent: Il campo minato JavaScript

Ok, questo argomento mi fa impazzire perché vedo gli sviluppatori sbagliare CONTINUAMENTE. JavaScript ti dà due funzioni di codifica, e suonano quasi identiche, ma usare quella sbagliata rovinerà la tua giornata.

Lascia che lo spieghi chiaramente:

encodeURI() è progettato per codificare un URL completo. Codifica i caratteri non sicuri ma lascia in pace quelli strutturali — cose come :, /, ?, #, &, =, @. Perché se stai codificando un URL completo, ovviamente non vuoi rompere la struttura dell'URL.

encodeURIComponent() è progettato per codificare un singolo valore che va dentro un URL. Codifica TUTTO tranne lettere, cifre e - _ . ~. Questo include :, /, ?, #, &, = — perché quando questi appaiono in un valore, sono dati, non struttura.

Ecco un confronto che rende tutto cristallino:

CarattereencodeURI()encodeURIComponent()
:: (invariato)%3A
// (invariato)%2F
?? (invariato)%3F
## (invariato)%23
&& (invariato)%26
== (invariato)%3D
@@ (invariato)%40
Spazio%20%20
é%C3%A9%C3%A9

Ora diventa spaventoso. Guarda cosa succede quando usi la funzione sbagliata:

javascript

E l'errore opposto è altrettanto grave:

javascript

La regola d'oro: encodeURIComponent per i valori, encodeURI per URL completi. O ancora meglio, usa semplicemente la API URL e lascia che il browser se ne occupi. Seriamente, le classi URL e URLSearchParams esistono per un motivo. Consulta la documentazione MDN di encodeURIComponent e la documentazione MDN di encodeURI per tutti i dettagli.

Codifica URL in diversi linguaggi

JavaScript non è l'unico linguaggio con funzioni di codifica URL confuse. Ogni linguaggio ha le sue particolarità, e non scherzo, alcuni sono ancora più confusi della coppia di JavaScript.

Python — In realtà piuttosto ragionevole, una volta trovato il modulo giusto:

python

Java — Qui le cose si fanno strane. URLEncoder è stato progettato per la codifica dei form HTML, non per la codifica URL generale. Quindi gli spazi diventano + invece di %20:

java

C# — .NET in realtà ti dà gli strumenti giusti, ma ci sono tipo cinque metodi diversi che fanno cose leggermente diverse:

csharp

PHP — Oh PHP. Ovviamente hai due funzioni con nomi quasi identici che fanno cose leggermente diverse:

php

Go — Pulito e sensato, come Go tende ad essere:

go

La conclusione? Ogni linguaggio gestisce la questione + vs %20 diversamente, e ogni linguaggio ha almeno una funzione che ti sorprenderà. Controlla sempre la documentazione del linguaggio che stai usando. Non dare per scontato che funzioni come JavaScript.

Unicode negli URL: Il Far West

Ok, qui le cose diventano DAVVERO interessanti. Cosa succede quando metti caratteri non-ASCII in un URL? Tipo, cosa succede se vuoi un URL con giapponese, arabo o — non scherzo — emoji?

La risposta coinvolge due sistemi completamente diversi, e confonderli è un errore classico.

Per il percorso e la query: Usi la codifica percentuale. Prendi i byte UTF-8 del carattere e codifichi ciascuno. Quindi café diventa caf%C3%A9. Il tuo browser lo fa automaticamente e di solito ti mostra la versione bella nella barra degli indirizzi, ma dietro le quinte sta inviando la versione codificata.

Per i nomi di dominio: La codifica percentuale NON viene usata. Invece, c'è un sistema chiamato Punycode. Converte i nomi di dominio Unicode in stringhe compatibili ASCII che iniziano con xn--.

Guarda qui:

  • café.comxn--caf-dma.com
  • münchen.dexn--mnchen-3ya.de
  • 例え.jpxn--r8jz45g.jp

Perché due sistemi diversi? Perché il DNS (il sistema che trasforma i nomi di dominio in indirizzi IP) è stato costruito negli anni '80 e supporta solo ASCII. Quindi hanno dovuto inventare un modo per infilare Unicode in stringhe ASCII — e Punycode è quell'invenzione. Le parti percorso e query di un URL, d'altro canto, sono gestite dai web server che possono gestire byte codificati in percentuale.

In realtà esiste un'intera specifica per Unicode negli URL chiamata IRI (Internationalized Resource Identifiers) definita nell'RFC 3987. Un IRI è fondamentalmente un URL che permette caratteri Unicode direttamente. I browser convertono gli IRI in URI dietro le quinte.

E sì, i domini emoji esistono. 💩.la è un dominio reale (o lo è stato a un certo punto). Viene codificato in Punycode come xn--ls8h.la. Non consiglio di usare domini emoji per qualcosa di serio, ma è una prova divertente che il sistema funziona.

Un'insidia con Unicode negli URL: diverse rappresentazioni Unicode dello "stesso" carattere. Per esempio, é può essere rappresentato come un singolo codepoint (U+00E9) o come e + un accento combinante (U+0065 + U+0301). Questi producono stringhe codificate diverse! Lo standard WHATWG URL raccomanda la normalizzazione NFC, ma non tutti i sistemi seguono questo in modo coerente.

Doppia codifica: Il bug che perseguita i tuoi sogni

Ho menzionato la doppia codifica prima, ma merita un approfondimento dedicato perché questo bug ha probabilmente sprecato più ore collettive di sviluppo di qualsiasi altro problema legato agli URL. Ci sono passato — più volte.

Ecco lo scenario base:

plaintext

Cos'è successo? Quando codifichi hello%20world una seconda volta, il carattere % viene codificato in %25. Quindi %20 diventa %2520. Il server vede la stringa letterale %20 invece di uno spazio.

Sembra ovvio quando lo spiego così, ma nelle codebase reali è incredibilmente subdolo. Ecco gli scenari in cui la doppia codifica ti colpisce:

Catene di proxy. Invii una richiesta al server A, che la inoltra al server B. Se entrambi i server codificano l'URL, boom — doppia codifica. API gateway come Kong, AWS API Gateway o reverse proxy nginx sono colpevoli comuni.

Catene di reindirizzamento. L'utente va alla pagina A, viene reindirizzato alla pagina B con un parametro ?returnUrl=..., e la pagina B reindirizza di nuovo con l'URL di ritorno come parametro. Ogni reindirizzamento potrebbe ri-codificare l'URL. Dopo tre reindirizzamenti, il tuo URL è triplo-codificato e completamente rovinato.

"Helper" dei framework. Alcuni framework web codificano automaticamente i parametri URL. Se codifichi manualmente prima di passare al framework, ottieni doppia codifica. L'ho visto succedere con Spring Boot, middleware Express.js e il reversing degli URL di Django.

Come si rileva la doppia codifica? Cerca %25 nell'URL. È un segno di percentuale che è stato codificato, il che di solito significa che qualcosa è stato codificato due volte. Se vedi %2520, è uno spazio doppiamente codificato. Se vedi %253D, è un = doppiamente codificato.

Come risolvere:

javascript

La migliore difesa è stabilire confini chiari nel tuo codice: codifica ai bordi (subito prima di inviare una richiesta HTTP, o subito prima di costruire un URL da visualizzare), e passa stringhe grezze e non codificate internamente ovunque.

Limiti di lunghezza degli URL e cosa fare

Ecco qualcosa che ti sorprenderà: la specifica HTTP stessa NON definisce una lunghezza massima degli URL. RFC 3986 dice che gli URL dovrebbero avere "lunghezza illimitata". Ma il mondo reale non è d'accordo.

Diversi componenti nella catena hanno i propri limiti, e il più corto vince:

ComponenteLunghezza massima URL
Internet Explorer (RIP)2.083 caratteri
Chrome, Firefox, Safari~65.000+ caratteri
Apache (predefinito)8.190 caratteri
Nginx (predefinito)8.192 caratteri
IIS (predefinito)16.384 caratteri
AWS ALB8.192 caratteri
Cloudflare32.768 caratteri

Quel vecchio limite di 2.083 caratteri di IE governava tutto. Anche se IE è praticamente morto ora, alcuni sviluppatori e strumenti lo trattano ancora come vangelo. Ma in pratica, la maggior parte degli stack moderni può gestire URL molto più lunghi.

Detto questo, solo perché PUOI fare un URL di 65.000 caratteri non significa che DOVRESTI. Ecco alcuni motivi reali per tenere gli URL corti:

  • Log del server. Molti sistemi di logging troncano gli URL lunghi, rendendo il debug un incubo.
  • Copia e incolla. Gli utenti copiano e condividono URL. URL super-lunghi si rompono nelle email, messaggi chat e documenti.
  • SEO. I motori di ricerca generalmente raccomandano di tenere gli URL sotto i 2.000 caratteri.
  • Caching. Alcuni limiti delle chiavi di cache CDN e proxy sono basati sugli URL. URL più lunghi = più cache miss.

Quindi cosa fai quando il tuo URL diventa troppo lungo? Sono contento che tu l'abbia chiesto:

1. Usa POST invece di GET. Se stai inviando molti dati, mettili nel corpo della richiesta. Il corpo della richiesta non ha limiti pratici di dimensione. Questa è la soluzione più comune per form di ricerca complessi con molti filtri.

2. Usa URL shortener o ID di riferimento. Genera un token breve che mappa all'insieme completo di parametri memorizzato lato server. Quindi invece di /search?filter1=abc&filter2=def&filter3=... ottieni /search/saved/abc123.

3. Comprimi i tuoi parametri. Alcune app codificano in base64 un blob JSON compresso e lo mettono nell'URL. Non è elegante, ma funziona. Lo vedrai in strumenti come gli URL delle dashboard di Grafana.

Codifica dei form: application/x-www-form-urlencoded

Parliamo dell'elefante nella stanza che rende la codifica URL ancora più confusa: la codifica dei form HTML. Quando invii un form HTML con method="POST", il browser codifica i dati del form usando un formato chiamato application/x-www-form-urlencoded. E questo formato è QUASI uguale alla codifica percentuale standard, ma con una differenza chiave che fa impazzire tutti.

Gli spazi diventano + invece di %20.

Tutto qui. Questa è la differenza principale. Ma cavolo, quanta confusione causa.

plaintext

Perché esiste questa differenza? Ragioni storiche, ovviamente. La specifica della codifica form HTML precede la specifica della codifica URL, e usava + per gli spazi perché... beh, qualcuno negli anni '90 pensava che fosse più carino. E ora siamo bloccati con questo per sempre.

Quando invii un form HTML, il browser invia un header Content-Type: application/x-www-form-urlencoded, e il server sa di interpretare + come spazi. Ma se stai costruendo URL manualmente in JavaScript e usi + per gli spazi nella parte del percorso, il server vedrà dei segni più letterali. Che divertimento.

Ecco dove conta nella pratica:

javascript

E poi c'è multipart/form-data, che è una bestia completamente diversa. Quando il tuo form include upload di file (), il browser passa alla codifica multipart/form-data, che usa dei boundary per separare i campi invece dei segni &. Non usa affatto la codifica URL — ogni parte ha i suoi header e body. Se hai mai provato a fare il parsing manuale di una richiesta multipart, conosci il dolore.

Il consiglio pratico: usa URLSearchParams per le query string e i dati dei form. Usa FormData per gli upload di file. Non provare a codificare queste cose a mano a meno che non sia davvero, davvero necessario.

Provalo tu stesso

Stai lavorando con URL che sembrano sbagliati? Incollali nel nostro Decodificatore URL per vedere i caratteri effettivi. Hai bisogno di codificare un valore prima di metterlo in un URL? Il Codificatore URL lo gestisce istantaneamente. E per scomporre URL complessi nei loro componenti, usa il Parser URL per vedere ogni parte chiaramente.