Toda URL que você já digitou ou clicou passou por codificação de URLs. O espaço em “meu arquivo.txt” se torna %20. O & em uma string de consulta se torna %26. O / em um caminho permanece como / — mas apenas porque o codificador sabe quais caracteres são seguros e quais não são.
A codificação de URLs (oficialmente “codificação por porcentagem”) é como URLs representam caracteres que não estão no conjunto de caracteres não reservados. É uma transformação simples, mas os edge cases são onde a maioria dos bugs de API vive.
Os caracteres não reservados
Esses caracteres são sempre seguros em URLs e nunca precisam de codificação:
A-Z a-z 0-9 - _ . ~
Tudo mais — espaços, barras, E commercial, sinais de igual, caracteres não ASCII — precisa ser codificado como um sinal de porcentagem seguido por dois dígitos hexadecimais:
- Espaço →
%20 &→%26=→%3D/→%2F?→%3F#→%23
A codificação são os valores de bytes UTF-8 do caractere, cada um representado por dois dígitos hexadecimais. Um caractere multi-byte como é (UTF-8: 0xC3 0xA9) se torna %C3%A9.
Onde a codificação importa
Parâmetros de consulta. Aqui é onde a codificação de URLs causa mais bugs. Se um valor de consulta contiver & ou =, o parser de URL divide nesses caracteres e quebra a estrutura do parâmetro:
/search?q=cats&dogs ← ambíguo: "dogs" é um parâmetro separado?
/search?q=cats%26dogs ← correto: "cats&dogs" é um único valor
Toda biblioteca HTTP tem uma função para codificar parâmetros de consulta. Use-a. Nunca concatene strings em uma string de consulta manualmente.
Caminhos. Espaços em nomes de arquivo precisam de codificação:
/download/my file.pdf ← quebrado
/download/my%20file.pdf ← funciona
Mas barras dentro de um segmento de caminho também precisam de codificação:
/file/path/segment ← dois segmentos: "file/path" dividido por /
/file%2Fpath/segment ← um segmento: "file/path"
Caracteres não ASCII. URLs são apenas ASCII. Qualquer caractere não ASCII (letras acentuadas, caracteres CJK, emojis) deve ser codificado por porcentagem:
café→caf%C3%A9日本語→%E6%97%A5%E6%9C%AC%E8%AA%9E🎉→%F0%9F%8E%89
A maioria dos navegadores exibe a versão decodificada na barra de endereço, mas os bytes reais enviados pela rede são codificados.
A armadilha da dupla codificação
O bug de codificação de URL mais comum: codificar uma string já codificada.
Pegue o caminho /hello%20world. Se você codificá-lo novamente em URL, o % se torna %25:
/hello%20world ← original (correto)
/hello%2520world ← duplamente codificado (quebrado)
O servidor decodifica %25 para %, depois vê %20 e o decodifica para um espaço. Você termina com /hello world — mas apenas se o servidor fizer uma única decodificação. Se fizer duas decodificações (alguns fazem), você obtém o original de volta. O comportamento é inconsistente e imprevisível.
A regra: codifique uma vez, decodifique uma vez. Se você receber uma string codificada, decodifique antes de recodificar. Verifique se o construtor de URL da sua biblioteca HTTP espera valores brutos ou pré-codificados — a diferença entre path e rawPath na maioria dos frameworks importa.
Codificação de string de consulta
Strings de consulta têm suas próprias regras de codificação. A diferença principal dos caminhos: + representa um espaço em strings de consulta (application/x-www-form-urlencoded), mas %20 também representa um espaço. Ambos são válidos, mas vêm de padrões diferentes:
application/x-www-form-urlencoded(submissões de formulário) —+para espaços- Codificação por porcentagem (URLs) —
%20para espaços
A maioria das APIs modernas aceita ambos. Mas se você estiver analisando uma string de consulta de uma submissão de formulário, + → espaço. Se estiver construindo uma URL, %20 → espaço. Misturá-los causa bugs sutis onde espaços se tornam sinais + ou vice-versa.
Use a função de codificação de URL da sua linguagem. Ela lida com a distinção para você.
Codificação vs escape
Codificação de URL não é escape de HTML. Eles resolvem problemas diferentes:
- Codificação de URL (
%20) — para caracteres em URLs. Previne que caracteres sejam interpretados como sintaxe de URL. - Escape de HTML (
&,<) — para caracteres em HTML. Previne que caracteres sejam interpretados como tags ou entidades HTML.
Uma URL dentro de um href HTML precisa de ambos: codifique os valores dos parâmetros em URL, depois codifique toda a URL em HTML:
<a href="/search?q=cats%26d&page=1">
O %26 impede que & seja interpretado como separador de consulta. O & impede que & seja interpretado como início de entidade HTML.
Armadilhas comuns
Espaços em diferentes contextos. %20 em uma URL, + em um corpo de formulário, %2520 se você acidentalmente codificou duplamente. Saiba em qual contexto você está.
Fragmentos de hash. Tudo após # não é enviado ao servidor. Se você codificar uma URL com um fragmento e o fragmento contiver ? ou &, o servidor nunca os vê. O fragmento é apenas do lado do cliente.
Codificar o sinal de porcentagem. % → %25. Se um % literal aparecer em seus dados (como uma senha com %), deve ser codificado. Se você não codificar, o parser interpreta os dois caracteres após ele como uma sequência hexadecimal.
Normalização Unicode. Alguns sistemas normalizam Unicode antes de codificar. café (com acento combinante) e café (com é pré-composto) codificam para diferentes sequências de porcentagem. Isso causa problemas com nomes de arquivo e nomes de domínio internacionalizados.
Referência rápida | Caractere | Codificado por porcentagem | Contexto | |———–|–––––––––––––|–––––| | Espaço | %20 | URL | | Espaço | + | Corpo de formulário | | & | %26 | String de consulta | | = | %3D | String de consulta | | / | %2F | Segmento de caminho | | ? | %3F | String de consulta | | # | %23 | Caminho/consulta | | % | %25 | Em todo lugar | | + | %2B | String de consulta |
Experimente
Se você tem uma URL ou string codificada que precisa decodificar (ou dados brutos que precisa codificar), use uma ferramenta local para que a conversão aconteça em seu navegador — nenhum dado é enviado a lugar nenhum.