O módulo base64 no Python converte bytes binários em caracteres ASCII e faz a operação inversa. Isso permite transportar imagens, chaves, identificadores e pequenos blobs em formatos que aceitam apenas texto, como JSON, cabeçalhos, arquivos de configuração e algumas URLs.
Base64 é codificação, não criptografia. O conteúdo pode ser recuperado por qualquer pessoa que tenha acesso à string. Ele também não autentica nem detecta alterações de forma confiável. Para confidencialidade use criptografia; para integridade e autenticidade use hashes autenticados ou assinaturas.
Codificação básica
import base64
dados = b"mensagem binaria\x00\xff"
codificado = base64.b64encode(dados)
restaurado = base64.b64decode(codificado)
assert restaurado == dados
print(codificado)As funções de codificação recebem objetos bytes-like e devolvem bytes ASCII. Para armazenar em JSON, converta para texto ASCII explicitamente:
texto = base64.b64encode(dados).decode("ascii")
bytes_originais = base64.b64decode(texto)Base64 aumenta o tamanho
O formato representa grupos de três bytes com quatro caracteres, criando overhead próximo de 33%, além de padding e delimitadores externos. Não use Base64 para economizar espaço. Se o tamanho importar, comprima os bytes antes com um algoritmo adequado, como zlib no Python, e só então codifique se o canal exigir texto.
Decodificação estrita com validate
Por padrão, b64decode() descarta caracteres fora do alfabeto antes de verificar o padding. Isso é conveniente para formatos com quebras de linha, mas pode aceitar lixo inesperado. Em APIs e tokens, use validate=True:
import base64
import binascii
try:
dados = base64.b64decode(valor, validate=True)
except (binascii.Error, ValueError) as erro:
raise ValueError("Base64 inválido") from erroValide também o tamanho da entrada e da saída. Uma string Base64 longa pode consumir memória mesmo antes de ser convertida.
Padding com sinal de igual
O caractere = completa o último grupo. Remover padding é comum em identificadores URL-safe, mas a API de decodificação normalmente espera comprimento válido. Restaure apenas o padding necessário:
import base64
def decodificar_sem_padding(texto: str) -> bytes:
if len(texto) > 10_000:
raise ValueError("entrada muito longa")
padding = "=" * (-len(texto) % 4)
return base64.urlsafe_b64decode(texto + padding)Não acrescente uma quantidade arbitrária sem validar caracteres e comprimento. Um protocolo deve documentar se padding é obrigatório, opcional ou proibido.
Base64 URL-safe
urlsafe_b64encode() substitui + por - e / por _:
import base64
identificador = base64.urlsafe_b64encode(b"arquivo/2026+versao")
print(identificador)
print(base64.urlsafe_b64decode(identificador))A saída ainda pode conter =. “URL-safe” significa que o alfabeto evita alguns caracteres problemáticos, não que a string completa possa ser inserida em qualquer componente sem considerar encoding e contexto. Para construir uma query corretamente, use urllib.parse no Python.
Alfabeto alternativo
b64encode() aceita altchars de exatamente dois bytes para substituir + e /:
import base64
customizado = base64.b64encode(b"dados", altchars=b"-_")
original = base64.b64decode(customizado, altchars=b"-_", validate=True)Prefira as funções URL-safe quando esse for o padrão desejado. Alfabetos personalizados prejudicam interoperabilidade e precisam ser documentados.
Arquivos e imagens em JSON
import base64
import json
from pathlib import Path
caminho = Path("icone.png")
conteudo = caminho.read_bytes()
if len(conteudo) > 2 * 1024 * 1024:
raise ValueError("arquivo excede o limite")
payload = json.dumps({
"nome": caminho.name,
"conteudo_base64": base64.b64encode(conteudo).decode("ascii"),
})Para arquivos grandes, prefira upload binário, multipart ou armazenamento de objetos. Base64 aumenta tráfego, uso de memória e custo de parsing, pois normalmente coexistem bytes originais, texto e bytes decodificados.
Data URLs
Uma Data URL combina tipo MIME e Base64:
import base64
dados = b"..."
tipo = "image/png"
data_url = f"data:{tipo};base64,{base64.b64encode(dados).decode('ascii')}"Não confie no tipo declarado. Detecte ou valide o formato real e aplique uma allowlist. Data URLs podem transportar HTML, SVG ou scripts e criar riscos de XSS quando inseridas em páginas sem política adequada.
Base32
Base32 usa um alfabeto menor, geralmente mais fácil de ler e digitar:
import base64
codigo = base64.b32encode(b"segredo temporario")
print(codigo)
print(base64.b32decode(codigo))b32decode() rejeita letras minúsculas por padrão. casefold=True aceita minúsculas. O parâmetro map01 pode mapear os dígitos 0 e 1 para letras parecidas, mas o padrão seguro é não aceitar essas substituições, evitando ambiguidades.
Base32 Hex
b32hexencode() e b32hexdecode() usam o alfabeto hexadecimal estendido da RFC 4648. Como os dígitos 0 e 1 fazem parte do alfabeto, não existe o mapeamento ambíguo para O, I ou L.
Base16
Base16 é representação hexadecimal:
import base64
hexadecimal = base64.b16encode(b"ABC")
print(hexadecimal) # b'414243'
print(base64.b16decode(hexadecimal))A decodificação aceita apenas maiúsculas por padrão. Use casefold=True somente quando o protocolo permitir. Para hashes e IDs, bytes.hex() e bytes.fromhex() podem ser mais diretos.
Ascii85 e Base85
Base85 representa quatro bytes em cinco caracteres, reduzindo overhead em comparação ao Base64. O módulo oferece variantes distintas:
a85encode(): Ascii85 usado em PostScript e PDF.b85encode(): variante usada por ferramentas como Git.z85encode(): alfabeto Z85 do ZeroMQ, disponível desde Python 3.13.
import base64
dados = b"12345678"
print(base64.a85encode(dados))
print(base64.b85encode(dados))
print(base64.z85encode(dados))Essas variantes não são intercambiáveis. Escolha conforme a especificação externa e teste padding, marcadores e comprimento.
Comprimento no Z85
Z85 exige que a entrada tenha comprimento múltiplo de quatro e que o texto codificado tenha múltiplo de cinco. Se você adicionar padding manual, transporte também o comprimento original ou um protocolo que permita removê-lo com segurança.
Interface legada e MIME
encodebytes() insere quebras de linha a cada 76 caracteres, conforme MIME. Para mensagens de e-mail completas, use o pacote email, que gerencia cabeçalhos, transfer encoding e estrutura corretamente. A interface moderna é melhor para APIs e armazenamento.
Base64 em autenticação HTTP
HTTP Basic Authentication combina usuário e senha com Base64. Isso não protege as credenciais; a segurança depende de TLS:
import base64
credenciais = "usuario:senha".encode("utf-8")
header = "Basic " + base64.b64encode(credenciais).decode("ascii")Evite registrar o header e não reutilize credenciais. Prefira tokens de curta duração e mecanismos adequados quando disponíveis.
Não use Base64 para senhas
Codificar uma senha não a protege. Senhas devem ser armazenadas com algoritmos de hash específicos, salt e custo configurável. Chaves privadas e tokens devem ser criptografados ou mantidos em um gerenciador de segredos.
Tokens assinados
Formatos como JWT usam Base64URL para representar partes, mas a segurança vem da assinatura ou do MAC. Decodificar um JWT não verifica sua autenticidade. Verifique algoritmo, assinatura, emissor, audiência, expiração e demais claims com uma biblioteca apropriada.
Limites e processamento
import base64
import binascii
MAX_TEXTO = 4 * 1024 * 1024
MAX_SAIDA = 3 * 1024 * 1024
def decodificar_limitado(texto: str) -> bytes:
if len(texto) > MAX_TEXTO:
raise ValueError("Base64 excede o limite")
try:
dados = base64.b64decode(texto, validate=True)
except binascii.Error as erro:
raise ValueError("Base64 inválido") from erro
if len(dados) > MAX_SAIDA:
raise ValueError("resultado excede o limite")
return dadosO limite do texto deve considerar que a saída é aproximadamente três quartos do tamanho codificado. Verifique ainda o tipo e a estrutura dos bytes resultantes.
Compare com segurança
Se os bytes decodificados forem uma assinatura ou MAC esperado, compare com hmac.compare_digest() para reduzir vazamento de timing. Primeiro valide tamanho e formato.
Dados binários estruturados
Base64 apenas transporta bytes. Para criar um layout binário versionado antes da codificação, use struct no Python. Inclua magic, versão, comprimentos e limites. Para processar lotes concorrentes, queue no Python oferece backpressure.
Testes recomendados
Teste entrada vazia, todos os comprimentos módulo quatro, padding ausente ou excessivo, caracteres inválidos, Unicode não ASCII, Base64 padrão e URL-safe, limites, Base32 ambíguo, Base85 com padding e round trips de dados aleatórios. Inclua casos conhecidos da RFC 4648.
Boas práticas
- Trabalhe com bytes internamente.
- Converta para ASCII apenas na borda.
- Use
validate=Trueem entradas externas. - Defina limites antes e depois da decodificação.
- Escolha o alfabeto conforme a especificação.
- Não confunda codificação com segurança.
- Não registre tokens ou credenciais.
- Valide o conteúdo binário depois de decodificar.
Conclusão
O base64 no Python oferece Base16, Base32, Base64, Ascii85, Base85 e Z85 para transportar bytes em canais textuais. A API é simples, mas o uso robusto exige validação estrita, limites e entendimento do formato esperado.
Consulte a documentação oficial do base64 e a RFC 4648. Codificação resolve transporte; confidencialidade e autenticidade exigem ferramentas específicas.







