URL é exigente. Só fala ASCII, e mesmo dentro do ASCII reserva um punhado de caracteres com função estrutural — a barra entre segmentos do path, o ponto de interrogação antes da query, o e-comercial entre parâmetros. Qualquer outra coisa precisa virar percent encoding antes de viajar pela rede.
O que percent encoding é, na real
O percent encoding está definido na RFC 3986, o mesmo documento que define a sintaxe de URI. A regra é curta: para qualquer byte que você não consegue escrever direto na URI, escreva % seguido de dois dígitos hexadecimais. Espaço vira %20. Um e-comercial dentro de um valor de query vira %26 pra não ser confundido com separador de parâmetro. Um caractere UTF-8 multi-byte como ç vira dois pares percent — %C3%A7 — porque o UTF-8 escreve esse caractere em dois bytes.
A RFC 3986 §2.2 separa os caracteres especiais em dois grupos. gen-delims (: / ? # [ ] @) são os separadores estruturais principais. sub-delims (! $ & ' ( ) * + , ; =) carregam sentido em sub-componentes, principalmente em query strings. Quando o dado que você quer passar pela URI colide com algum desses como delimitador, você codifica.
Acentos PT em URL — o caso de uso brasileiro central
Aqui é onde quase todo dev BR encosta primeiro. Uma URL com São Paulo num valor de query precisa virar S%C3%A3o%20Paulo antes de ir. Não porque o servidor não entenda São Paulo — alguns entendem — mas porque o transporte pela RFC 3986 não define o que fazer com bytes fora do ASCII. O comportamento "às vezes funciona" é o pior dos mundos: dá certo no Chrome do dev e quebra no proxy corporativo do cliente.
A regra prática: todo valor de query com acento (ção, ãm, é, ú, ô, ç) ou cedilha passa por encodeURIComponent antes de virar URL. A função recebe a string, converte para UTF-8 internamente, e emite os percent triplets corretos. açúcar vira a%C3%A7%C3%BAcar; coração vira cora%C3%A7%C3%A3o. Round-trip via decodeURIComponent recupera o acento original — é por isso que decodificadores estritos sobre URLs codificadas parecem mágica até você lembrar que UTF-8 é o pivô invisível.
encodeURIComponent vs encodeURI — escolha a faca certa
As duas funções existem em todo browser e em todo runtime Node. Diferem em quanto do conjunto reservado tocam. encodeURIComponent é estrita: escapa tudo exceto letras, dígitos e os quatro caracteres unreserved - _ . ~ (mais os históricos ! * ' ( )). Use para valores de query, segmentos de path, fragments — qualquer lugar em que você está enfiando uma string num slot de URI que você já controla.
encodeURI é mais permissiva: preserva os caracteres estruturais da própria URI (/, ?, :, @, &, =, +, $, #, ,, ;) assumindo que você entregou uma URL inteira e só quer espaços e acentos normalizados. Se você usa encodeURI quando devia ter usado encodeURIComponent, um & dentro de valor silenciosamente vira separador de parâmetro. É bug difícil de pegar a olho e fácil de subir pra produção.
APIs BR fintechs e dados sensíveis em query
CPF em query parameter URL-encoded é cenário cotidiano em integrações com fintechs e PSPs brasileiros. O CPF em si é numérico (sem acento), então o encoding é trivial — mas o problema costuma estar nos campos vizinhos: nome com acento, endereço com cedilha, email com + de sub-endereço. Cada um desses precisa de tratamento próprio. Aqui o RFC 3986 e o encodeURIComponent dão a resposta mecânica; a parte humana é não passar PII por canal que log que não devia logar.
Esta ferramenta é 100% client-side justamente por isso. Em contextos de open banking BR, autenticação Pix, integração com SERPRO ou Receita, qualquer codificação que vaze pra servidor de terceiros é vetor desnecessário. Codifica no navegador, copia o resultado, cola no seu cliente HTTP. Zero rede.
Vale notar o detalhe operacional: o Bacen, em normativos de open banking, referencia padrões IETF (RFC 3986 entre eles) como base de URI signing pra request authentication. Quando a request inclui parâmetros derivados de input de usuário com acento, a assinatura precisa ser computada sobre a representação percent-encoded canônica — não sobre a versão "amigável" exibida na UI. Diferenças sutis no encoding aqui geram falhas de assinatura difíceis de debugar. A regra prática: padronize em encodeURIComponent e cheque round-trip antes de assinar.
O bicho-papão do + versus %20
Uma pergunta de percent encoding insiste em voltar: espaço deve ser %20 ou +? Os dois estão certos, em contextos diferentes.
%20 é a resposta RFC 3986. Vale em qualquer parte de uma URI — path, query, fragment. + é a resposta application/x-www-form-urlencoded. Esse formato foi padronizado na RFC 1866 como encoding padrão de formulário HTML, e a convenção de espaço virar + pegou. O WHATWG URL Living Standard mantém as duas regras lado a lado: o component percent-encode set emite %20; o application/x-www-form-urlencoded percent-encode set emite + e escapa o + literal da entrada.
Este gerador emite %20 nos dois variants, porque encodeURIComponent e encodeURI seguem RFC 3986. Se você precisa de form encoding, pós-processa a saída trocando %20 por + — mas só quando o consumidor espera form encoding. Misturar os dois no lado decoder é onde mora a maioria dos bugs "meu espaço virou mais".
Decodificar é a ponta tolerante do round trip
decodeURIComponent é superset. Aceita a saída de encodeURIComponent e de encodeURI e devolve a string original. Não precisa saber qual variante o encoder usou. É por isso que o modo Decode aqui não tem toggle de variante — um decoder cobre os dois.
A única coisa que quebra o decode é percent encoding malformado. Um % sozinho, uma sequência %G1, um %2 incompleto no fim — qualquer um deles dispara URIError no runtime. O widget captura e mostra uma mensagem amigável. A causa comum é input que veio de copy-paste por um canal que estragou o alfabeto — um chat client que comeu o segundo dígito hex, um campo de form que decodificou cedo demais. Quando o decoder rejeita uma entrada, revise a origem antes de assumir que o algoritmo quebrou.
O que percent encoding NÃO é
Não é criptografia. A saída é totalmente reversível por quem ler. Botar senha ou token de sessão em encodeURIComponent não esconde nada — proxies intermediários e access logs veem o valor decodificado no momento em que o receptor decodifica. Para confidencialidade real, TLS pro transporte e cifra de verdade pra storage.
Também não é Base64. Base64 empacota binário arbitrário em um alfabeto ASCII de 64 caracteres; URL encoding escapa caracteres reservados individuais de qualquer string. Se você quer botar binário em URL com segurança, a combinação certa é Base64URL (RFC 4648 §5) seguido de URL encoding apenas se necessário — Base64URL foi desenhado pra encaixar em URL sem escapar mais nada.
Privacidade e codificação client-side
Toda etapa de percent encoding nesta ferramenta roda no seu navegador. Nada sai da página. Isso importa mais do que parece pra dados de query — no momento em que você cola uma URL num codificador server-side, o servidor já viu seus tokens, seu CPF, seus valores privados de parâmetro. Uma ferramenta 100% client-side remove essa superfície inteira. O painel de entradas recentes guarda só seus inputs (modo + variante + timestamp), nunca a saída codificada, no localStorage do seu navegador. Limpar o painel é um clique.

