URL encode: como codificar parâmetros de URL sem quebrar nada

Codificar uma URL é trocar os caracteres que têm significado especial (como &, =, ? e espaço) por sequências %XX, para que um valor não seja confundido com a estrutura do endereço. Este guia explica a diferença entre encodeURIComponent e encodeURI, por que o espaço às vezes vira + e às vezes %20, e mostra o jeito certo em JavaScript, Python e PHP.

Por Leonardo Gaertner · Publicado em

Por que codificar

Na URL /buscar?q=pão & café, o & separa parâmetros, então o servidor recebe q=pão e um parâmetro estranho chamado café. Codificado, o valor vira p%C3%A3o%20%26%20caf%C3%A9 e chega inteiro. Os acentos viram os bytes do UTF-8, cada um como %XX.

Para codificar ou decodificar um valor na hora, use o codificador de URL.

encodeURIComponent ou encodeURI?

  • encodeURIComponent codifica tudo que tem significado na URL, inclusive /, ?, & e =. Use para um valor: um parâmetro, um trecho do caminho.
  • encodeURI mantém esses caracteres, porque espera uma URL inteira. Use só para corrigir espaços e acentos de um endereço já montado.
  • O erro mais comum é usar encodeURI em um valor: um & dentro dele passa sem codificar e quebra a query string.

Espaço: %20 ou +?

Os dois existem. Na URL em geral, o espaço é %20. No formato de formulário (application/x-www-form-urlencoded), usado na query string por URLSearchParams, urlencode do Python e http_build_query do PHP, ele vira +.

O problema aparece na leitura: decodeURIComponent("a+b") devolve a+b, com o sinal de mais. Para ler uma query string, use o leitor da própria linguagem, que entende os dois formatos.

Em JavaScript

Para montar uma query com vários parâmetros, URLSearchParams codifica cada valor e cuida dos separadores:

JavaScript
// Um valor dentro da URL (parâmetro, trecho do caminho): espaço vira %20
function codificarParametro(valor) {
  return encodeURIComponent(valor);
}

// A query string inteira, no formato de formulário: espaço vira +
function montarQuery(params) {
  return new URLSearchParams(params).toString();
}

// Ler a query string: o URLSearchParams entende tanto + quanto %20
function lerQuery(query) {
  return Object.fromEntries(new URLSearchParams(query));
}

Funciona no navegador e no Node.js.

Em Python e PHP

No Python, quote deixa a barra sem codificar, a não ser que você passe safe="". No PHP, prefira rawurlencode, que usa %20, a urlencode, que usa +.

Python
from urllib.parse import parse_qsl, quote, urlencode


def codificar_parametro(valor: str) -> str:
    return quote(valor, safe="")  # espaço vira %20; sem safe="", a barra passaria


def montar_query(params: dict) -> str:
    return urlencode(params)  # espaço vira +


def ler_query(query: str) -> dict:
    return dict(parse_qsl(query, keep_blank_values=True))
PHP
<?php
function codificarParametro(string $valor): string
{
    return rawurlencode($valor); // espaço vira %20
}

function montarQuery(array $params): string
{
    return http_build_query($params); // espaço vira +
}

function lerQuery(string $query): array
{
    parse_str($query, $params);
    return $params;
}

Cuidados

  • Codifique cada valor uma única vez. Codificar de novo transforma %20 em %2520, e o servidor recebe o texto errado.
  • Os caracteres ! ' ( ) * ficam sem codificar no encodeURIComponent, mas são codificados no Python e no PHP. Os dois resultados são válidos e decodificam igual.
  • Não codifique a URL inteira com encodeURIComponent: o https:// vira https%3A%2F%2F e deixa de ser um endereço.
  • Dados sensíveis, como senhas e tokens, não devem ir na URL, mesmo codificados: ela fica em históricos e registros de servidores.

Achou um erro neste guia? Avise por e-mail.

Perguntas frequentes

Qual a diferença entre encodeURI e encodeURIComponent?

O encodeURIComponent codifica também os caracteres que estruturam a URL, como barra, interrogação, e comercial e igual, e serve para valores. O encodeURI mantém esses caracteres e serve para uma URL inteira.

Por que o espaço aparece como + em algumas URLs?

É o formato de formulário, usado em query strings. Nele o espaço vira mais. No resto da URL, o espaço vira %20. Os leitores de query string das linguagens entendem as duas formas.

URL encode é o mesmo que Base64?

Não. O URL encode troca só os caracteres especiais por %XX e mantém o resto legível. O Base64 converte todos os bytes para outro alfabeto.

Como os acentos ficam na URL?

Cada letra acentuada vira os bytes do UTF-8 codificados. O ã, por exemplo, vira %C3%A3. Os navegadores costumam mostrar a letra na barra de endereço, mas enviam a forma codificada.