Base64 en JavaScript — atob() et Buffer
Utilisez le Décodeur Base64 en ligne gratuit directement dans votre navigateur — sans installation.
Essayer Décodeur Base64 en ligne en ligne →Lorsque je débogue un problème d'authentification en production, la première chose que je cherche est un Décodeur Base64 — les charges utiles JWT, les signatures de webhook et les valeurs de configuration encodées se cachent toutes dans des chaînes Base64. JavaScript offre deux approches natives principales pour décoder en base64 : atob() (navigateur + Node.js 16+) et Buffer.from(encoded, 'base64').toString() (Node.js) — et leur comportement est très différent lorsque les données d'origine contiennent des caractères Unicode. Pour un décodage rapide sans écrire de code, le Décodeur Base64 de ToolDeck le gère instantanément dans votre navigateur. Ce guide couvre les deux environnements — ciblant Node.js 16+ et les navigateurs modernes (Chrome 80+, Firefox 75+, Safari 14+) — avec des exemples prêts pour la production : récupération UTF-8, variantes URL-safe, décodage JWT, fichiers, réponses API, streams Node.js, et les quatre erreurs qui produisent systématiquement une sortie corrompue dans les bases de code réelles.
- ✓atob(encoded) est natif au navigateur et disponible dans Node.js 16+ globalement, mais retourne une chaîne binaire — utilisez TextDecoder pour récupérer le texte UTF-8 pour tout contenu au-delà de l'ASCII.
- ✓Buffer.from(encoded, "base64").toString("utf8") est l'approche idiomatique de Node.js et gère l'UTF-8 automatiquement sans étapes supplémentaires.
- ✓Le Base64 URL-safe (utilisé dans les JWT) remplace + par -, / par _, et supprime le padding =. Restaurez ces caractères avant d'appeler atob(), ou utilisez Buffer.from(encoded, "base64url").toString() dans Node.js 18+.
- ✓Supprimez les espaces et les retours à la ligne avant de décoder — l'API GitHub Contents et de nombreux encodeurs MIME encapsulent la sortie Base64 à 60–76 caractères par ligne.
- ✓Uint8Array.prototype.fromBase64() (TC39 Stage 3) est déjà disponible dans Node.js 22+ et Chrome 130+ et unifiera à terme les deux environnements.
Qu'est-ce que le décodage Base64 ?
Le décodage Base64 est l'opération inverse de l'encodage — il convertit la représentation ASCII en 64 caractères vers les données binaires ou texte d'origine. Chaque groupe de 4 caractères Base64 correspond exactement à 3 octets. Les caractères de padding = à la fin d'une chaîne encodée indiquent au décodeur combien d'octets supplémentaires ont été ajoutés pour compléter le dernier groupe de 3 octets.
Le Base64 n'est pas un chiffrement — l'opération est complètement réversible par quiconque possède la chaîne encodée. Son but est la sécurité du transport : les protocoles et les formats de stockage conçus pour le texte ASCII 7 bits ne peuvent pas gérer des octets binaires arbitraires, et le Base64 comble cette lacune. Les scénarios courants de décodage JavaScript incluent l'inspection des charges utiles JWT, le décompactage des configs JSON encodées en Base64 depuis les variables d'environnement, l'extraction du contenu de fichiers binaires depuis les API REST, et le décodage des data URI dans le navigateur.
ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=
deploy-bot:sk-prod-a7f2c91e4b3d8
atob() — La fonction de décodage native du navigateur
atob()(ASCII-to-binary) est disponible dans les navigateurs depuis IE10 et est devenu une fonction globale dans Node.js 16.0 dans le cadre de l'initiative de compatibilité WinterCG. Elle fonctionne également nativement dans Deno, Bun et Cloudflare Workers — aucune importation requise.
La fonction retourne une chaîne binaire: une chaîne JavaScript où chaque caractère a un point de code égal à une valeur d'octet brute (0–255). Cela est important : si les données d'origine étaient du texte UTF-8 contenant des caractères au-delà de U+007F (lettres accentuées, cyrillique, CJK, emoji), la chaîne retournée est la séquence d'octets bruts, pas du texte lisible. Utilisez TextDecoder pour le récupérer (abordé dans la section suivante).
Exemple minimal fonctionnel
// Decoding an HTTP Basic Auth credential pair received in a request header
// Authorization: Basic ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=
function parseBasicAuth(header: string): { serviceId: string; apiKey: string } {
const base64Part = header.replace(/^Basics+/i, '')
const decoded = atob(base64Part)
const [serviceId, apiKey] = decoded.split(':')
return { serviceId, apiKey }
}
const auth = parseBasicAuth('Basic ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=')
console.log(auth.serviceId) // deploy-bot
console.log(auth.apiKey) // sk-prod-a7f2c91e4b3d8Vérification d'un aller-retour
// Verify lossless recovery for ASCII-only content const original = 'service:payments region:eu-west-1 env:production' const encoded = btoa(original) const decoded = atob(encoded) console.log(encoded) // c2VydmljZTpwYXltZW50cyByZWdpb246ZXUtd2VzdC0xIGVudjpwcm9kdWN0aW9u console.log(decoded === original) // true
atob() et btoa() font partie de la WinterCG Minimum Common API — la même spécification qui régit Fetch, URL et crypto dans les environnements non-navigateur. Leur comportement est identique dans Node.js 16+, Bun, Deno et Cloudflare Workers.Récupérer le texte UTF-8 après décodage
Le piège le plus courant avec atob()est de mal comprendre son type de retour. Lorsque le texte d'origine a été encodé en UTF-8 avant le Base64, atob() retourne une chaîne binaire Latin-1, pas le texte lisible :
// 'Алексей Иванов' was UTF-8 encoded then Base64 encoded before transmission const encoded = '0JDQu9C10LrRgdC10Lkg0JjQstCw0L3QvtCy' // ❌ atob() returns the raw UTF-8 bytes as a Latin-1 string — garbled output console.log(atob(encoded)) // "Алексей Р˜РІР°РЅРѕРІ" ← byte values misread as Latin-1
L'approche correcte utilise TextDecoder pour interpréter ces octets bruts en UTF-8 :
Approche TextDecoder — sûre pour toute sortie Unicode
// Unicode-safe Base64 decode utilities
function fromBase64(encoded: string): string {
const binary = atob(encoded)
const bytes = Uint8Array.from(binary, ch => ch.charCodeAt(0))
return new TextDecoder().decode(bytes)
}
function toBase64(text: string): string {
const bytes = new TextEncoder().encode(text)
const chars = Array.from(bytes, byte => String.fromCharCode(byte))
return btoa(chars.join(''))
}
// Works with any language or script
const orderNote = 'Confirmed: 田中太郎 — São Paulo warehouse, qty: 250'
const encoded = toBase64(orderNote)
const decoded = fromBase64(encoded)
console.log(decoded === orderNote) // true
console.log(decoded)
// Confirmed: 田中太郎 — São Paulo warehouse, qty: 250Buffer.from(encoded, 'base64').toString('utf8'). Il interprète les octets décodés en UTF-8 automatiquement et est plus rapide pour les grandes entrées.Buffer.from() dans Node.js — Guide complet de décodage
Dans Node.js, Bufferest l'API idiomatique pour toutes les opérations binaires, y compris le décodage Base64. Il gère l'UTF-8 nativement, retourne un Buffercorrect (sûr pour le binaire), et depuis Node.js 18 prend en charge le raccourci d'encodage 'base64url' pour les variantes URL-safe.
Décodage d'une variable d'environnement de configuration
// Server config stored as Base64 in an env variable (avoids JSON escaping in shell)
// DB_CONFIG=eyJob3N0IjoiZGItcHJpbWFyeS5pbnRlcm5hbCIsInBvcnQiOjU0MzIsImRhdGFiYXNlIjoiYW5hbHl0aWNzX3Byb2QiLCJtYXhDb25uZWN0aW9ucyI6MTAwfQ==
const raw = Buffer.from(process.env.DB_CONFIG!, 'base64').toString('utf8')
const dbConfig = JSON.parse(raw)
console.log(dbConfig.host) // db-primary.internal
console.log(dbConfig.port) // 5432
console.log(dbConfig.maxConnections) // 100Restaurer un fichier binaire depuis un fichier .b64
import { readFileSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
// Read the Base64-encoded certificate and restore the original binary
const encoded = readFileSync(join(process.cwd(), 'dist', 'cert.b64'), 'utf8').trim()
const certBuf = Buffer.from(encoded, 'base64')
writeFileSync('./ssl/server.crt', certBuf)
console.log(`Restored ${certBuf.length} bytes`)
// Restored 2142 bytesDécodage asynchrone avec gestion des erreurs
import { readFile, writeFile } from 'node:fs/promises'
async function decodeBase64File(
encodedPath: string,
outputPath: string,
): Promise<number> {
try {
const encoded = await readFile(encodedPath, 'utf8')
const binary = Buffer.from(encoded.trim(), 'base64')
await writeFile(outputPath, binary)
return binary.length
} catch (err) {
const code = (err as NodeJS.ErrnoException).code
if (code === 'ENOENT') throw new Error(`File not found: ${encodedPath}`)
if (code === 'EACCES') throw new Error(`Permission denied: ${encodedPath}`)
throw err
}
}
// Restore a PDF stored as Base64
const bytes = await decodeBase64File('./uploads/invoice.b64', './out/invoice.pdf')
console.log(`Decoded ${bytes} bytes — PDF restored`)Fonctions de décodage Base64 — Référence des paramètres
Référence rapide pour les paramètres des deux API de décodage natives principales, formatée pour être utilisée comme aide-mémoire lors de l'écriture ou de la révision du code.
atob(encodedData)
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
| encodedData | string | Oui | Chaîne Base64 standard utilisant les caractères +, /, =. Les variantes URL-safe (-, _) génèrent une InvalidCharacterError. Les espaces ne sont pas autorisés. |
Buffer.from(input, inputEncoding) / .toString(outputEncoding)
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
| input | string | Buffer | TypedArray | ArrayBuffer | obligatoire | La chaîne encodée en Base64 à décoder, ou un tampon contenant des octets encodés. |
| inputEncoding | BufferEncoding | "utf8" | Définir sur "base64" pour le Base64 standard (RFC 4648 §4), ou "base64url" pour le Base64 URL-safe (RFC 4648 §5, Node.js 18+). |
| outputEncoding | string | "utf8" | Encodage pour la sortie .toString(). Utilisez "utf8" pour le texte lisible, "binary" pour une chaîne binaire Latin-1 compatible avec la sortie atob(). |
| start | integer | 0 | Décalage d'octet dans le Buffer décodé pour commencer la lecture. Passé à .toString() comme deuxième argument. |
| end | integer | buf.length | Décalage d'octet pour arrêter la lecture (exclusif). Passé à .toString() comme troisième argument. |
Base64 URL-safe — Décoder les JWT et les paramètres d'URL
Les JWT utilisent le Base64 URL-safe (RFC 4648 §5) pour les trois segments. Le Base64 URL-safe remplace + par - et / par _, et supprime le padding = de fin. Passer cela directement à atob() sans restauration produit une sortie incorrecte ou génère une erreur.
Navigateur — restaurer les caractères et le padding avant le décodage
function decodeBase64Url(input: string): string {
const base64 = input.replace(/-/g, '+').replace(/_/g, '/')
const padded = base64 + '==='.slice(0, (4 - base64.length % 4) % 4)
const binary = atob(padded)
const bytes = Uint8Array.from(binary, ch => ch.charCodeAt(0))
return new TextDecoder().decode(bytes)
}
// Inspect a JWT payload segment (the middle part between the two dots)
const jwtToken = 'eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciIsIndvcmtzcGFjZUlkIjoid3NfM2E3ZjkxYzIiLCJleHAiOjE3MTcyMDM2MDB9'
const payload = decodeBase64Url(jwtToken)
const claims = JSON.parse(payload)
console.log(claims.userId) // usr_9f2a1c3e8b4d
console.log(claims.role) // editor
console.log(claims.workspaceId) // ws_3a7f91c2Node.js 18+ — encodage natif 'base64url'
// Node.js 18 added 'base64url' as a first-class Buffer encoding — no manual replace needed
function decodeJwtSegment(segment: string): Record<string, unknown> {
const json = Buffer.from(segment, 'base64url').toString('utf8')
return JSON.parse(json)
}
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciIsIndvcmtzcGFjZUlkIjoid3NfM2E3ZjkxYzIiLCJleHAiOjE3MTcyMDM2MDB9.SIGNATURE'
const [headerB64, payloadB64] = token.split('.')
const header = decodeJwtSegment(headerB64)
const payload = decodeJwtSegment(payloadB64)
console.log(header.alg) // HS256
console.log(payload.role) // editor
console.log(payload.workspaceId) // ws_3a7f91c2Décoder le Base64 depuis des fichiers et des réponses API
Dans le code de production, le décodage Base64 se produit le plus souvent lors de la consommation d'API externes qui livrent du contenu sous forme encodée. Les deux scénarios présentent des pièges importants concernant les espaces et la sortie binaire vs texte. Si vous avez juste besoin d'inspecter une réponse encodée lors du débogage, collez-la directement dans le Décodeur Base64 — il gère les modes standard et URL-safe instantanément.
Décoder le contenu depuis l'API GitHub Contents
// GitHub Contents API returns file content as Base64, wrapped at 60 chars per line
async function fetchDecodedFile(
owner: string,
repo: string,
path: string,
token: string,
): Promise<string> {
const res = await fetch(
`https://api.github.com/repos/${owner}/${repo}/contents/${path}`,
{ headers: { Authorization: `Bearer ${token}`, Accept: 'application/vnd.github.v3+json' } }
)
if (!res.ok) throw new Error(`GitHub API ${res.status}: ${res.statusText}`)
const data = await res.json() as { content: string; encoding: string }
if (data.encoding !== 'base64') throw new Error(`Unexpected encoding: ${data.encoding}`)
// ⚠️ GitHub wraps at 60 chars — strip newlines before decoding
const clean = data.content.replace(/\n/g, '')
return Buffer.from(clean, 'base64').toString('utf8')
}
const openApiSpec = await fetchDecodedFile('acme-corp', 'platform-api', 'openapi.json', process.env.GITHUB_TOKEN!)
const spec = JSON.parse(openApiSpec)
console.log(`API version: ${spec.info.version}`)Décoder un binaire encodé en Base64 depuis une API (navigateur)
// Some APIs return binary content (images, PDFs) as Base64 JSON fields
async function downloadDecodedFile(endpoint: string, authToken: string): Promise<void> {
const res = await fetch(endpoint, { headers: { Authorization: `Bearer ${authToken}` } })
if (!res.ok) throw new Error(`Download failed: ${res.status}`)
const { filename, content, mimeType } = await res.json() as {
filename: string; content: string; mimeType: string
}
// Decode Base64 → binary bytes → Blob
const binary = atob(content)
const bytes = Uint8Array.from(binary, ch => ch.charCodeAt(0))
const blob = new Blob([bytes], { type: mimeType })
// Trigger browser download
const url = URL.createObjectURL(blob)
const a = Object.assign(document.createElement('a'), { href: url, download: filename })
a.click()
URL.revokeObjectURL(url)
}
await downloadDecodedFile('/api/reports/latest', sessionStorage.getItem('auth_token')!)Décodage Base64 en ligne de commande dans Node.js et Shell
Pour les scripts CI/CD, les sessions de débogage ou les tâches de décodage ponctuelles, les outils shell et les commandes Node.js en une ligne sont plus rapides qu'un script complet. Notez que le nom du paramètre diffère entre macOS et Linux.
# ── macOS / Linux system base64 ───────────────────────────────────────
# Standard decoding (macOS uses -D, Linux uses -d)
echo "ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=" | base64 -d # Linux
echo "ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=" | base64 -D # macOS
# Decode a .b64 file to its original binary
base64 -d ./dist/cert.b64 > ./ssl/server.crt # Linux
base64 -D -i ./dist/cert.b64 -o ./ssl/server.crt # macOS
# URL-safe Base64 — restore + and / before decoding
echo "eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ" | tr '-_' '+/' | base64 -d
# ── Node.js one-liner — works on Windows too ───────────────────────────
node -e "process.stdout.write(Buffer.from(process.argv[1], 'base64').toString())" "ZGVwbG95LWJvdA=="
# deploy-bot
# URL-safe (Node.js 18+)
node -e "process.stdout.write(Buffer.from(process.argv[1], 'base64url').toString())" "eyJhbGciOiJIUzI1NiJ9"
# {"alg":"HS256"}base64 utilise -D pour décoder (D majuscule), tandis que Linux utilise -d(minuscule). Cela peut faire échouer silencieusement les scripts CI — utilisez une commande Node.js en une ligne lorsque la plateforme cible n'est pas garantie d'être Linux.Alternative haute performance : js-base64
La principale raison d'utiliser une bibliothèque est la cohérence entre environnements. Si vous publiez un package qui s'exécute à la fois dans le navigateur et Node.js sans configuration de bundler, Buffernécessite une détection d'environnement et atob() nécessite la solution de contournement TextDecoder. js-base64 (plus de 100 millions de téléchargements hebdomadaires sur npm) gère les deux de manière transparente.
npm install js-base64 # or pnpm add js-base64
import { fromBase64, fromBase64Url, isValid } from 'js-base64'
// Standard decoding — Unicode-safe, works in browser and Node.js
const raw = fromBase64('eyJldmVudElkIjoiZXZ0XzdjM2E5ZjFiMmQiLCJ0eXBlIjoiY2hlY2tvdXRfY29tcGxldGVkIiwiY3VycmVuY3kiOiJFVVIiLCJhbW91bnQiOjE0OTAwfQ==')
const event = JSON.parse(raw)
console.log(event.type) // checkout_completed
console.log(event.currency) // EUR
// URL-safe decoding — no manual character replacement needed
const jwtPayload = fromBase64Url('eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciJ9')
const claims = JSON.parse(jwtPayload)
console.log(claims.role) // editor
// Validate before decoding untrusted input
const untrusted = 'not!valid@base64#'
if (!isValid(untrusted)) {
console.error('Rejected: invalid Base64 input')
}
// Binary output — second argument true returns Uint8Array
const pngBytes = fromBase64('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==', true)
console.log(pngBytes instanceof Uint8Array) // trueSortie terminal avec coloration syntaxique
Lors de l'écriture d'outils CLI de débogage ou de scripts d'inspection, la sortie brute de console.log est difficile à lire pour de grandes charges utiles JSON. chalk(le package npm le plus téléchargé pour la coloration terminale) combiné avec le décodage Base64 produit une sortie terminale lisible et analysable — utile pour l'inspection des JWT, le débogage des réponses API et l'audit de configuration.
npm install chalk # chalk v5+ is ESM-only — use import, not require
import chalk from 'chalk'
// Decode and display any Base64 value with smart type detection
function inspectBase64(encoded: string, label = 'Decoded value'): void {
let decoded: string
try {
decoded = Buffer.from(encoded.trim(), 'base64').toString('utf8')
} catch {
console.error(chalk.red('✗ Invalid Base64 input'))
return
}
console.log(chalk.bold.cyan(`\n── ${label} ──`))
// Attempt JSON pretty-print
try {
const parsed = JSON.parse(decoded)
console.log(chalk.green('Type:'), chalk.yellow('JSON'))
for (const [key, value] of Object.entries(parsed)) {
const display = typeof value === 'object' ? JSON.stringify(value) : String(value)
console.log(chalk.green(` ${key}:`), chalk.white(display))
}
return
} catch { /* not JSON */ }
// Plain text fallback
console.log(chalk.green('Type:'), chalk.yellow('text'))
console.log(chalk.white(decoded))
}
// Inspect a Base64-encoded JWT payload
const tokenParts = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciIsImV4cCI6MTcxNzIwMzYwMH0.SIGNATURE'.split('.')
inspectBase64(tokenParts[0], 'JWT Header')
inspectBase64(tokenParts[1], 'JWT Payload')
// ── JWT Header ──
// Type: JSON
// alg: HS256
// typ: JWT
//
// ── JWT Payload ──
// Type: JSON
// userId: usr_9f2a1c3e8b4d
// role: editor
// exp: 1717203600Décoder de grands fichiers Base64 avec les streams Node.js
Lorsqu'un fichier encodé en Base64 dépasse ~50 Mo, le charger entièrement en mémoire avec readFileSync() devient problématique. Les streams Node.js vous permettent de décoder les données par morceaux — mais le Base64 nécessite des multiples de 4 caractères par morceau (chaque groupe de 4 caractères se décode en exactement 3 octets) pour éviter les erreurs de padding aux limites des morceaux.
import { createReadStream, createWriteStream } from 'node:fs'
import { pipeline } from 'node:stream/promises'
async function streamDecodeBase64(inputPath: string, outputPath: string): Promise<void> {
const readStream = createReadStream(inputPath, { encoding: 'utf8', highWaterMark: 4 * 1024 * 192 })
const writeStream = createWriteStream(outputPath)
let buffer = ''
await pipeline(
readStream,
async function* (source) {
for await (const chunk of source) {
buffer += (chunk as string).replace(/\s/g, '') // strip any whitespace/newlines
// Decode only complete 4-char groups to avoid mid-stream padding issues
const remainder = buffer.length % 4
const safe = buffer.slice(0, buffer.length - remainder)
buffer = buffer.slice(buffer.length - remainder)
if (safe.length > 0) yield Buffer.from(safe, 'base64')
}
if (buffer.length > 0) yield Buffer.from(buffer, 'base64')
},
writeStream,
)
}
// Decode a 200 MB video that was stored as Base64
await streamDecodeBase64('./uploads/product-demo.b64', './dist/product-demo.mp4')
console.log('Stream decode complete')4 × 1024 × 192 = 786 432 caractères (768 Ko). Pour les fichiers inférieurs à 50 Mo, readFile() + Buffer.from(content.trim(), 'base64') est plus simple et suffisamment rapide.Erreurs courantes
J'ai vu ces quatre erreurs dans des bases de code JavaScript à maintes reprises — elles ont tendance à rester cachées jusqu'à ce qu'un caractère non ASCII ou une réponse API encapsulée sur plusieurs lignes atteigne le chemin de décodage en production.
Erreur 1 — Utiliser atob() sans TextDecoder pour le contenu UTF-8
Problème : atob()retourne une chaîne binaire où chaque caractère est une valeur d'octet brut. Les séquences multi-octets UTF-8 (cyrillique, CJK, lettres accentuées) apparaissent comme des caractères Latin-1 corrompus. Solution : encapsulez la sortie dans TextDecoder.
// ❌ atob() returns the raw UTF-8 bytes as a Latin-1 string const encoded = '0JDQu9C10LrRgdC10Lkg0JjQstCw0L3QvtCy' const decoded = atob(encoded) console.log(decoded) // "Алексей Р˜РІР°РЅРѕРІ" ← wrong
// ✅ Use TextDecoder to correctly interpret the UTF-8 bytes const encoded = '0JDQu9C10LrRgdC10Lkg0JjQstCw0L3QvtCy' const binary = atob(encoded) const bytes = Uint8Array.from(binary, ch => ch.charCodeAt(0)) const decoded = new TextDecoder().decode(bytes) console.log(decoded) // Алексей Иванов ✓
Erreur 2 — Passer du Base64 URL-safe directement à atob()
Problème : Les segments JWT utilisent - et _ au lieu de + et /, sans padding. atob() peut retourner des données incorrectes ou générer une erreur. Solution : restaurez d'abord les caractères standard et rajoutez le padding.
// ❌ URL-safe JWT segment passed directly — unreliable const jwtPayload = 'eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ' const decoded = atob(jwtPayload) // May produce wrong result or throw
// ✅ Restore standard Base64 chars and padding first
function decodeBase64Url(input: string): string {
const b64 = input.replace(/-/g, '+').replace(/_/g, '/')
const pad = b64 + '==='.slice(0, (4 - b64.length % 4) % 4)
const bin = atob(pad)
const bytes = Uint8Array.from(bin, ch => ch.charCodeAt(0))
return new TextDecoder().decode(bytes)
}
const decoded = decodeBase64Url('eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ')
// {"userId":"usr_9f2a1c3e"} ✓Erreur 3 — Ne pas supprimer les retours à la ligne du Base64 encapsulé
Problème : L'API GitHub Contents et les encodeurs MIME encapsulent la sortie Base64 à 60–76 caractères par ligne. atob() génère une InvalidCharacterError sur les caractères \n. Solution : supprimez tous les espaces avant de décoder.
// ❌ GitHub API content field contains embedded newlines const data = await res.json() const decoded = atob(data.content) // ❌ throws InvalidCharacterError
// ✅ Strip newlines (and any other whitespace) before decoding const data = await res.json() const clean = data.content.replace(/\s/g, '') const decoded = atob(clean) // ✓
Erreur 4 — Appeler .toString() sur du contenu binaire décodé
Problème : Lorsque les données d'origine sont binaires (images, PDF, audio), appeler .toString('utf8')remplace les séquences d'octets non reconnues par U+FFFD, corrompant silencieusement la sortie. Solution : conservez le résultat sous forme de Buffer — ne le convertissez pas en chaîne.
// ❌ .toString('utf8') corrupts binary content
import { readFileSync, writeFileSync } from 'node:fs'
const encoded = readFileSync('./uploads/invoice.b64', 'utf8').trim()
const corrupted = Buffer.from(encoded, 'base64').toString('utf8') // ❌
writeFileSync('./out/invoice.pdf', corrupted) // ❌ unreadable PDF// ✅ Keep the Buffer as binary — do not convert to a string
import { readFileSync, writeFileSync } from 'node:fs'
const encoded = readFileSync('./uploads/invoice.b64', 'utf8').trim()
const binary = Buffer.from(encoded, 'base64') // ✓ raw bytes preserved
writeFileSync('./out/invoice.pdf', binary) // ✓ valid PDFMéthodes de décodage Base64 en JavaScript — Comparaison rapide
| Méthode | Sortie UTF-8 | Sortie binaire | URL-safe | Environnements | Installation requise |
|---|---|---|---|---|---|
| atob() | ❌ nécessite TextDecoder | ✅ chaîne binaire | ❌ restauration manuelle | Navigateur, Node 16+, Bun, Deno | Non |
| TextDecoder + atob() | ✅ UTF-8 | ✅ via Uint8Array | ❌ restauration manuelle | Navigateur, Node 16+, Deno | Non |
| Buffer.from().toString() | ✅ utf8 | ✅ garder comme Buffer | ✅ base64url (Node 18+) | Node.js, Bun | Non |
| Uint8Array.fromBase64() (TC39) | ✅ via TextDecoder | ✅ natif | ✅ option alphabet | Chrome 130+, Node 22+ | Non |
| js-base64 | ✅ toujours | ✅ Uint8Array | ✅ intégré | Universel | npm install |
Choisissez atob()uniquement lorsque le contenu décodé est garanti être du texte ASCII. Pour tout texte fourni par l'utilisateur ou multilingue dans un navigateur, utilisez TextDecoder + atob(). Pour le code côté serveur Node.js, Bufferest le bon choix par défaut — il gère l'UTF-8 automatiquement et préserve les données binaires intactes. Pour les bibliothèques multi-environnements, js-base64 élimine tous les cas particuliers.
Questions fréquemment posées
Outils connexes
Pour un décodage en un clic sans écrire de code, collez votre chaîne Base64 directement dans le Décodeur Base64 — il gère les modes standard et URL-safe avec une sortie immédiate dans votre navigateur.
Alex is a front-end and Node.js developer with extensive experience building web applications and developer tooling. He is passionate about web standards, browser APIs, and the JavaScript ecosystem. In his spare time he contributes to open-source projects and writes about modern JavaScript patterns, performance optimisation, and everything related to the web platform.
Sophie is a full-stack developer focused on TypeScript across the entire stack — from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.