Skip to content

Comparison

Base64 vs base64url: dois caracteres que fazem diferença

Mesmo alfabeto, dois últimos caracteres diferentes, padding diferente. Uma linha de diferença, casos de uso totalmente distintos.

By Published

Resumo. Base64 e base64url são a mesma codificação, exceto por três detalhes definidos no RFC 4648: + vira -, / vira _, e o padding = é removido. Use base64url sempre que o valor codificado viajar em uma URL, JWT ou cookie assinado; use Base64 padrão para anexos de e-mail, HTTP Basic Auth e URIs de dados.

Ambos são definidos no RFC 4648. O Base64 padrão (§4) e o base64url (§5) diferem em exatamente três detalhes: duas substituições de alfabeto e o tratamento do padding. Só isso. Mas misturá-los quebra JWTs, cookies assinados e tudo que viaja em uma URL.

A diferença

PropriedadeBase64 padrãoBase64url
62º caractere+-
63º caractere/_
Padding= para múltiplo de 4Normalmente omitido
Seguro para URL?Não (+, /, = precisam de codificação percentual)Sim
Definido emRFC 4648 §4RFC 4648 §5

A mesma entrada, ambas as codificações

Codificando https://example.com/?q=hello world:

  • Padrão: aHR0cHM6Ly9leGFtcGxlLmNvbS8/cT1oZWxsbyB3b3JsZA==
  • Base64url: aHR0cHM6Ly9leGFtcGxlLmNvbS8_cT1oZWxsbyB3b3JsZA

Note que o / na forma padrão vira_ em base64url, e o == final é removido.

Por que URLs precisam de sua própria variante

O alfabeto Base64 padrão inclui + e/. Ambos são reservados na sintaxe de URL:

  • / é o separador de caminho.
  • + é, por convenção em query strings codificadas por formulário, interpretado como espaço.
  • = é o delimitador chave-valor em query strings.

Incorporar uma string Base64 padrão em uma URL requer codificação percentual dos três: + vira%2B, / vira %2F,= vira %3D. A string fica maior e mais difícil de ler. O base64url evita a codificação percentual escolhendo caracteres que já são seguros para URL.

Por que o padding é opcional no base64url

O Base64 padrão sempre completa a saída para um múltiplo de 4 caracteres usando =. Isso não é matematicamente necessário — o decodificador pode inferir o comprimento original a partir do comprimento da saída módulo 4. O padding existe para decodificadores de streaming que precisam saber o limite entre blocos concatenados.

O base64url omite o padding porque: (a) é redundante, (b) = precisa de codificação percentual em URLs, e (c) sinais de igual no final de URLs às vezes confundem analisadores de caminho, CDNs e chaves de cache.

Onde cada um é usado

Caso de usoVariante
Anexos de e-mail (MIME)Base64 padrão
HTTP Basic Auth (Authorization: Basic …)Base64 padrão
URIs de dados (data:image/png;base64,…)Base64 padrão
JWT (todos os três segmentos)Base64url, sem padding
OAuth 2.0 PKCE code verifier/challengeBase64url, sem padding
WebPush chaves de mensagem, JOSE/JWS/JWEBase64url, sem padding
Cookies assinados (Rails, Django, etc.)Base64url, sem padding

O problema na decodificação

O decodificador Base64 padrão de muitas bibliotecas falha com entradas base64url. O base64.b64decode do Python rejeita - e _; o Buffer.from(s, "base64") do Node.js é permissivo, mas o inverso (.toString("base64")) produz Base64 padrão.

Soluções entre linguagens: substitua antes de decodificar.

// base64url → Base64 padrão
const standard = base64url
  .replace(/-/g, "+")
  .replace(/_/g, "/")
  .padEnd(Math.ceil(base64url.length / 4) * 4, "=");

Melhor: use uma biblioteca que suporte explicitamente base64url (Node 16+ tem Buffer.from(s, "base64url"); Python tem base64.urlsafe_b64decode).

A regra prática

Se o valor codificado aparecer em uma URL, em um JWT, em um cookie assinado ou como segmento de caminho — use base64url. Se for para um anexo de e-mail, cabeçalho HTTP (exceto cookies) ou URI de dados JSON — use Base64 padrão.

Nosso codificador Base64 suporta ambas as variantes, com alternância de alfabeto. O decodificador JWT assume base64url porque o padrão exige isso.

Fatos numéricos

  • Comprimento codificado: ambas as variantes expandem binário exatamente 4/3 (ceil(n/3)*4). 100 bytes de entrada → 136 chars de saída em Base64 padrão, ou 134 chars sem padding em base64url.
  • Overhead de padding: o Base64 padrão adiciona 0, 1 ou 2 chars = por string codificada — no máximo 1,5% de penalidade de tamanho para payloads curtos, negligível para longos.
  • Custo de codificação percentual em URLs: cada + / = no Base64 padrão se expande para 3 bytes (%2B %2F %3D) quando codificado em URL. Para um JWT de 512 chars, isso são tipicamente 30 a 60 bytes desperdiçados — o base64url evita completamente.
  • Tamanho do alfabeto: 64 caracteres em ambos, então cada caractere de saída carrega exatamente 6 bits de entrada.
  • Tamanhos dos segmentos JWT (RFC 7519): cabeçalho típico 40-50 chars, payload 100-400 chars, assinatura HS256 43 chars (exatamente 32 bytes / 6 = 43 chars base64url, sem padding).
  • Throughput: o Buffer.from(s, "base64") do Node 20 decodifica a ~2 GB/s; o base64.b64decode do Python a ~600 MB/s em laptop de 2024.

Matriz de decisão

Onde o valor viveEscolha
Caminho ou query string de URLbase64url, sem padding
JWT (cabeçalho / payload / assinatura)base64url, sem padding (RFC 7519)
OAuth 2.0 PKCE verifierbase64url, sem padding (RFC 7636 §4.1)
Cookie assinado (Rails / Django / Express)base64url, sem padding
URI data: em HTML/CSSBase64 padrão com padding
Anexo de e-mail MIMEBase64 padrão com padding, quebra de linha 76 chars (RFC 2045)
Cabeçalho HTTP Basic AuthBase64 padrão (RFC 7617)
Chaves de assinatura WebPushbase64url, sem padding (RFC 8291)

Fontes

Frequently asked questions

Posso decodificar base64url com um decodificador Base64 padrão?
Às vezes — o Buffer.from do Node é permissivo, o b64decode do Python não é. A abordagem segura entre linguagens: substitua '-' por '+', '_' por '/', e adicione padding até um múltiplo de 4 com '=' antes de decodificar. Runtimes modernos fornecem decodificadores base64url explícitos (Node 16+, urlsafe_b64decode do Python) que tratam isso diretamente.
Por que o base64url remove o padding?
Três razões: é matematicamente redundante (os decodificadores podem inferir o comprimento original a partir do comprimento da saída mod 4), o caractere '=' precisa de codificação percentual em URLs, e '=' no final confunde alguns analisadores de caminho, CDNs e chaves de cache.
Os segmentos JWT são sempre base64url?
Sim. O RFC 7519 exige base64url sem padding para todos os três segmentos JWT (cabeçalho, payload, assinatura). Codificar um JWT com Base64 padrão produz um token que não será verificado em nenhuma biblioteca compatível.
O base64url economiza bytes em comparação com o Base64 padrão?
Marginalmente — o mesmo tamanho de alfabeto significa o mesmo comprimento codificado antes do padding. Remover o padding economiza 0 a 2 bytes por codificação. A economia real é evitar a codificação percentual (cada %XX são 3 bytes para 1), o que pode economizar 6 a 9 bytes por string Base64 em uma URL.

Related

Published May 16, 2026