Codificação · 5 de setembro de 2026

Codificação de URLs — por que %20 existe, quando codificar e o armsadilha que quebra APIs

A codificação de URLs transforma caracteres inseguros em sequências codificadas por porcentagem. É simples até deixar de ser — dupla codificação, parâmetros de consulta vs caminhos e a única regra que previne 90% dos bugs.

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) — %20 para 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&amp;page=1">

O %26 impede que & seja interpretado como separador de consulta. O &amp; 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.