base64 no Python: codifique dados

Publicado em: 18/08/2026
Tempo de leitura: 6 minutos
A person reads 'Python for Unix and Linux System Administration' indoors.

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 erro

Valide 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 dados

O 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=True em 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.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Detailed shot of a Jungle Carpet Python (Morelia spilota cheynei) in its natural habitat.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    urllib.parse no Python: manipule URLs

    Aprenda urllib.parse no Python para decompor URLs, criar queries, codificar componentes e evitar riscos com urljoin, redirects e SSRF.

    Ler mais

    Tempo de leitura: 6 minutos
    18/08/2026
    A person typing on a laptop with a Python programming book visible, capturing technology and learning.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ipaddress no Python: redes IPv4 e IPv6

    Aprenda ipaddress no Python para validar IPv4 e IPv6, calcular redes CIDR, dividir sub-redes e criar políticas de acesso seguras.

    Ler mais

    Tempo de leitura: 6 minutos
    18/08/2026
    A vibrant collection of blue sewing threads arranged with hands on a white background.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    queue no Python: coordene threads

    Aprenda queue no Python para coordenar threads com FIFO, prioridade, backpressure, task_done, join, retries e shutdown seguro.

    Ler mais

    Tempo de leitura: 5 minutos
    17/08/2026
    A male software engineer working on code in a modern office setting.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    struct no Python: trabalhe com binário

    Aprenda struct no Python para empacotar dados binários, controlar endianness, usar buffers e validar protocolos e arquivos externos.

    Ler mais

    Tempo de leitura: 5 minutos
    17/08/2026
    Close-up of a laptop screen with code and a coffee mug, perfect for tech abstract themes.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tarfile no Python: crie TAR seguro

    Aprenda tarfile no Python para criar TAR comprimido, inspecionar membros e extrair com filtros, limites e proteção contra path traversal.

    Ler mais

    Tempo de leitura: 5 minutos
    17/08/2026
    Row of colorful office binders neatly arranged on a shelf, ideal for organization concepts.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    gzip no Python: comprima arquivos .gz

    Aprenda gzip no Python para ler e gravar .gz, criar saídas reproduzíveis, trabalhar com streams e limitar a expansão de

    Ler mais

    Tempo de leitura: 4 minutos
    17/08/2026