Pular para o conteúdo principal

Codificar e decodificar URL

O Codificador e decodificador de URL aplica percent-encoding e decodifica texto no seu navegador. O modo importa mais do que parece: em uma query string, um espaço é +; em um path, é %20 — e decodificar o corpo de um formulário com o modo errado transforma “a + b” em “a b” sem nenhum erro.

Só local
Modo
Texto puro
0 B1 linhaLin. 1, Col. 1
Codificadosomente leitura
0 B1 linha

Como funciona o Codificar e decodificar URL?

“URL encoding” nomeia três codificações diferentes, e escolher a errada produz um bug que nunca lança exceção.

Percent-encoding não é codificação de formulário

O percent-encoding do RFC 3986 escreve um espaço como %20. O formato application/x-www-form-urlencoded — o que uma query string e o corpo de um POST de formulário realmente usam — o escreve como +, o que significa que um sinal de mais literal precisa ser escrito %2B. Decodifique o corpo de um formulário com decodeURIComponent e o + permanece intacto, então a busca “a + b” chega como “a + b” quando a pessoa digitou um sinal de mais, e como “a+b” quando digitou espaços. Um dos dois está errado, e nenhum dos dois gera erro.

encodeURIComponent deixa passar cinco caracteres que o RFC reserva

!, ', (, ) e * são reservados pelo RFC 3986 e deixados de lado pelo encodeURIComponent. Normalmente é inofensivo; deixa de ser quando uma assinatura é calculada sobre o formulário codificado, e é por isso que toda biblioteca de AWS SigV4 e OAuth 1.0a traz seu próprio codificador. A opção strict os codifica.

Cada componente da URL tem suas próprias regras

Um path pode conter / ; um valor de query não pode conter um & sem codificação, senão ele se divide em dois parâmetros. Essa é a diferença entre o modo componente e o modo URL completa: o primeiro codifica tudo que não é unreserved, o segundo preserva os caracteres que dão a estrutura de uma URL. Codificar uma URL inteira com encodeURIComponent produz uma string que deixa de ser uma URL.

Codificação dupla, e como enxergá-la

%2520 é um espaço que passou duas vezes por um codificador: o % do %20 foi ele próprio codificado como %25. Para quem folheia um log de relance, ele se lê como “%20”, e no valor decodificado produz um %20 literal. A ferramenta conta quantas passadas de decodificação a entrada sobrevive, então uma camada extra indevida fica visível em vez de misteriosa.

Dividir uma URL usa o parser da plataforma

O detalhamento dos componentes vem da própria implementação de URL do navegador, e não de uma expressão regular, porque o parsing de URL tem casos extremos demais — userinfo, literais IPv6, portas padrão, hosts com percent-encoding —, e o algoritmo WHATWG que já existe na plataforma é ao mesmo tempo mais curto e mais correto do que qualquer padrão de expressão regular. Chaves de query duplicadas são preservadas na ordem, já que muitas APIs dão significado a elas.

Entrada

q=a + b

Codificado

component: q%3Da%20%2B%20b
form:      q%3Da+%2B+b

Quais opções e casos-limite o Codificar e decodificar URL suporta?

Referência técnica e opções
ParâmetroTipoPadrãoComportamento e casos-limite
ComponenteencodeURIComponentpadrãoPara um único valor de query ou um segmento de caminho. Codifica tudo, exceto A–Z a–z 0–9 - _ . ~ e os cinco caracteres abaixo.
URL completaencodeURI—Para uma URL inteira. Mantém : / ? # [ ] @ ! $ & ' ( ) * + , ; = para que a URL continue sendo uma URL. Usar o modo componente aqui destrói a estrutura.
Formuláriox-www-form-urlencoded—Para uma query string ou um corpo POST. Espaço vira +, e um + literal vira %2B. Para decodificar corretamente, é preciso desfazer o + antes da decodificação por porcentagem; do contrário, um + literal vira espaço.
base64urlRFC 4648 §5—O alfabeto base64 seguro para URL: - e _ em vez de + e /, sem padding. É o que os segmentos de JWT usam.
RFC 3986 estritobooleanodesligadoTambém codifica ! ' ( ) *, que encodeURIComponent deixa em paz. Necessário quando a forma codificada alimenta uma assinatura.
Codificar tudobooleanodesligadoCodifica em porcentagem cada byte, inclusive os não reservados. Feio, válido e, às vezes, a única coisa que um gateway exigente aceita.
Conjunto de caracteresUTF-8sempreO que não é ASCII é codificado como seus bytes UTF-8, um %XX por byte, que é o que todo navegador e servidor atuais esperam.
Entrada malformadanotificadacom posiçãodecodeURIComponent lança um URIError puro e simples. Aqui, a sequência problemática é localizada e nomeada.

Perguntas frequentes

Por que meu espaço virou um + em vez de %20?

Porque você está no modo formulário, que é o correto para uma query string ou para o corpo de um POST de formulário — esse formato define o espaço como +. Em um segmento de path ou em um fragmento, o espaço é %20 e o + é um sinal de mais literal. As duas codificações estão corretas; usar a errada para a posição é o que corrompe o valor.

encodeURI ou encodeURIComponent?

encodeURIComponent para uma parte isolada — um valor de query, um segmento de path, um fragmento. encodeURI para uma URL inteira que você quer que continue sendo uma URL. O teste é simples: se o texto que você está codificando contém caracteres estruturais (um ?, um &, um /) e você quer que eles continuem funcionando, use encodeURI; se você quer que eles virem dados, use encodeURIComponent.

O que é %2520 e como ele surgiu?

Um espaço, codificado duas vezes. A primeira passada produziu %20; a segunda codificou esse % como %25, resultando em %2520. Normalmente significa que um valor foi codificado pelo código da aplicação e depois de novo por um framework ou um proxy. O contador de profundidade acima mostra quantas passadas a sua entrada sobrevive, então você consegue saber se uma camada está sobrando.

Por que !'()* não é codificado?

O encodeURIComponent os deixa de propósito, mesmo que o RFC 3986 os reserve. Quase sempre é inofensivo — até o momento em que a string codificada vira a entrada de uma assinatura, onde quem assina e quem verifica precisam coincidir byte a byte. É por isso que AWS SigV4 e OAuth 1.0a especificam cada um o seu próprio codificador. Ative o modo strict se estiver nessa situação.

base64url é o mesmo que base64?

Mesmo algoritmo, alfabeto diferente. O base64 usa + e /, que são significativos em uma URL, então o base64url os troca por - e _ e descarta o preenchimento com =, que tem significado em uma query string. Um JWT são três segmentos base64url unidos por pontos, e é por isso que um JWT pode ser colado direto em uma URL e um blob base64 não.

Minha entrada é enviada?

Não. Codificar e decodificar são operações de string que rodam no seu navegador — abra o painel Network e observe enquanto você digita. Aqui isso importa porque as URLs que as pessoas precisam decodificar costumam ser URLs de callback assinadas, redirecionamentos OAuth e tokens de sessão, ou seja, credenciais em uma forma que parece inofensiva.