Codificador / descodificador de URL

Codifique e descodifique URL, escolha o âmbito componente ou URL completo, e desdobre um URL nas suas partes.

Para um valor isolado, como um parâmetro de consulta. Escapa também / ? : @ & = + porque aí são dados e não estrutura.

Entrada
Saída

A saída aparecerá aqui

Para que serve a codificação percentual

Um URL só pode conter um conjunto pequeno de caracteres: as letras A–Z e a–z, os algarismos, alguns sinais como - . _ ~, e um conjunto de caracteres reservados que dão forma ao endereço — / ? # & = : @ e mais alguns. Tudo o resto, de um espaço a uma palavra em hebraico ou a um emoji, tem de ser representado indiretamente. A codificação percentual é essa representação: o carácter é convertido nos seus bytes UTF-8 e cada byte é escrito como um sinal de percentagem seguido de dois dígitos hexadecimais. Um espaço passa a %20, e א passa a %D7%90.

Os caracteres reservados são o caso interessante. São legais dentro de um URL, mas significam algo estrutural: ? abre a consulta, & separa parâmetros, = divide uma chave do seu valor. Quando um desses caracteres faz parte dos seus dados e não da estrutura, tem de ser codificado — caso contrário o analisador do outro lado lê-o como pontuação e parte o seu valor no sítio errado.

Componente ou URL completo — a distinção que parte ligações

Esta é a origem mais comum de erros com URL, e é por isso que esta ferramenta lhe pede para escolher um âmbito em vez de adivinhar.

  • O âmbito componente escapa também os delimitadores: / ? : @ & = + $ , e #. Use-o para um único dado — um termo de pesquisa, um destino de redirecionamento, um token — que vai ser colocado dentro de um URL maior.
  • O âmbito URL completo deixa esses delimitadores intactos e escapa apenas o que é realmente ilegal, como espaços e texto não ASCII. Use-o quando já tem um endereço completo bem estruturado que só precisa de limpeza.

Errar em qualquer das direções parte alguma coisa. Codifique um URL inteiro em âmbito componente e cada barra e ponto de interrogação passam a %2F e %3F, produzindo uma única cadeia inutilizável. Codifique um valor isolado em âmbito URL completo e um E comercial lá dentro sobrevive como delimitador: uma pesquisa por «gatos & cães» torna-se silenciosamente dois parâmetros e a segunda metade do seu valor desaparece.

// O valor contém um delimitador, por isso tem de ser escapado:
const q = 'cats & dogs'
`/search?q=${encodeURIComponent(q)}`  // /search?q=cats%20%26%20dogs
`/search?q=${encodeURI(q)}`           // /search?q=cats%20&%20dogs  ✗

// Melhor ainda: deixe a plataforma montá-lo
const url = new URL('https://example.com/search')
url.searchParams.set('q', 'cats & dogs')

Vale a pena adotar esta última abordagem como hábito. URL e URLSearchParams estão embutidos em todos os navegadores e no Node, e aplicam a codificação certa a cada parte por si — o que elimina a decisão em vez de o obrigar a acertar à mão de cada vez.

Porque é que um espaço é às vezes + e às vezes %20

Estão em ação duas especificações diferentes, e discordam em exatamente um carácter. O RFC 3986, que rege os URL em geral, codifica um espaço como %20. O formato mais antigo application/x-www-form-urlencoded — o que os formulários HTML submetem e, portanto, aquilo com que a maioria das cadeias de consulta se parece — codifica-o como +.

A armadilha é que o decodeURIComponent implementa apenas a primeira regra. Dê-lhe hello+world e recebe hello+world de volta, mais e tudo — sem erro, sem aviso, apenas um valor subtilmente errado. É por isso que esta ferramenta oferece a opção «tratar + como espaço» e a assinala quando a sua entrada contém um mais e a opção está desligada.

Note que o URLSearchParams, que alimenta a tabela de desdobramento sob a ferramenta, segue as regras dos formulários e converte + em espaço. Assim, a mesma cadeia de consulta pode descodificar-se de forma diferente consoante a API que usar — deliberadamente, e corretamente, em ambos os casos.

Uma consequência a lembrar: se um mais faz mesmo parte dos seus dados — um número de telefone, uma expressão de filtro — tem de ser codificado como %2B. Um + literal numa cadeia de consulta é ambíguo na melhor das hipóteses e será lido como espaço pela maioria dos analisadores.

Ler um URL

Cole um URL absoluto e a ferramenta divide-o nas suas partes. Vale a pena saber como se chama cada uma, porque as mensagens de erro e a documentação pressupõem o vocabulário:

  • Esquema — https, mailto, ftp. Tudo o que vem antes dos dois pontos, e o que decide como se interpreta o resto.
  • Info de utilizador — um user:password opcional antes do anfitrião. Continua legal, e continua a ser má ideia: viaja em cada pedido e acaba em registos, no histórico do navegador e em cabeçalhos referrer.
  • Anfitrião — o nome de domínio ou o endereço IP. Tudo o que vem a seguir é tratado por esse servidor, não pela rede.
  • Porta — normalmente ausente, porque 443 para https e 80 para http estão implícitas.
  • Origem — o esquema, o anfitrião e a porta em conjunto. É a unidade sobre a qual assenta a segurança do navegador: a política de mesma origem, o CORS e o âmbito dos cookies comparam origens, não caminhos.
  • Caminho — a parte depois do anfitrião e antes de qualquer ? ou #.
  • Consulta — os pares chave/valor depois do ?, separados por &.
  • Fragmento — tudo o que vem depois do #. Caso único, isto nunca é enviado ao servidor; é tratado inteiramente pelo navegador.

Este pormenor do fragmento importa mais do que parece. Como nunca sai do navegador, tudo o que puser depois de um # é invisível para os registos do servidor — razão pela qual algumas aplicações de página única o usaram historicamente para encaminhamento, e razão pela qual não é ali que se procura quando se depura um pedido que nunca chegou.

Um último cuidado sobre o que a codificação não faz. A codificação percentual torna o texto seguro para transportar dentro de um URL; não é saneamento nem um controlo de segurança. Codificar um valor não o torna seguro para interpolar em HTML, SQL ou num comando de shell, e descodificar entrada não fidedigna pode revelar caracteres — separadores de caminho, bytes nulos — que a forma codificada escondia. Valide o que um valor é, separadamente de codificar como ele viaja.

O endereço que escreve nem sempre é o que segue

Antes de um URL ir a qualquer lado é normalizado, e a reescrita é silenciosa. Esta ferramenta mostra o resultado sempre que difere da entrada, porque é essa cadeia — e não a que escreveu — que chega ao servidor e que aparece num registo:

HTTPS://Example.COM:443\a\b     escrito
https://example.com/a/b         enviado

Ali dispararam quatro regras distintas. O esquema e o anfitrião passam a minúsculas, já que nenhum distingue maiúsculas. A porta desaparece porque 443 é a predefinida do https. As barras invertidas tornam-se barras normais, uma regra de compatibilidade que surpreende quem escreve caminhos ao estilo Windows. E um caminho vazio teria passado a uma única barra. Nada disto é um erro, mas se comparar dois URL, ou confrontar um com uma lista de permitidos, tem de comparar as formas normalizadas ou obterá a resposta errada.

Um nome de anfitrião com caracteres não ASCII também é reescrito, para uma forma ASCII que começa por xn--, chamada punycode. A ferramenta mostra ambos os sentidos: o nome legível e o que viaja de facto. Vale a pena olhar em vez de saltar, porque dois nomes Unicode diferentes podem parecer idênticos no ecrã — um «a» latino e um «а» cirílico são caracteres distintos — e produzir um punycode completamente diferente. Comparar as formas ASCII é a única maneira fiável de distinguir um par assim.

Uma coisa nunca é normalizada: um parâmetro de consulta repetido. Escrever ?tag=a&tag=b é perfeitamente legal, e a norma não diz o que significa, por isso cada plataforma escolheu a sua resposta. O PHP fica com o último valor, o Express junta-os num array, e muitas frameworks e o URLSearchParams.get ficam com o primeiro. A ferramenta assinala as chaves repetidas em vez de as listar duas vezes sem comentário, porque o erro daí resultante — um valor que funciona num serviço e desaparece noutro — é genuinamente difícil de detetar a ler.

Perguntas frequentes

Qual é a diferença entre âmbito componente e URL completo?
O âmbito componente escapa também os delimitadores / ? : @ & = +, o que é correto para um valor isolado colocado dentro de um URL. O âmbito URL completo deixa-os intactos porque aí separam as partes do endereço. Usar o âmbito componente num URL inteiro transforma cada barra em %2F e produz uma cadeia inutilizável.
Porque é que o meu texto descodificado ainda tem um +?
Porque o decodeURIComponent segue o RFC 3986, onde + é apenas um mais. As submissões de formulário e a maioria das cadeias de consulta usam codificação de formulário, onde + significa espaço. Ative «tratar + como espaço» quando o texto vier de qualquer um deles.
Como codifico um mais que é mesmo um mais?
Escreva-o como %2B. Um + literal numa cadeia de consulta será lido como espaço pela maioria dos analisadores, por isso qualquer mais que faça mesmo parte dos seus dados — num número de telefone, por exemplo — tem de ser escapado.
Devo codificar o URL inteiro ou apenas as partes?
Apenas as partes, e de preferência não à mão: construa o endereço com URL e URLSearchParams, que aplicam a codificação correta a cada componente. Codificar um URL já montado é de onde vêm a maioria dos erros de dupla codificação.
Porque é que a decomposição mostra um URL diferente do que colei?
Porque é esse que segue. Um URL é normalizado antes de ser usado: o esquema e o anfitrião passam a minúsculas, uma porta predefinida é removida, as barras invertidas tornam-se barras, um caminho vazio torna-se uma barra, e um anfitrião não ASCII torna-se punycode. Se comparar URL ou os confrontar com uma lista de permitidos, compare estas formas normalizadas e não o texto em bruto.
Porque é que não aparece decomposição para example.com/path?
Porque não é um URL absoluto — não tem esquema, logo não há anfitrião a identificar. A ferramenta não adivinha um por si: example.com:8080 já é um URL absoluto válido cujo esquema é example.com e cujo caminho é 8080, pelo que acrescentar https:// em silêncio pode produzir uma decomposição que parece razoável e está errada. Acrescente o esquema você mesmo e as partes aparecerão.
O que é dupla codificação?
Codificar um valor que já estava codificado, de modo que um %20 passa a %2520 — o próprio sinal de percentagem é escapado. Costuma aparecer como sequências %20 literais visíveis numa página. Descodifique uma vez e veja se ainda aparecem escapes; se sim, foi codificado duas vezes.
Codificar um valor torna-o seguro?
Não. A codificação percentual trata do transporte, não da segurança. Um valor codificado continua a ser o que era, e precisa da mesma validação e do mesmo escape adequado ao contexto antes de chegar a HTML, SQL ou a uma shell.
Porque é que o fragmento não é enviado ao servidor?
Por desenho: tudo o que vem depois do # é tratado apenas pelo navegador e nunca aparece no pedido. É por isso que não se vê nos registos do servidor, e por isso foi historicamente usado para encaminhamento do lado do cliente.
O que eu colo é enviado para algum lado?
Não. A codificação, a descodificação e o desdobramento do URL usam as funções embutidas do próprio navegador e correm inteiramente no seu dispositivo. Nada do que colar sai dele.