Base64 Decode у JavaScript: atob() та Buffer
Використовуйте безкоштовний Base64 Decode Online прямо в браузері — без встановлення.
Спробувати Base64 Decode Online онлайн →Коли я налагоджую проблему з автентифікацією у продакшені, перше, за що я беруся, — це Base64 decoder: JWT-пейлоади, підписи вебхуків та закодовані конфігураційні значення ховаються всередині Base64-рядків. JavaScript надає два вбудованих підходи до base64-декодування: atob() (браузер + Node.js 16+) та Buffer.from(encoded, 'base64').toString() (Node.js) — і вони поводяться дуже по-різному, коли вихідні дані містять символи Unicode. Для швидкого одноразового декодування без написання коду Base64 Decoder від ToolDeck впорається миттєво прямо у браузері. Цей посібник охоплює обидва середовища — Node.js 16+ та сучасні браузери (Chrome 80+, Firefox 75+, Safari 14+) — із готовими до продакшену прикладами: відновлення UTF-8, URL-безпечні варіанти, декодування JWT, файлів, відповідей API, потоків Node.js і чотири помилки, які стабільно призводять до спотвореного виводу в реальних проектах.
- ✓atob(encoded) вбудований у браузер і доступний у Node.js 16+ глобально, але повертає бінарний рядок — використовуйте TextDecoder для відновлення UTF-8 тексту з будь-якого вмісту вище ASCII.
- ✓Buffer.from(encoded, "base64").toString("utf8") — ідіоматичний підхід у Node.js, який обробляє UTF-8 автоматично без додаткових кроків.
- ✓URL-безпечний Base64 (що використовується в JWT) замінює + на -, / на _ та прибирає паддинг =. Відновіть їх перед викликом atob() або використовуйте Buffer.from(encoded, "base64url").toString() у Node.js 18+.
- ✓Видаляйте пробіли та переноси рядків перед декодуванням — GitHub Contents API і багато MIME-енкодерів переносять вивід Base64 кожні 60–76 символів.
- ✓Uint8Array.prototype.fromBase64() (TC39 Stage 3) вже доступний у Node.js 22+ і Chrome 130+ та зрештою уніфікує обидва середовища.
Що таке декодування Base64?
Декодування Base64 — це зворотна операція до кодування: вона перетворює 64-символьне ASCII-представлення назад у вихідні бінарні дані або текст. Кожні 4 символи Base64 відповідають рівно 3 байтам. Символи = наприкінці закодованого рядка повідомляють декодеру, скільки додаткових байт було додано для завершення останньої 3-байтової групи.
Base64 — це не шифрування: операція повністю оборотна для будь-кого, хто має закодований рядок. Його призначення — транспортна сумісність: протоколи та формати зберігання, розраховані на 7-бітний ASCII-текст, не можуть обробляти довільні бінарні байти, і Base64 усуває цей розрив. Типові сценарії декодування в JavaScript включають інспекцію JWT-пейлоадів, розпаковку Base64-закодованих JSON-конфігів зі змінних середовища, вилучення вмісту бінарних файлів із REST API та декодування data URI у браузері.
ZGVwbG95LWJvdDpzay1wcm9kLWE3ZjJjOTFlNGIzZDg=
deploy-bot:sk-prod-a7f2c91e4b3d8
atob() — вбудована функція декодування для браузерів
atob() (ASCII-to-binary) доступний у браузерах починаючи з IE10 і став глобальною функцією у Node.js 16.0 в рамках ініціативи WinterCG щодо сумісності. Він також працює нативно у Deno, Bun та Cloudflare Workers — без імпорту.
Функція повертає бінарний рядок: JavaScript-рядок, у якому кожен символ має кодову точку, рівну одному значенню сирого байта (0–255). Це важливо: якщо вихідні дані були UTF-8 текстом, що містить символи вище U+007F (літери з діакритикою, кирилиця, CJK, емодзі), повернутий рядок є сирою послідовністю байт, а не читаємим текстом. Використовуйте TextDecoder, щоб відновити його (детальніше в наступному розділі).
Мінімальний робочий приклад
// 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-a7f2c91e4b3d8Перевірка коректності відновлення даних
// 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() та btoa() є частиною WinterCG Minimum Common API — тієї ж специфікації, що регулює Fetch, URL та crypto у небраузерних середовищах виконання. Вони поводяться однаково у Node.js 16+, Bun, Deno та Cloudflare Workers.Відновлення UTF-8 тексту після декодування
Найпоширеніша пастка з atob() — нерозуміння типу значення, що повертається. Коли вихідний текст був закодований у UTF-8 перед Base64, atob() повертає Latin-1 бінарний рядок, а не читаємий текст:
// 'Алексей Иванов' 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
Правильний підхід використовує TextDecoder для інтерпретації цих сирих байт як UTF-8:
Підхід із TextDecoder — безпечний для будь-якого 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'). Він автоматично інтерпретує декодовані байти як UTF-8 і працює швидше для великих вхідних даних.Buffer.from() у Node.js — повний посібник із декодування
У Node.js Buffer є ідіоматичним API для всіх бінарних операцій, включаючи декодування Base64. Він обробляє UTF-8 нативно, повертає справжній Buffer (безпечний для бінарних даних), а починаючи з Node.js 18 підтримує скорочення 'base64url' для URL-безпечних варіантів.
Декодування конфігу зі змінної середовища
// 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) // 100Відновлення бінарного файлу з .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 bytesАсинхронне декодування з обробкою помилок
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`)Функції декодування Base64 — довідник параметрів
Короткий довідник параметрів двох основних нативних API декодування для використання під час написання та перевірки коду.
atob(encodedData)
| Параметр | Тип | Обов'язковий | Опис |
|---|---|---|---|
| encodedData | string | Так | Стандартний Base64-рядок із символами +, /, =. URL-безпечні варіанти (-, _) викидають InvalidCharacterError. Пробіли не допускаються. |
Buffer.from(input, inputEncoding) / .toString(outputEncoding)
| Параметр | Тип | За замовчуванням | Опис |
|---|---|---|---|
| input | string | Buffer | TypedArray | ArrayBuffer | обов'язковий | Base64-закодований рядок для декодування або буфер із закодованими байтами. |
| inputEncoding | BufferEncoding | "utf8" | Встановіть "base64" для стандартного Base64 (RFC 4648 §4) або "base64url" для URL-безпечного Base64 (RFC 4648 §5, Node.js 18+). |
| outputEncoding | string | "utf8" | Кодування для виводу .toString(). Використовуйте "utf8" для читаємого тексту, "binary" для Latin-1 бінарного рядка, сумісного з виводом atob(). |
| start | integer | 0 | Зміщення байта всередині декодованого Buffer, з якого починати читання. Передається у .toString() як другий аргумент. |
| end | integer | buf.length | Зміщення байта для зупинки читання (не включно). Передається у .toString() як третій аргумент. |
URL-безпечний Base64 — декодування JWT та URL-параметрів
JWT використовують URL-безпечний Base64 (RFC 4648 §5) для всіх трьох сегментів. URL-безпечний Base64 замінює + на - та / на _, а також прибирає завершальний = паддинг. Передача цього напряму в atob() без відновлення дає некоректний вивід або виключення.
Браузер — відновлення символів і паддингу перед декодуванням
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+ — нативне кодування '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_3a7f91c2Декодування Base64 з файлів та відповідей API
У продакшен-коді декодування Base64 найчастіше відбувається під час роботи із зовнішніми API, які повертають контент у закодованому вигляді. В обох сценаріях є важливі нюанси навколо пробілів і бінарного vs текстового виводу. Якщо вам просто потрібно оглянути закодовану відповідь під час налагодження, вставте її напряму в Base64 Decoder — він миттєво обробляє стандартний і URL-безпечний режими.
Декодування вмісту з GitHub Contents API
// 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}`)Декодування Base64-закодованого бінарного файлу з API (браузер)
// 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')!)Декодування Base64 через командний рядок у Node.js та Shell
Для CI/CD-скриптів, сесій налагодження або одноразових задач декодування утиліти командного рядка та однорядники Node.js швидші за повноцінний скрипт. Зверніть увагу, що ім'я прапорця відрізняється на macOS і 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 використовує -D для декодування (велика D), тоді як Linux використовує -d (мала). Це непомітно ламає CI-скрипти — використовуйте однорядник Node.js, коли цільова платформа не гарантовано є Linux.Високопродуктивна альтернатива: js-base64
Головна причина використовувати бібліотеку — крос-середовища узгодженість. Якщо ви поставляєте пакет, що працює як у браузері, так і в Node.js без налаштування бандлера, Buffer вимагає визначення середовища, а atob() вимагає обхідного шляху через TextDecoder. js-base64 (понад 100 млн завантажень npm на тиждень) прозоро обробляє обидва варіанти.
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) // trueВивід у термінал із підсвіткою синтаксису
При написанні CLI-інструментів налагодження або скриптів інспекції простий console.log важко читати для великих JSON-пейлоадів. chalk (найбільш завантажуваний npm-пакет для розфарбування терміналу) у поєднанні з декодуванням Base64 дає читаємий, легко переглядуваний вивід — корисний для інспекції JWT, налагодження відповідей API та аудиту конфігів.
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: 1717203600Декодування великих Base64-файлів за допомогою потоків Node.js
Коли Base64-закодований файл перевищує ~50 МБ, завантаження його повністю в пам'ять за допомогою readFileSync() стає проблемою. Потоки Node.js дозволяють декодувати дані частинами — але Base64 вимагає кратних 4 символам чанків (кожна 4-символьна група декодується рівно в 3 байти) для уникнення помилок паддингу на межах чанків.
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 символи (768 КБ). Для файлів до 50 МБ readFile() + Buffer.from(content.trim(), 'base64') простіше і достатньо швидко.Поширені помилки
Я бачив ці чотири помилки в JavaScript-кодових базах знову і знову — вони, як правило, залишаються непоміченими, доки не ASCII символ або перенесена відповідь API не потрапляє до шляху декодування у продакшені.
Помилка 1 — Використання atob() без TextDecoder для UTF-8 вмісту
Проблема: atob() повертає бінарний рядок, де кожен символ — це одне значення сирого байта. Багатобайтові UTF-8 послідовності (кирилиця, CJK, літери з діакритикою) відображаються як спотворені Latin-1 символи. Рішення: загорніть вивід у 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) // Алексей Иванов ✓
Помилка 2 — Передача URL-безпечного Base64 напряму в atob()
Проблема: JWT-сегменти використовують - та _ замість + та /, без паддингу. atob() може повернути неправильні дані або викинути виключення. Рішення: спочатку відновіть стандартні символи та додайте паддинг.
// ❌ 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"} ✓Помилка 3 — Не видаляти переноси рядків із перенесеного Base64
Проблема: GitHub Contents API та MIME-енкодери переносять вивід Base64 кожні 60–76 символів. atob() викидає InvalidCharacterError на символах \n. Рішення: видаліть усі пробіли перед декодуванням.
// ❌ 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) // ✓
Помилка 4 — Виклик .toString() на декодованому бінарному вмісті
Проблема: Коли вихідні дані є бінарними (зображення, PDF, аудіо), виклик .toString('utf8') замінює нерозпізнані байтові послідовності на U+FFFD, непомітно пошкоджуючи вивід. Рішення: залишайте результат як Buffer — не перетворюйте на рядок.
// ❌ .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 PDFМетоди декодування Base64 у JavaScript — швидке порівняння
| Метод | UTF-8 вивід | Бінарний вивід | URL-безпечний | Середовища | Потребує встановлення |
|---|---|---|---|---|---|
| atob() | ❌ потрібен TextDecoder | ✅ бінарний рядок | ❌ ручне відновлення | Browser, Node 16+, Bun, Deno | Ні |
| TextDecoder + atob() | ✅ UTF-8 | ✅ через Uint8Array | ❌ ручне відновлення | Browser, Node 16+, Deno | Ні |
| Buffer.from().toString() | ✅ utf8 | ✅ залишити як Buffer | ✅ base64url (Node 18+) | Node.js, Bun | Ні |
| Uint8Array.fromBase64() (TC39) | ✅ через TextDecoder | ✅ нативний | ✅ опція alphabet | Chrome 130+, Node 22+ | Ні |
| js-base64 | ✅ завжди | ✅ Uint8Array | ✅ вбудований | Універсально | npm install |
Використовуйте atob() лише коли декодований вміст гарантовано є ASCII-текстом. Для будь-якого призначеного для користувача або багатомовного тексту в браузері використовуйте TextDecoder + atob(). Для серверного коду Node.js Buffer — правильний вибір за замовчуванням: він обробляє UTF-8 автоматично та зберігає бінарні дані незайманими. Для крос-середовищних бібліотек js-base64 усуває всі граничні випадки.
Поширені запитання
Пов'язані інструменти
Для декодування в один клік без написання коду вставте ваш Base64-рядок напряму в Base64 Decoder — він обробляє стандартний і URL-безпечний режими з миттєвим виводом у браузері.
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.