Como Decodificar Base64 em JavaScript
Decodifique Base64 em JavaScript da forma certa: atob no navegador, Buffer no Node.js, TextDecoder seguro para Unicode, variantes URL-safe e tratamento de erros.
Decodificar Base64 em JavaScript parece coisa de uma única linha, e para ASCII puro é mesmo. Mas no momento em que você decodifica emojis, caracteres acentuados, o payload de um JWT ou uma string URL-safe, a abordagem ingênua quebra de formas sutis e frustrantes. Este guia percorre todos os métodos confiáveis, tanto no navegador quanto no Node.js, com os casos extremos que de fato afetam os desenvolvedores em produção.
Se você só precisa de um resultado agora mesmo sem escrever código, cole sua string em Base64 Decode e leia o texto puro na hora. Para todo o resto, veja como fazer isso corretamente em código.
A resposta rápida: atob()
Todos os navegadores (e o Node.js moderno) expõem duas funções globais:
btoa()— binary to aSCII (codificar)atob()— aSCII to binary (decodificar)
atob('SGVsbG8sIFdvcmxkIQ=='); // "Hello, World!"
btoa('Hello, World!'); // "SGVsbG8sIFdvcmxkIQ=="
Para texto ASCII simples, isso é tudo o que você precisa. O problema é que atob() devolve uma string binária: uma string em que cada caractere representa um byte (0–255). Isso funciona perfeitamente com caracteres latinos, mas estraga qualquer coisa fora da faixa ASCII.
O problema do Unicode
Tente decodificar uma string Base64 que contenha um caractere não ASCII e você verá lixo:
// "Héllo" codificado como UTF-8 e depois Base64 é "SMOpbGxv"
atob('SMOpbGxv'); // "Héllo" ❌ mojibake
O é acentuado saiu como dois caracteres soltos. Por quê? Porque atob() lhe dá bytes brutos, e o é em UTF-8 são dois bytes (0xC3 0xA9). Tratar esses dois bytes como dois caracteres separados produz o clássico mojibake é.
A solução é pegar os bytes de atob() e decodificá-los como UTF-8 de forma explícita.
A forma moderna e correta: TextDecoder
function decodeBase64Utf8(b64) {
const binary = atob(b64);
const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
return new TextDecoder('utf-8').decode(bytes);
}
decodeBase64Utf8('SMOpbGxv'); // "Héllo" ✅
TextDecoder está integrado em todos os navegadores modernos e no Node.js. É a abordagem recomendada em 2024 e em diante: rápida, baseada em padrões e correta para toda a faixa Unicode, incluindo emojis.
// "🚀 launch" faz a ida e volta corretamente
const bytes = new TextEncoder().encode('🚀 launch');
const b64 = btoa(String.fromCharCode(...bytes));
decodeBase64Utf8(b64); // "🚀 launch" ✅
Decodificar Base64 no Node.js
O Node.js tem sua própria API, mais limpa, através da classe Buffer. Você não precisa de atob() de jeito nenhum (embora ele exista como global desde o Node 16).
// Decodificar Base64 para uma string UTF-8
Buffer.from('SMOpbGxv', 'base64').toString('utf-8'); // "Héllo"
// Codificar uma string UTF-8 para Base64
Buffer.from('Héllo', 'utf-8').toString('base64'); // "SMOpbGxv"
Buffer lida com Unicode corretamente de fábrica porque você informa a ele a codificação de saída ('utf-8'). Esta é a forma idiomática de decodificar Base64 em qualquer JavaScript do lado do servidor, incluindo handlers do Express, funções serverless e scripts de build.
Decodificar para bytes brutos (arquivos, imagens)
Quando o Base64 representa dados binários —uma imagem, um PDF, uma chave criptográfica— não o converta para uma string. Mantenha-o como um Buffer:
import { writeFileSync } from 'node:fs';
const b64 = 'iVBORw0KGgoAAAANSUhEUgAA...'; // um PNG, codificado
const buffer = Buffer.from(b64, 'base64');
writeFileSync('output.png', buffer); // grava a imagem real
Converter dados binários para uma string UTF-8 os corromperia, porque a maioria das sequências de bytes não é UTF-8 válido.
Lidar com Base64 URL-safe
JWTs, tokens OAuth e muitas APIs usam Base64 URL-safe (RFC 4648 §5), que troca dois caracteres e muitas vezes remove o preenchimento:
| Padrão | URL-safe |
|---|---|
+ |
- |
/ |
_ |
preenchimento = |
geralmente omitido |
O atob() nativo e o Buffer.from(..., 'base64') esperam o alfabeto padrão, então você precisa normalizar primeiro:
function decodeBase64Url(b64url) {
// 1. Restaurar o alfabeto padrão
let b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
// 2. Recolocar o preenchimento para que o comprimento seja múltiplo de 4
while (b64.length % 4) b64 += '=';
// 3. Decodificar como UTF-8
const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
return new TextDecoder('utf-8').decode(bytes);
}
// Decodificar o segmento de payload de um JWT
const payload = 'eyJ1c2VyIjoiam9obiIsImFkbWluIjp0cnVlfQ';
decodeBase64Url(payload); // '{"user":"john","admin":true}'
O Node 16+ também aceita diretamente a codificação 'base64url', que cuida de tudo isso para você:
Buffer.from('eyJ1c2VyIjoiam9obiJ9', 'base64url').toString('utf-8');
// '{"user":"john"}'
Se você quiser inspecionar um token sem escrever código, o decodificador de JWT faz a divisão e a decodificação Base64URL por você. Para entender o panorama geral de como esses formatos se relacionam, consulte codificar vs decodificar.
Tratamento de erros
atob() lança uma DOMException ("InvalidCharacterError") quando a entrada não é Base64 válido. Sempre envolva a decodificação em uma proteção, especialmente quando a entrada vem de usuários ou de APIs externas:
function safeDecode(b64) {
try {
const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
} catch (err) {
return null; // Base64 inválido ou UTF-8 inválido
}
}
Passar { fatal: true } para o TextDecoder faz com que ele lance uma exceção diante de sequências de bytes malformadas em vez de inserir silenciosamente caracteres de substituição (�). Isso costuma ser o que você quer: falhar de forma ruidosa em vez de entregar texto corrompido.
Causas comuns de falhas na decodificação:
- Espaços em branco ou quebras de linha na string: remova-os com
.replace(/\s/g, '')antes de decodificar (o Base64 MIME quebra as linhas a cada 76 caracteres). - Preenchimento ausente: recoloque
=até que o comprimento seja divisível por 4. - Caracteres URL-safe (
-,_) passados para um decodificador padrão: normalize-os primeiro. - Dados codificados duas vezes: alguém codificou uma string que já estava codificada.
Uma função reutilizável e pronta para produção
Aqui está uma única função que lida com entrada padrão e URL-safe, espaços em branco, preenchimento ausente e Unicode, adequada tanto para o navegador quanto para o Node.js moderno:
function decodeBase64(input) {
let b64 = input.trim()
.replace(/\s+/g, '') // remover quebras de linha MIME
.replace(/-/g, '+') // URL-safe → padrão
.replace(/_/g, '/');
while (b64.length % 4) b64 += '='; // corrigir o preenchimento
const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
}
Coloque isso em qualquer projeto e ela se comportará de forma previsível diante das strings desordenadas do mundo real que você realmente recebe.
Perguntas frequentes
Por que atob() devolve caracteres estranhos para texto acentuado ou emojis?
Porque atob() devolve uma string binária de bytes brutos, não texto decodificado. Caracteres UTF-8 de múltiplos bytes (acentos, emojis, CJK) voltam como bytes separados e aparecem como mojibake. Passe os bytes por TextDecoder('utf-8') para recuperar o texto original.
atob() está obsoleto?
Não. atob() e btoa() continuam sendo padrão e têm suporte em toda parte. Eles são apenas de baixo nível: operam sobre strings binárias, então você os combina com TextDecoder/TextEncoder para Unicode. No Node.js, Buffer é a opção mais ergonômica.
Como decodifico Base64 no Node.js sem atob()?
Use Buffer.from(str, 'base64').toString('utf-8') para texto, ou mantenha o Buffer como está para dados binários como imagens e arquivos. Para entrada URL-safe, use a codificação 'base64url' (Node 16+).
Como decodifico o payload de um JWT em JavaScript?
Divida o token em ., pegue o segundo segmento (o payload) e decodifique-o como Base64 URL-safe; depois aplique JSON.parse() ao resultado. Observe que isso apenas lê o token: não verifica a assinatura. Use o decodificador de JWT para inspecionar tokens visualmente.
Qual é a diferença entre Base64 padrão e URL-safe?
O Base64 padrão usa + e / e preenche com =. O Base64 URL-safe os substitui por - e _ e geralmente omite o preenchimento, de modo que a string pode trafegar em URLs e nomes de arquivo sem escape. Normalize a entrada URL-safe de volta ao alfabeto padrão antes de decodificar com atob().
Como posso decodificar Base64 sem escrever nenhum código?
Cole a string em Base64 Decode e o texto puro aparece na hora no seu navegador. Ele lida automaticamente com espaços em branco, caracteres URL-safe e preenchimento ausente, e nenhum dado jamais sai do seu dispositivo.
Experimente você mesmo
Use nossa ferramenta online gratuita para começar imediatamente