O que o Base64 realmente é
Base64 é uma forma de escrever bytes quaisquer usando apenas 64 caracteres seguros. A ideia é toda essa. Não é criptografia, nem compressão, nem checksum. Resolve um problema bem estreito: você tem dados binários e o canal pelo qual precisa passá-los só aceita texto.
Esse canal pode ser o corpo de um e-mail, um campo JSON, uma URL, um cabeçalho HTTP, um arquivo
YAML ou um arquivo PEM. Envie bytes crus e algo no caminho vai estragá-los: um byte nulo corta uma
string, um 0x0D é reescrito por uma conversão de fim de linha, um byte alto é
reinterpretado em outro conjunto de caracteres. O Base64 contorna tudo isso usando apenas letras,
dígitos e dois sinais de pontuação, e todos eles sobrevivem a ser tratados como texto.
O custo é o tamanho: a saída fica cerca de um terço maior que a entrada. É a troca, e quase sempre vale a pena, porque a alternativa são dados que chegam corrompidos.
Como três bytes se tornam quatro caracteres
O Base64 trabalha em grupos de três bytes. Três bytes são 24 bits, e 24 se divide exatamente em quatro grupos de seis. Cada grupo de 6 bits indexa um alfabeto de 64 caracteres, então três bytes de entrada produzem quatro caracteres de saída.
Pegue os três bytes de Man:
M = 77 = 01001101, a = 97 = 01100001, n = 110 = 01101110
Junte os bits e divida de novo em grupos de seis:
010011 010110 000101 101110 → 19, 22, 5, 46 → T, W, F, u
Então Man codifica como TWFu. Quatro caracteres, sem preenchimento,
porque os três bytes dividiram exato. Esse “dividiram exato” é justamente o assunto da seção
seguinte.
Os 64 caracteres
Os índices 0–25 são A–Z, 26–51 são a–z,
52–61 são 0–9, e 62 e 63 são os dois que causam todo o problema. No
Base64 padrão são + e /.
O alfabeto, e por que existem dois
+ e / são perfeitamente aceitáveis no corpo de um e-mail e
francamente hostis numa URL. / é separador de caminho e + significa
espaço numa query string, então um valor Base64 colado numa URL pode voltar com os bytes
alterados e sem erro algum em lugar nenhum.
Daí o base64url, uma variante que mantém os primeiros 62 caracteres e troca os
dois últimos: - por + e _ por /. É a
codificação usada pelos JSON Web Tokens — se você já leu um JWT à mão, leu base64url — e por tudo
mais que viaja numa URL ou num nome de arquivo.
No resto as duas variantes são idênticas, e é exatamente isso que torna perigoso misturá-las.
Uma string que não contenha nenhum +, /, - ou
_ é válida nas duas e decodifica igual. Uma que contenha decodifica para
bytes diferentes conforme a variante que o decodificador assumir, normalmente sem levantar
erro nenhum. O nosso codificador e
decodificador Base64 informa qual alfabeto detectou exatamente por isso.
O preenchimento, e por que os decodificadores discordam
A entrada raramente é múltiplo de três bytes. Um byte sobrando dá dois caracteres, dois bytes
sobrando dão três, e o Base64 padrão completa o grupo até quatro com sinais =:
- 3 bytes → 4 caracteres, sem preenchimento
- 2 bytes → 3 caracteres +
= - 1 byte → 2 caracteres +
==
O preenchimento não carrega dados. Existe para que um decodificador lendo um fluxo concatenado
saiba onde termina um valor codificado. Se você decodifica uma única string isolada, não precisa
dele — por isso o base64url normalmente o descarta, e por isso = é inconveniente numa
URL de todo modo.
O problema prático
Alguns decodificadores exigem o preenchimento e rejeitam de saída uma string sem ele. Outros
aceitam as duas formas. Esse é o motivo mais comum de um token funcionar numa linguagem e falhar
em outra com um seco “base64 inválido”. A correção quase sempre é devolver o preenchimento:
acrescente = até o comprimento ser múltiplo de quatro. Um decodificador rigoroso com
preenchimento não está quebrado, e o codificador que o omitiu também não — cada um segue uma
metade diferente da mesma especificação.
Base64 não é criptografia
Isto merece seção própria porque o erro é comum e caro. O Base64 não tem chave. Não esconde nada. Revertê-lo é uma única chamada de função, disponível em toda linguagem e em qualquer página como esta.
O exemplo canônico é a autenticação HTTP Basic. Um cabeçalho
Authorization: Basic não é nada além de usuário:senha em Base64. Parece
opaco, e é exatamente aí o perigo: soa como “criptografado” para quem nunca decodificou um,
quando na verdade qualquer um que veja a requisição consegue ler as credenciais. É por isso que o
Basic só é aceitável sobre HTTPS — o sigilo vem do transporte, a codificação não fornece
nenhum.
O mesmo vale para o payload de um JWT, para um bloco Base64 num arquivo de configuração e para uma chave de API que alguém “ofuscou” antes de commitar. Se a única coisa entre um atacante e o seu segredo é Base64, não há nada entre um atacante e o seu segredo. Nosso guia para decodificar e depurar JSON Web Tokens aprofunda o que isso significa para tokens em particular.
Onde você encontra Base64 de verdade
Depois que você reconhece o formato, vê em todo lugar:
- Anexos de e-mail. O MIME carrega binário assim desde o começo dos anos noventa, quebrado em 76 caracteres por linha.
- data: URIs. Uma imagem pequena embutida em CSS ou HTML como
data:image/png;base64,…, trocando uma requisição HTTP por um terço mais de bytes. - Arquivos PEM. Certificados e chaves entre marcadores
-----BEGIN…são Base64 do DER subjacente, quebrado em 64 caracteres. - JWTs. Cabeçalho e payload são JSON em base64url; a assinatura é base64url de bytes crus.
- Basic auth e algumas credenciais de API. Como acima, com a mesma ressalva.
- Binário dentro de JSON. JSON não tem tipo byte, então bytes viajam como uma string Base64.
Por que alguns Base64 têm quebras de linha
MIME quebra em 76 caracteres e PEM em 64, porque os formatos onde vivem são anteriores a linhas longas. Essas quebras não fazem parte dos dados e um decodificador deve ignorá-las. A maioria ignora; alguns não, e é por isso que colar um corpo PEM quebrado num decodificador rigoroso às vezes falha até você remover as quebras.
O custo em tamanho, e quando ele importa
Quatro caracteres por três bytes é uma expansão de 4/3 — cerca de 33 % — antes do preenchimento e das quebras de linha. Para um valor de configuração pontual isso é irrelevante. Para qualquer coisa num caminho crítico, não é.
Uma imagem de 10 KB embutida como data: URI custa cerca de 13,3 KB de HTML e, ao contrário de uma imagem real, não pode ser cacheada separadamente nem carregada sob demanda. Um token enviado em cada chamada de API carrega seu custo em cada requisição. E a compressão não te salva: a saída Base64 comprime muito pior que os bytes originais, porque a codificação destrói os padrões em nível de byte que um compressor procura. Comprima primeiro, codifique depois — nunca o contrário.
Codificar texto significa codificar bytes
O Base64 codifica bytes. Ele não tem noção de caracteres, então “codifique esta string em Base64” é sempre um atalho para “transforme esta string em bytes e então codifique esses bytes”. O passo do meio é onde as coisas dão errado, porque ele precisa de uma codificação de caracteres e a especificação não escolhe uma para você.
Na prática a resposta é UTF-8, e APIs modernas usam isso por padrão. Mas se um lado codifica o texto como UTF-16 ou Latin-1 e o outro decodifica como UTF-8, o Base64 é perfeitamente válido e o texto que sai é ilegível. O sinal é que caracteres não ASCII sobrevivem mal enquanto ASCII puro sobrevive bem, já que ASCII é um subconjunto de UTF-8.
O teste de ida e volta
Se você não tem certeza se um pipeline trata texto corretamente, codifique uma string com um
acento e um caractere não latino, decodifique de novo e compare. Qualquer coisa que estrague
José ou um emoji está perdendo informação em algum ponto da conversão para bytes, não
no Base64 em si.
Quando a decodificação dá errado
Quatro diagnósticos cobrem quase todos os casos:
- “Caractere inválido”. Entrou algo que não está no alfabeto — na maioria das
vezes um espaço perdido, uma aspa copiada junto com a string, ou um prefixo
data:image/png;base64,que ficou na frente. - “Comprimento inválido”. Depois de remover os espaços, o comprimento módulo quatro é 1, o que nenhum Base64 válido pode produzir. Um caractere se perdeu no caminho.
- Decodifica, mas para lixo. Ou os alfabetos estão trocados (base64url decodificado como padrão, ou o contrário), ou a codificação de texto está trocada, como descrito acima.
- Decodifica para bytes que não são texto. Isso não é erro. Muito Base64 guarda uma imagem, uma chave ou uma estrutura serializada; um bom decodificador mostra uma visão hexadecimal em vez de fingir que o resultado é uma string.
Percorrer esses pontos em ordem — caracteres, comprimento, alfabeto, codificação — resolve quase tudo. E quando um valor simplesmente não decodifica em lugar nenhum, a explicação mais provável é a mais sem graça: ele estava truncado. O Base64 não tem verificação de integridade, então uma string que perdeu o final parece exatamente igual a uma que nunca teve.
Ferramentas e guias relacionados:
- Codificador e decodificador Base64 — Codifique texto para Base64 ou de volta, com saída URL-safe e UTF-8 tratado.
- Decodificador JWT — Decodifique um JSON Web Token e leia o cabeçalho, o payload, as claims e a expiração.
- JWT explicado: como decodificar e depurar JSON Web Tokens — O que um JSON Web Token contém
Perguntas frequentes
Para que serve o Base64?⌄
O Base64 carrega dados binários por canais que só aceitam texto: anexos de e-mail, data: URIs em CSS e HTML, certificados e chaves em arquivos PEM, campos binários dentro de JSON e cabeçalhos HTTP como Authorization: Basic. Onde bytes crus seriam corrompidos ou rejeitados, o Base64 os leva intactos.
Base64 é criptografia ou codificação?⌄
Codificação. Não há chave nem sigilo — decodificar é uma única chamada de função que qualquer navegador faz. O Base64 torna bytes transportáveis, não protegidos de leitura. Nunca o use para proteger uma senha, um token ou uma chave de API.
Por que minha string Base64 termina em = ou ==?⌄
Isso é preenchimento. O Base64 trabalha em grupos de três bytes, e quando a entrada não divide exato o último grupo é completado até quatro caracteres com um ou dois sinais =. O preenchimento não carrega dados; o base64url normalmente o omite e alguns decodificadores rigorosos o exigem, o que costuma explicar uma string que decodifica numa linguagem mas não em outra.
Qual a diferença entre Base64 e base64url?⌄
Dois caracteres e o preenchimento. O Base64 padrão usa + e / nas duas últimas posições do alfabeto; o base64url usa - e _ no lugar, porque + e / têm significados especiais numa URL, e normalmente descarta o preenchimento =. JWTs usam base64url. Decodificar um como o outro produz bytes diferentes silenciosamente.
Quanto o Base64 aumenta meus dados?⌄
Cerca de 33 %: cada três bytes viram quatro caracteres, mais preenchimento e quebras de linha. Se o tamanho importa, comprima antes de codificar e não depois — a saída Base64 comprime mal porque a codificação destrói os padrões de bytes de que um compressor depende.
Mais de 15 anos de experiência prática em desenvolvimento web e segurança. Foco em segurança web prática: manter sites seguros, confiáveis e fáceis de diagnosticar. O BuildToolForge existe para tornar essas verificações gratuitas, privadas e compreensíveis. As ferramentas rodam no seu navegador sempre que possível, e nada do que você digita em uma ferramenta é armazenado.
Como escrevemos nossos guias: Cada guia nasce da experiência prática, é conferido com os padrões oficiais e testado com nossas próprias ferramentas em domínios reais. Atualizamos os guias quando padrões ou ferramentas mudam. Encontrou um erro? Escreva para contact@buildtoolforge.com.