Encodage Base64 en JavaScript : Guide complet

·Front-end & Node.js Developer·Révisé parSophie Laurent·Publié

Utilisez le Encodeur Base64 en Ligne gratuit directement dans votre navigateur — sans installation.

Essayer Encodeur Base64 en Ligne en ligne →

Lorsque vous intégrez une image dans une URI de données CSS, transmettez des identifiants dans un en-tête HTTP Authorization, ou stockez un certificat binaire dans une variable d'environnement, vous devez encoder des données JavaScript en Base64 de manière fiable aussi bien dans le navigateur que dans Node.js. JavaScript fournit deux API intégrées distinctes :btoa() pour les environnements navigateur (également disponible dans Node.js 16+) et Buffer.from() pour Node.js — chacune avec des contraintes différentes concernant Unicode, les données binaires et la sécurité des URL. Pour un encodage rapide sans écrire de code, l'encodeur Base64 de ToolDeck le fait instantanément dans le navigateur. Ce guide couvre les deux environnements avec des exemples prêts pour la production : gestion d'Unicode, variantes URL-safe, encodage de fichiers et de réponses d'API, utilisation CLI, et les quatre erreurs qui causent des bugs de façon récurrente dans les bases de code réelles.

  • btoa() est natif au navigateur et disponible globalement dans Node.js 16+, mais n'accepte que le Latin-1 (points de code 0–255) — une entrée Unicode lève une DOMException
  • Buffer.from(text, "utf8").toString("base64") est l'équivalent Node.js et gère Unicode nativement sans étapes supplémentaires
  • Le Base64 URL-safe remplace + → -, / → _, et supprime le rembourrage = — utilisez Buffer.from().toString("base64url") dans Node.js 18+ pour une solution en une ligne
  • Pour les données binaires (ArrayBuffer, Uint8Array, fichiers), utilisez Buffer dans Node.js ou l'approche arrayBuffer() + Uint8Array dans le navigateur — jamais response.text()
  • Uint8Array.prototype.toBase64() (TC39 Stage 3) est déjà disponible dans Node.js 22+ et Chrome 130+ et unifiera les deux environnements

Qu'est-ce que l'encodage Base64 ?

Base64 convertit des données binaires arbitraires en une chaîne construite à partir de 64 caractères ASCII imprimables : A–Z, a–z, 0–9, +, et /. Chaque 3 octets d'entrée sont mappés vers exactement 4 caractères Base64 ; si la longueur de l'entrée n'est pas un multiple de 3, un ou deux caractères de rembourrage =sont ajoutés. La sortie encodée est toujours environ 33 % plus grande que l'original.

Base64 n'est pasdu chiffrement — il n'offre aucune confidentialité. Toute personne disposant de la chaîne encodée peut la décoder en un seul appel de fonction. Son but est la sécurité du transport : de nombreux protocoles et formats de stockage ont été conçus pour du texte ASCII 7 bits et ne peuvent pas gérer des octets binaires arbitraires. Base64 comble cette lacune. Les cas d'usage courants en JavaScript incluent les URI de données pour l'intégration d'assets, les en-têtes HTTP Basic Auth, les segments de jetons JWT, les pièces jointes MIME d'e-mail, et le stockage de blobs binaires dans des API JSON.

Before · text
After · text
deploy-bot:sk-prod-a7f2c91e4b3d8
ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=

btoa() — La fonction d'encodage native du navigateur

btoa()(binary-to-ASCII) est disponible dans les navigateurs depuis IE10 et est devenue une 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. Aucun import n'est nécessaire.

La fonction prend un seul argument chaîne et retourne sa forme encodée en Base64. La contrepartie symétrique atob()(ASCII-to-binary) la décode en retour. Les deux sont synchrones et s'exécutent avec une mémoire constante relative à la taille de l'entrée.

Exemple minimal fonctionnel

JavaScript (browser / Node.js 16+)
// Encoding an API credential pair for an HTTP Basic Auth header
const serviceId  = 'deploy-bot'
const apiKey     = 'sk-prod-a7f2c91e4b3d8'

const credential = btoa(`${serviceId}:${apiKey}`)
// → 'ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg='

const headers = new Headers({
  Authorization: `Basic ${credential}`,
  'Content-Type': 'application/json',
})

console.log(headers.get('Authorization'))
// Basic ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=

Décodage avec atob()

JavaScript
// Round-trip: encode, transmit, decode
const payload = 'service:payments region:eu-west-1 env:production'

const encoded = btoa(payload)
const decoded = atob(encoded)

console.log(encoded)
// c2VydmljZTpwYXltZW50cyByZWdpb246ZXUtd2VzdC0xIGVudjpwcm9kdWN0aW9u

console.log(decoded === payload) // true
Remarque :btoa() et atob() font partie de la WinterCG Minimum Common API — la même spécification qui régit Fetch, URL et crypto dans les runtimes non-navigateurs. Elles se comportent de manière identique dans Node.js 16+, Bun, Deno et Cloudflare Workers.

Gestion d'Unicode et des caractères non-ASCII

Le piège le plus courant avec btoa() est sa limite stricte en Latin-1. Tout caractère avec un point de code supérieur à U+00FF provoque une exception immédiate :

JavaScript
btoa('Müller & Søren') // ❌ Uncaught DOMException: String contains an invalid character
btoa('résumé')         // ❌ 'é' is U+00E9 = 233 — within Latin-1, this one actually works
btoa('田中太郎')         // ❌ Throws — all CJK characters are above U+00FF

La bonne approche consiste à encoder d'abord la chaîne en octets UTF-8, puis à encoder ces octets en Base64. JavaScript fournit TextEncoder exactement à cet effet :

Approche TextEncoder — sûre pour toute entrée Unicode

JavaScript (browser + Node.js 16+)
// Utility functions for Unicode-safe Base64
function toBase64(text: string): string {
  const bytes = new TextEncoder().encode(text)
  const chars = Array.from(bytes, byte => String.fromCharCode(byte))
  return btoa(chars.join(''))
}

function fromBase64(encoded: string): string {
  const binary = atob(encoded)
  const bytes  = Uint8Array.from(binary, ch => ch.charCodeAt(0))
  return new TextDecoder().decode(bytes)
}

// Works with any language or script
const orderNote = 'Confirmé : Thomas Dupont — entrepôt Paris, qté : 250'
const encoded   = toBase64(orderNote)
const decoded   = fromBase64(encoded)

console.log(encoded)
// Q29uZmlybcOpIDogVGhvbWFzIER1cG9udCDigJMgZW50cmVww7R0IFBhcmlzLCBxdMOpIDogMjUw

console.log(decoded === orderNote) // true
Remarque :Si vous êtes déjà dans Node.js, ignorez complètement le contournement TextEncoder — utilisez Buffer.from(text, 'utf8').toString('base64'). Il gère Unicode nativement et est plus rapide pour les grandes chaînes.

Buffer.from() dans Node.js — Guide complet avec exemples

Dans Node.js, Bufferest l'API idiomatique pour toutes les opérations sur les données binaires, y compris les conversions d'encodage. Il précède TextEncoder de plusieurs années et reste le choix préféré pour le code côté serveur. Avantages clés par rapport à btoa(): support natif d'UTF-8, gestion des données binaires, et le raccourci d'encodage 'base64url' disponible depuis Node.js 18.

Encodage et décodage de texte basique

Node.js
// Encoding a server configuration object for storage in an env variable
const dbConfig = JSON.stringify({
  host:           'db-primary.internal',
  port:           5432,
  database:       'analytics_prod',
  maxConnections: 100,
  ssl:            { rejectUnauthorized: true },
})

const encoded = Buffer.from(dbConfig, 'utf8').toString('base64')
console.log(encoded)
// eyJob3N0IjoiZGItcHJpbWFyeS5pbnRlcm5hbCIsInBvcnQiOjU0MzIsImRhdGFiYXNlIjoiYW5h...

// Decoding back
const decoded = Buffer.from(encoded, 'base64').toString('utf8')
const config  = JSON.parse(decoded)

console.log(config.host)           // db-primary.internal
console.log(config.maxConnections) // 100

Encodage de fichiers binaires depuis le disque

Node.js
import { readFileSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'

// Read a TLS certificate and encode it for embedding in a config file
const certPem     = readFileSync(join(process.cwd(), 'ssl', 'server.crt'))
const certBase64  = certPem.toString('base64')

// Store as a single-line string — suitable for env vars or JSON configs
writeFileSync('./dist/cert.b64', certBase64, 'utf8')

console.log(`Certificate encoded: ${certBase64.length} characters`)
// Certificate encoded: 2856 characters

// Restore the binary cert from the encoded value
const restored = Buffer.from(certBase64, 'base64')
console.log(restored.equals(certPem)) // true

Encodage asynchrone de fichiers avec gestion des erreurs

Node.js
import { readFile } from 'node:fs/promises'

async function encodeFileToBase64(filePath: string): Promise<string> {
  try {
    const buffer = await readFile(filePath)
    return buffer.toString('base64')
  } catch (err) {
    const code = (err as NodeJS.ErrnoException).code
    if (code === 'ENOENT') throw new Error(`File not found: ${filePath}`)
    if (code === 'EACCES') throw new Error(`Permission denied: ${filePath}`)
    throw err
  }
}

// Encode a PDF for an email attachment payload
const reportBase64 = await encodeFileToBase64('./reports/q1-financials.pdf')

const emailPayload = {
  to:          'finance-team@company.internal',
  subject:     'Q1 Financial Report',
  attachments: [{
    filename:    'q1-financials.pdf',
    content:     reportBase64,
    encoding:    'base64',
    contentType: 'application/pdf',
  }],
}

console.log(`Attachment: ${reportBase64.length} chars`)

Fonctions Base64 JavaScript — Référence des paramètres

Contrairement au module base64de Python, JavaScript n'a pas de fonction Base64 unique et unifiée. L'API dépend de l'environnement cible. Voici la référence complète pour toutes les approches natives :

FonctionType d'entréeUnicodeURL-safeDisponible dans
btoa(string)string (Latin-1)❌ lève au-dessus de U+00FF❌ remplacement manuelBrowser, Node 16+, Bun, Deno
atob(string)Base64 string❌ retourne une chaîne binaire❌ remplacement manuelBrowser, Node 16+, Bun, Deno
Buffer.from(src, enc) .toString(enc)string | Buffer | Uint8Array✅ encodage utf8✅ base64url dans Node 18+Node.js, Bun
TextEncoder().encode(str) + btoa()string (tout Unicode)✅ via octets UTF-8❌ remplacement manuelBrowser, Node 16+, Deno
Uint8Array.toBase64() (TC39)Uint8Array✅ binaire✅ omitPadding + alphabetChrome 130+, Node 22+

La signature Buffer.from(src, enc).toString(enc) accepte plusieurs valeurs d'encodage pertinentes pour Base64 :

"base64"
Base64 standard (RFC 4648 §4). Utilise + et / avec rembourrage =.
"base64url"
Base64 URL-safe (RFC 4648 §5, Node.js 18+). Utilise - et _ sans rembourrage.
"utf8"
Par défaut pour les sources chaîne. À utiliser quand la source est du texte lisible par l'humain.
"binary"
Latin-1 / ISO-8859-1. Utilisé quand la source est une chaîne binaire brute (ex. : de atob()).

Base64 URL-safe — Encodage pour les JWT, URL et noms de fichier

Le Base64 standard utilise + et /, qui sont réservés dans les URL — + est décodé comme un espace dans les query strings, et /est un séparateur de chemin. Les JWT, paramètres d'URL, noms de fichier et valeurs de cookie nécessitent tous la variante URL-safe : +-, /_, = final supprimé.

Navigateur — remplacement manuel des caractères

JavaScript (browser)
function toBase64Url(text: string): string {
  // For ASCII-safe input (e.g., JSON with only ASCII chars)
  return btoa(text)
    .replace(/+/g, '-')
    .replace(///g, '_')
    .replace(/=/g, '')
}

function fromBase64Url(encoded: string): string {
  // Restore standard Base64 characters and padding before decoding
  const base64  = encoded.replace(/-/g, '+').replace(/_/g, '/')
  const padded  = base64 + '==='.slice(0, (4 - base64.length % 4) % 4)
  return atob(padded)
}

// JWT header — must be URL-safe Base64
const header  = JSON.stringify({ alg: 'HS256', typ: 'JWT' })
const encoded = toBase64Url(header)
console.log(encoded) // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

const decoded = fromBase64Url(encoded)
console.log(decoded) // {"alg":"HS256","typ":"JWT"}

Node.js 18+ — encodage natif 'base64url'

Node.js 18+
// Node.js 18 added 'base64url' as a first-class Buffer encoding
const sessionPayload = JSON.stringify({
  userId:     'usr_9f2a1c3e8b4d',
  role:       'editor',
  workspaceId:'ws_3a7f91c2',
  exp:        Math.floor(Date.now() / 1000) + 3600,
})

const encoded = Buffer.from(sessionPayload, 'utf8').toString('base64url')
// No + or / or = characters in the output
// eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2U4YjRkIiwicm9sZSI6ImVkaXRvciIsIndvcmtzcGFjZUlkIjoid3NfM2E3ZjkxYzIiLCJleHAiOjE3MTcyMDM2MDB9

const decoded = Buffer.from(encoded, 'base64url').toString('utf8')
console.log(JSON.parse(decoded).role) // editor

Encoder des fichiers et des réponses d'API en JavaScript

Dans le code de production, l'encodage Base64 est le plus souvent appliqué aux fichiers transmis et aux réponses d'API externes qui livrent du contenu binaire. Les patterns diffèrent entre le navigateur et Node.js, et les données binaires requièrent une attention particulière.

Navigateur — encoder un fichier depuis un élément input

JavaScript (browser)
// Modern approach: File.arrayBuffer() (Chrome 76+, Firefox 69+, Safari 14+)
async function encodeFile(file: File): Promise<string> {
  const buffer = await file.arrayBuffer()
  const bytes  = new Uint8Array(buffer)
  const chars  = Array.from(bytes, b => String.fromCharCode(b))
  return btoa(chars.join(''))
}

const uploadInput = document.getElementById('avatar') as HTMLInputElement

uploadInput.addEventListener('change', async (e) => {
  const file = (e.target as HTMLInputElement).files?.[0]
  if (!file) return

  try {
    const encoded = await encodeFile(file)
    const dataUri = `data:${file.type};base64,${encoded}`

    // Preview the image inline
    const img   = document.getElementById('preview') as HTMLImageElement
    img.src     = dataUri
    img.hidden  = false

    console.log(`Encoded ${file.name} (${file.size} bytes) → ${encoded.length} Base64 chars`)
  } catch (err) {
    console.error('Encoding failed:', err)
  }
})

Récupérer des données binaires encodées en Base64 depuis une API

JavaScript
// GitHub Contents API returns file content as Base64 with embedded newlines
async function fetchRepoFile(
  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; size: number }

  if (data.encoding !== 'base64') {
    throw new Error(`Unexpected encoding from GitHub: ${data.encoding}`)
  }

  // GitHub wraps output at 60 chars — strip newlines before decoding
  const clean = data.content.replace(/\n/g, '')
  return atob(clean)
}

const openApiSpec = await fetchRepoFile(
  'acme-corp', 'platform-api', 'openapi.json', process.env.GITHUB_TOKEN!
)
const spec = JSON.parse(openApiSpec)
console.log(`API version: ${spec.info.version}`)

Lorsque vous avez juste besoin d'inspecter une réponse encodée lors du débogage d'API sans configurer de script, collez la valeur Base64 directement dans l' encodeur Base64 — il décode aussi, avec une sortie immédiate. Utile pour inspecter les réponses de l'API GitHub, les payloads JWT et les signatures de webhook.

Encodage Base64 en ligne de commande avec Node.js et Shell

Pour les scripts CI/CD, les targets Makefile ou le débogage ponctuel, vous avez rarement besoin d'un script complet. Les outils système et les one-liners Node.js couvrent la plupart des cas de manière multiplateforme.

bash
# ── macOS / Linux system base64 ───────────────────────────────────────
# Standard encoding
echo -n "deploy-bot:sk-prod-a7f2c91e4b3d8" | base64
# ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=

# URL-safe variant (replace chars and strip padding)
echo -n "deploy-bot:sk-prod-a7f2c91e4b3d8" | base64 | tr '+/' '-_' | tr -d '='

# Encode a file inline (macOS: -b 0 removes line wrapping; Linux: --wrap=0)
base64 -b 0 ./config/production.json
# or on Linux:
base64 --wrap=0 ./config/production.json

# Decode
echo "ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=" | base64 --decode

# ── Node.js one-liner — works on Windows too ───────────────────────────
node -e "process.stdout.write(Buffer.from(process.argv[1]).toString('base64'))" "my:secret"
# bXk6c2VjcmV0

# URL-safe from Node.js 18+
node -e "process.stdout.write(Buffer.from(process.argv[1]).toString('base64url'))" "my:secret"
# bXk6c2VjcmV0  (same here since there are no special chars)

# Decode in Node.js
node -e "console.log(Buffer.from(process.argv[1], 'base64').toString())" "ZGVwbG95LWJvdA=="
Remarque :Sur macOS, base64coupe la sortie à 76 caractères par défaut. Cela casse l'analyse en aval. Ajoutez toujours -b 0 (macOS) ou --wrap=0(Linux) quand vous avez besoin d'un résultat sur une seule ligne — par exemple, lors de l'écriture dans une variable d'environnement ou un champ de configuration.

Alternative haute performance : js-base64

Les API intégrées conviennent à la plupart des cas d'usage. La principale raison de recourir à une bibliothèque est la cohérence inter-environnements : si vous publiez un package qui s'exécute dans le navigateur et dans Node.js, l'utilisation de Bufferrequiert soit la détection d'environnement, soit la configuration du bundler, tandis que btoa() nécessite le contournement Unicode. js-base64 (plus de 100 M de téléchargements hebdomadaires sur npm) gère les deux de manière transparente.

bash
npm install js-base64
# or
pnpm add js-base64
JavaScript
import { toBase64, fromBase64, toBase64Url, fromBase64Url, isValid } from 'js-base64'

// Standard encoding — Unicode-safe, works in browser and Node.js
const telemetryEvent = JSON.stringify({
  eventId:   'evt_7c3a9f1b2d',
  type:      'checkout_completed',
  currency:  'EUR',
  amount:    14900,
  userId:    'usr_4e2b8d6a5c',
  timestamp: 1717200000,
})

const encoded    = toBase64(telemetryEvent)
const urlEncoded = toBase64Url(telemetryEvent) // No +, /, or = characters

const decoded = fromBase64(encoded)
console.log(JSON.parse(decoded).type) // checkout_completed

// Binary data — pass a Uint8Array as second argument
const pngMagicBytes = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])
const binaryEncoded = toBase64(pngMagicBytes, true) // true = binary mode

// Validation before decoding
const suspicious = 'not!valid@base64#'
console.log(isValid(suspicious)) // false

En interne, js-base64 utilise Buffernatif quand il est disponible et se replie sur une implémentation JS pure dans le navigateur. Il est 2–3× plus rapide que l'approche TextEncoder+btoa pour les grandes chaînes Unicode, et l'API symétrique (toBase64 / fromBase64) élimine la charge mentale de se souvenir dans quel sens vont btoa et atob.

Encoder de grands fichiers binaires avec les Streams Node.js

Lorsque vous devez encoder des fichiers de plus de ~50 Mo, charger l'intégralité du fichier en mémoire avec readFileSync()devient un problème. Les streams Node.js vous permettent de traiter les données par morceaux — mais l'encodage Base64 a une contrainte : vous devez alimenter l'encodeur par multiples de 3 octets pour éviter un rembourrage incorrect aux limites des chunks.

Node.js
import { createReadStream, createWriteStream } from 'node:fs'
import { pipeline } from 'node:stream/promises'

// Stream a large binary file to a Base64-encoded output file
async function streamEncodeToBase64(
  inputPath:  string,
  outputPath: string,
): Promise<void> {
  const readStream  = createReadStream(inputPath, { highWaterMark: 3 * 1024 * 256 }) // 768 KB chunks (multiple of 3)
  const writeStream = createWriteStream(outputPath, { encoding: 'utf8' })

  let buffer = Buffer.alloc(0)

  await pipeline(
    readStream,
    async function* (source) {
      for await (const chunk of source) {
        buffer = Buffer.concat([buffer, chunk as Buffer])

        // Encode in complete 3-byte groups to avoid mid-stream padding
        const remainder = buffer.length % 3
        const safe      = buffer.subarray(0, buffer.length - remainder)
        buffer          = buffer.subarray(buffer.length - remainder)

        if (safe.length > 0) yield safe.toString('base64')
      }
      // Flush remaining bytes (may add 1 or 2 '=' padding chars)
      if (buffer.length > 0) yield buffer.toString('base64')
    },
    writeStream,
  )
}

// Usage: encode a 200 MB video attachment
await streamEncodeToBase64(
  './uploads/product-demo.mp4',
  './dist/product-demo.b64',
)
console.log('Stream encoding complete')
Remarque :La taille du chunk doit être un multiple de 3 octets pour éviter le rembourrage = parasite au milieu de la sortie. L'exemple utilise 3 * 1024 * 256 = 786 432 octets (768 Ko) — ajustez highWaterMark en fonction de votre budget mémoire. Pour les fichiers inférieurs à 50 Mo, readFile() + Buffer.toString('base64') est plus simple et suffisamment rapide.

Erreurs courantes

J'ai examiné de nombreuses bases de code JavaScript avec encodage Base64, et ces quatre erreurs apparaissent de façon récurrente — souvent non découvertes jusqu'à ce qu'un caractère non-ASCII ou un fichier binaire atteigne le chemin d'encodage en production.

Erreur 1 — Passer de l'Unicode directement à btoa()

Problème : btoa()n'accepte que les caractères avec des points de code 0–255. Les caractères comme ñ, les emojis ou les idéogrammes CJK provoquent une DOMException immédiate. Correction : encodez d'abord avec TextEncoder, ou utilisez Buffer.from(text, 'utf8').toString('base64') dans Node.js.

Before · JavaScript
After · JavaScript
// ❌ DOMException: The string to be encoded contains
//    characters outside of the Latin1 range
const username = 'Claire Martin'
const encoded  = btoa(username)  // throws
// ✅ Encode as UTF-8 bytes first
function safeEncode(text: string): string {
  const bytes = new TextEncoder().encode(text)
  const chars = Array.from(bytes, b => String.fromCharCode(b))
  return btoa(chars.join(''))
}
const encoded = safeEncode('Claire Martin')
// Q2xhaXJlIE1hcnRpbg==

Erreur 2 — Oublier de restaurer le rembourrage avant atob()

Problème : Le Base64 URL-safe supprime le rembourrage =. Passer la chaîne sans rembourrage directement à atob() produit une sortie incorrecte ou lève une exception selon la longueur de la chaîne. Correction : restaurez + et /et rajoutez la bonne quantité de rembourrage avant d'appeler atob().

Before · JavaScript
After · JavaScript
// ❌ atob() may return wrong data or throw
//    on URL-safe Base64 without padding
const jwtSegment = 'eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ'
const decoded    = atob(jwtSegment) // Unreliable
// ✅ Restore characters 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)
  return atob(pad)
}
const decoded = decodeBase64Url('eyJ1c2VySWQiOiJ1c3JfOWYyYTFjM2UifQ')
// {"userId":"usr_9f2a1c3e"}

Erreur 3 — Concaténer des chunks encodés plutôt que des buffers bruts

Problème : Chaque appel à btoa() ou .toString('base64')ajoute son propre rembourrage. Concaténer deux chaînes Base64 rembourrées produit une sortie invalide car le rembourrage ne doit figurer qu'à la toute fin. Correction : concaténez les données brutes avant l'encodage.

Before · JavaScript
After · JavaScript
// ❌ Both parts are padded independently —
//    the combined string is not valid Base64
const part1 = Buffer.from('webhook-secret').toString('base64')
// d2ViaG9vay1zZWNyZXQ=  ← has padding
const part2 = Buffer.from('-v2').toString('base64')
// LXYy            ← correct in isolation
const combined = part1 + part2 // ❌ Invalid — padding in the middle
// ✅ Concatenate raw Buffers before encoding
const combined = Buffer.concat([
  Buffer.from('webhook-secret'),
  Buffer.from('-v2'),
]).toString('base64')
// d2ViaG9vay1zZWNyZXQtdjI= — single valid Base64 string

Erreur 4 — Utiliser response.text() pour lire des données binaires d'API avant l'encodage

Problème : response.text()interprète les octets bruts comme de l'UTF-8 et remplace les séquences d'octets non reconnues par le caractère de remplacement U+FFFD. Tout contenu binaire — images, PDFs, audio — est silencieusement corrompu avant d'atteindre btoa(). Correction : utilisez response.arrayBuffer() pour obtenir les octets bruts.

Before · JavaScript
After · JavaScript
// ❌ response.text() corrupts binary data
const res     = await fetch('/api/exports/invoice.pdf')
const text    = await res.text()   // ❌ PDF bytes mangled as UTF-8
const encoded = btoa(text)         // ❌ Corrupted Base64
// ✅ arrayBuffer() preserves raw bytes
const res     = await fetch('/api/exports/invoice.pdf')
const buffer  = await res.arrayBuffer()
const bytes   = new Uint8Array(buffer)
const chars   = Array.from(bytes, b => String.fromCharCode(b))
const encoded = btoa(chars.join('')) // ✅ Valid Base64

Méthodes Base64 JavaScript — Comparaison rapide

MéthodeUnicodeDonnées binairesURL-safeEnvironnementsInstallation requise
btoa() / atob()❌ Latin-1❌ contournement nécessaire❌ remplacement manuelBrowser, Node 16+, Bun, DenoNon
TextEncoder + btoa()✅ UTF-8✅ via Uint8Array❌ remplacement manuelBrowser, Node 16+, DenoNon
Buffer.from().toString()✅ utf8✅ natif✅ base64url (Node 18+)Node.js, BunNon
Uint8Array.toBase64() (TC39)✅ binaire✅ natif✅ option alphabetChrome 130+, Node 22+Non
js-base64✅ toujours✅ Uint8Array✅ intégréUniverselnpm install

Choisissez btoa()uniquement quand l'entrée est garantie ASCII uniquement — condensats hexadécimaux, ID numériques, ou chaînes Latin-1 pré-validées. Pour du texte fourni par l'utilisateur dans un navigateur, utilisez TextEncoder + btoa(). Pour tout le code côté serveur Node.js, Buffer est le bon choix par défaut. Pour les bibliothèques qui doivent fonctionner dans les deux environnements sans configuration du bundler, js-base64 élimine tous les cas limites.

Foire aux questions

Pourquoi btoa() lève-t-il "InvalidCharacterError" sur ma chaîne ?
btoa() n'accepte que les caractères avec des points de code dans la plage 0–255 (Latin-1 / ISO-8859-1). Tout caractère au-dessus de U+00FF — y compris la plupart du cyrillique, de l'arabe, des idéogrammes CJK et de nombreux emojis — provoque une DOMException. La correction dépend de votre environnement : dans le navigateur, encodez d'abord en octets UTF-8 avec TextEncoder, convertissez chaque octet en caractère avec String.fromCharCode(), puis appelez btoa(). Dans Node.js, utilisez Buffer.from(text, 'utf8').toString('base64') qui gère Unicode nativement.
btoa() est-il disponible dans Node.js sans aucun import ?
Oui, depuis Node.js 16.0. btoa() et atob() sont toutes deux enregistrées comme fonctions globales — aucun import requis. Elles se comportent de manière identique à leurs équivalents navigateur, y compris la restriction Latin-1. Pour le code serveur Node.js, Buffer.from() reste préférable à btoa() car il gère UTF-8 nativement, supporte les données binaires sans contournements, et dispose de l'option d'encodage 'base64url' ajoutée dans Node.js 18.
Quelle est la différence entre le Base64 standard et le Base64 URL-safe ?
Le Base64 standard (RFC 4648 §4) utilise + pour la valeur 62, / pour la valeur 63 et = pour le rembourrage. Ces caractères ont une signification spéciale dans les URL : + est interprété comme un espace dans les query strings, et / est un séparateur de chemin. Le Base64 URL-safe (RFC 4648 §5) substitue - à + et _ à /, et omet généralement le rembourrage = entièrement. Les JWT utilisent le Base64 URL-safe pour les trois segments. Dans Node.js 18+, Buffer.from(text).toString('base64url') produit directement le format URL-safe.
Comment encoder une image en Base64 pour une URI de données CSS en JavaScript ?
Dans un navigateur : utilisez file.arrayBuffer() pour lire le binaire, convertissez en Uint8Array, puis appelez btoa(Array.from(bytes, b => String.fromCharCode(b)).join('')). Construisez l'URI de données comme 'data:' + file.type + ';base64,' + encoded. Dans Node.js : const encoded = fs.readFileSync('./image.png').toString('base64') et préfixez le type MIME. Pour les fichiers SVG, vous pouvez souvent éviter complètement Base64 et utiliser une URI de données encodée en URL à la place, ce qui est plus lisible et légèrement plus petit.
Puis-je encoder et décoder en Base64 sans bibliothèque npm dans le navigateur ?
Oui. Pour les entrées ASCII uniquement, btoa() et atob() fonctionnent directement. Pour Unicode, la paire TextEncoder / TextDecoder vous donne l'ensemble d'outils complet — les deux sont intégrés dans tous les navigateurs modernes et Node.js 16+. Le seul cas où une bibliothèque apporte une vraie valeur est la cohérence inter-environnements : si vous écrivez un utilitaire qui doit fonctionner de manière identique dans le navigateur et Node.js sans configuration du bundler, js-base64 supprime la logique de détection d'environnement.
Comment décoder du contenu Base64 de l'API GitHub ?
L'API Contents de GitHub retourne le contenu du fichier en Base64 avec des sauts de ligne intégrés (l'API coupe la sortie à 60 caractères). Supprimez-les avant de décoder : const clean = data.content.replace(/\n/g, ''); const text = atob(clean);. Dans Node.js : const text = Buffer.from(data.content.replace(/\n/g, ''), 'base64').toString('utf8');. GitHub utilise toujours le Base64 standard (pas URL-safe), donc aucune substitution + → - ou / → _ n'est nécessaire.

Outils connexes

Pour un encodage ou décodage en un clic sans écrire de code, collez votre chaîne ou vos données binaires directement dans l' encodeur Base64 — il gère les modes standard et URL-safe instantanément dans votre navigateur.

Aussi disponible en :PythonJava
AC
Alex ChenFront-end & Node.js Developer

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.

SL
Sophie LaurentRéviseur technique

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.