Araçlar

Görsel Video Ses Metin Vektör Geliştirici Genel

⚡ Bugün kalan 20 ücretsiz kredi

Ücretsiz kaydol

JavaScript'te Metni Base64'e Dönüştürme (ve Çözümleme)

Çalışan tek satırlık kod, hata veren ve neden verdiği; UTF-8 güvenli dönüşüm, 2025 yerel yöntemleri ve Node.js farkları.

Katmanlı mavi belge şekillerinin, çözünerek bir dizi kodlanmış mavi küp haline geldiği yumuşak 3D illüstrasyon…

JavaScript'te bir dizeyi base64'e kodlamak için btoa('Hello, world!') çağrısı yapın; bu 'SGVsbG8sIHdvcmxkIQ==' döndürür. Ancak bu tek satırlık kod yalnızca ASCII ve Latin-1 metinler için çalışır: Bir emoji, vurgu işareti veya Çince karakter geçirdiğiniz anda InvalidCharacterError hatası verir. Bu rehber, bunun neden olduğunu ve sorunu çözen UTF-8 güvenli dönüşümü, 2025'teki yeni yerel yöntemler de dahil olmak üzere gösterir.

Tek satırda Base64: btoa() ve atob()

En hızlı çözüm: btoa('Hello, world!') ile kodlayın, atob('SGVsbG8sIHdvcmxkIQ==') ile çözün. İkisi de doğrulandı: btoa('a') 'YQ==' döndürür ve atob('SA==') 'S' döndürür.

btoa() aslında ne yapar? Dizenizi "ikili dize" (binary string) olarak ele alır; yani her karakterin ikili verinin tam olarak bir baytını temsil ettiği bir dize oluşturur ve bu baytları Base64'e kodlar. MDN'deki kullanım durumu, metin tabanlı kanallar üzerinden taşımak istediğiniz ASCII kontrol karakterleri (0–31) gibi aktarım sorunlarına neden olan verilerdir.

Metniniz ASCII ise bu tek satırlık kod yeterlidir: Her karakterin kod noktası 256'nın altında olmalı ve MDN'e göre bayt-kod noktası eşleşmesi güvenilir şekilde yalnızca 0x7F'e kadar geçerlidir. 0x80–0xFF aralığı teknik olarak çalışsa da, bu durum ortamlar arasında taşınabilir olmayan Latin-1 kodlama davranışına dayanır. İyi bir kural şudur: ASCII dışı her şey için aşağıdaki UTF-8 yolunu izleyin.

Neden btoa() emoji, vurgular ve CJK metinlerde InvalidCharacterError verir?

Base64 bir ikili kodlamadır, metin kodlaması değildir. MDN sözlüğü, rastgele metin veya HTML'i btoa()'e aktarma alışkanlığının yaygın bir yanlış anlama olduğunu belirtir: btoa/atob türü belirlenmiş dizilerden (typed arrays) önce geldiği için baytları temsil etmek üzere dizeleri kullanır. Sorun, dizenizin karakter başına bir bayt karşılığı gelmediği zaman başlar.

JavaScript dizeleri UTF-16'dır; bu nedenle bir kod birimi her zaman iki bayttır ve BMP dışındaki karakterler (emoji gibi) bir sürrogat çifti olarak dört bayt kaplar; UTF-8 ise kod noktası başına bir ila dört bayt kullanır. btoa() ve atob() yalnızca tek baytlı (Latin-1 aralığındaki) karakterlerle çalışır. Daha geniş bir şeyi kodlamaya çalıştığınızda şu hatayı alırsınız:

DOMException: Failed to execute 'btoa' on 'Window':
The string to be encoded contains characters outside of the Latin1 range

Kırılma durumu kolayca yeniden üretilebilir: btoa('✓') hata verir, btoa('a Ā 𐀀 文 🦄') de öyle. Emoji, Latin-1 dışı vurgulu harfler ve CJK karakterlerinin hepsi 0xFF'nin üzerindedir, bu nedenle hiçbirisi karakter başına bir bayt varsayımına uymaz. '✓' U+2713'tür, 0xFF'nin çok üzerindedir, bu nedenle btoa() verinizi sessizce bozmaktansa reddeder. Bu reddetme, API'nin en iyi özelliği olabilir: haftalar sonra keşfedeceğiniz mojibake (bozuk metin) üretmek yerine gürültülü bir şekilde başarısız olur.

Bunu düzeltmeden önce bilinmesi gereken bir şey daha: Base64, ham baytlara kıyasla veriyi yaklaşık %33 oranında büyütür. Kısa dizeler, belirteçler ve veri URI'ları için bu sorun değildir, ancak büyük yükleri Base64'e kodlamamak için gerçek bir neden vardır: İhtiyacınız olan sınırda kodlayın, her yerde değil.

Soldan akan ve iki yola ayrılan yumuşak 3D mavi kurdele: bir dal düzenli kümelenmiş gruplar oluşturur…
Bir veri akışı, iki bayt ayak izi: Çok baytlı kümeler versus tek baytlar.

Yalnız sürrogat uç durumu (ve String.isWellFormed())

Çoğu makale bunu atlar ama gerçekten can acıtır: Yalnız bir sürrogat içeren (genellikle dilimleme hatasından kaynaklanan bir emoji çiftinin yarısı) bir UTF-16 dizesi "bozuktur" (malformed). web.dev rehberi'ne göre, TextDecoder öntanımlı olarak U+FFFD'yi sessizce yerleştirir. Kodlamadan önce String.prototype.isWellFormed() ile iyi biçimli olup olmadığını kontrol edin veya yalnız sürrogatlar için encodeURIComponent()'ün fırlattığı URIError hatasını yakalayın; ardından ne yapacağınıza açıkça karar verin: Veriyi reddedin, değiştirmeyi bilerek etkinleştirin ya da sonraki analiz için hata fırlatın.

Doğru yol: TextEncoder → UTF-8 baytları → Base64

Doğru düzeltme, dizenizi önce TextEncoder ile UTF-8 baytlarına dönüştürüp dizeyi değil baytları Base64'e kodlamaktır. new TextEncoder().encode(str), herhangi bir JavaScript dizesini UTF-8 baytlarından oluşan bir Uint8Array'e dönüştürür (TextEncoder yalnızca UTF-8'i destekler). Geri dönüşte new TextDecoder() öntanımlı olarak UTF-8 kullanır ve dönüşümü tam olarak tersine çevirir. Burada atob()'ün size ne verdiğine dikkat edin: Bir ikili dize, karakter başına bir bayt; UTF-8 metin değil. Bu nedenle decode tarafında baytları tekrar okunabilir metne çevirmek için TextDecoder gerekir.

bytesToBase64() ve base64ToBytes() yardımcı fonksiyonları (kopyala-yapıştır kod)

İşte MDN'in referans dönüşümü; bu kod, TextEncoder'i destekleyen tüm tarayıcılarda çalışır (IE hariç):

function bytesToBase64(bytes) {
  const binString = Array.from(bytes, (b) => String.fromCodePoint(b)).join('');
  return btoa(binString);
}

function base64ToBytes(base64) {
  const binString = atob(base64);
  return Uint8Array.from(binString, (m) => m.codePointAt(0));
}

Tam bir dönüşümle doğrulayın

Bir dizeyi kodlamak bir satıra iner:

const encoded = bytesToBase64(new TextEncoder().encode('a Ā 𐀀 文 🦄'));
// 'YSDEgCDwkICAIOaWhyDwn6aE'

Çözümleme bunu tersine çevirir:

const decoded = new TextDecoder().decode(base64ToBytes(encoded));
// 'a Ā 𐀀 文 🦄'

web.dev'in doğrulanmış dönüşümü aynı deseni onaylar: 'hello⛳❤️🧀' 'aGVsbG/im7PinaTvuI/wn6eA''ye kodlar ve emoji dahil olmak üzere tam olarak geri çözer.

unescape(encodeURIComponent()) hilesini atlayın

btoa(unescape(encodeURIComponent(str))) kodunu her yerde kopyalanmış halde bulacaksınız. Çalışır, ancak unescape() Ek B mirasıdır ve ECMAScript 3'ten beri kullanımdan kaldırılmıştır. Yeni kod bunun yerine TextEncoder kullanmalıdır: Açıktır, standarttır ve kullanımdan kaldırılmış bir global'e dayanmaz.

2025 yolu: Uint8Array.toBase64() ve Uint8Array.fromBase64()

Eylül 2025'ten itibaren JavaScript'te Uint8Array üzerinde yerel Base64 yöntemleri mevcuttur; bu nedenle yukarıdaki bayt-dizisi yardımcı fonksiyonları artık tek seçenek değildir. TC39'un Base64 önerisi 4. aşamaya ulaştı ve dilin bir parçasıdır; TC39'un gerekçesi, base64'ün bir metin kodlaması olmamasıdır, bu nedenle TextEncoder/TextDecoder kavramsal olarak bunun için yanlış araçlardır.

MDN'ye göre bu yöntemler, güncel tarayıcılarda "Yeni kullanıma açılan" kategoriye girer. Göndermeden önce hedef çalışma ortamlarınızı kontrol edin; eski tarayıcıları veya eski Node sürümlerini destekliyorsanız TextEncoder + btoa yedekleme mekanizmasını koruyun. MDN, zaten bir Uint8Array varsa btoa()/atob() yerine bu yöntemleri tercih eder çünkü ham bayt dizisi oluşturulmasına gerek kalmaz.

Kodlama: bytes.toBase64()

const b64 = new TextEncoder().encode('Hello, world!').toBase64();
// 'SGVsbG8sIHdvcmxkIQ=='

Tek bir UTF-8 dönüşümü, tek bir yöntem çağrısı ve iş biter.

Çözümleme: Uint8Array.fromBase64()

const text = new TextDecoder().decode(Uint8Array.fromBase64(b64));
// 'Hello, world!'

MDN, çözümlenen verinin ASCII metin olarak amaçlanmadığı sürece fromBase64()'in atob()'e tercih edilmesi gerektiğini belirtir; çünkü gerçek bir bayt dizisi döndürür. Yalnızca base64 alfabesini (A–Z, a–z, 0–9, artı +/ veya -_), isteğe bağlı = dolgu karakterini kabul eder ve ASCII boşluklarını yok sayar; alfabenin dışında kalan karakterlerde SyntaxError hatası verir.

Seçenekler: alphabet, omitPadding, lastChunkHandling

Spesifikasyonun seçenek paketi size hassas kontrol sağlar:

Seçenek Değerler Ne işe yarar
alphabet 'base64' (varsayılan), 'base64url' +// vs -/_
omitPadding boolean Son = karakterlerini atar: new Uint8Array([72]).toBase64() → 'SA==', omitPadding ile birlikte → 'SA'
lastChunkHandling 'loose' (varsayılan), 'strict', 'stop-before-partial' Son parça için çözümleyici toleransı

'loose' eksik dolgu ve boşluğu tolere eder. 'strict', taşan bitlerin sıfırlandığı tam 4 karakterlik parçaları gerektirir; bu da güvenilir olmayan girdileri doğrularken istediğiniz davranıştır. 'stop-before-partial' akışlı kullanım içindir. Varsayılan gevşek mod, sıkı modun reddettiği sıfırdan farklı taşan bitleri de tolere eder.

Base64 vs base64url: Hangi alfabe gerekiyor?

Standart base64, + ve /'i kullanır ve = dolgusu ile birlikte, yol segmenti veya sorgu dizesi içermeyen data: URL'leri için uygundur. base64url (RFC 4648 §5) ise - ve _'yı kullanır ve genellikle dolguyu atar; çıktı bir URL içinde iletilecekse base64url zorunludur. Örneğin JWT'ler üç segmentinin tamamında base64url kullanır.

Ne zaman base64url kullanılmalı

Kodlanmış dize bir URL yolunun veya sorgu parametresinin parçası olduğunda base64url kullanın; + ve / burada kaçış karakteri gerektirir ve = dolgusu sorgu dizelerini karmaşıklaştırır. Veri URI'ları, JSON yüklerine bayt gömme veya URL dışı herhangi bir durum için standart base64 kullanın.

base64url nasıl üretilir

Ortama bağlı olarak üç yol vardır:

  • Modern tarayıcılar: bytes.toBase64({ alphabet: 'base64url' })
  • Node 16+: Buffer.from(str).toString('base64url')
  • Son işlem: Standart çıktıyı alın, + → - ve / → _ değişimlerini yapın, ardından = dolgusunu kaldırın.

Bilmeye değer ince bir nokta: RFC 4648, kodlayıcılardan son parçada veri dışı taşan bitleri sıfırlamasını ister; sıkı çözümleyiciler bunlar sıfırlanmadığında hata verebilir. MDN'un sözlüğü, kirli dolgu bitlerine sahip olsa da 'VQ==' ile aynı bayt olan 'VR==' örneğini verir. İyi davranan bir kodlayıcıyla base64 üretirseniz bu sorun hiç çıkmaz; kendiniz yazarsanız çıkabilir.

Dosya veya resmi Base64'e dönüştürme (veri URI'ları)

Dosyalar için tarayıcı yolu, tam bir veri URI'sı üreten FileReader ile readAsDataURL() kullanmaktır; ardından ön eki çıkararak ham base64'e ulaşırsınız. Zaten bir canvas üzerinde render edilmiş görüntüler için toDataURL('image/png') tek bir çağrıyla bu işi halleder.

FileReader.readAsDataURL() → veri URI'sı → ham base64

function fileToDataURL(file) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.readAsDataURL(file);
  });
}

const dataUrl = await fileToDataURL(fileInput.files[0]);
const rawBase64 = dataUrl.replace(/^data:\w+\/\w+;base64,/, '');

Görüntüler için canvas.toDataURL()

Bir görüntüyü canvas üzerine çizdiyseniz (boyutlandırma, kırpma vb.), FileReader'ı tamamen atlayın:

const dataUrl = canvas.toDataURL('image/png');

Sadece ham base64 stringine ihtiyacınız varsa aynı ön ek çıkarma işlemi geçerlidir.

Veri URI'sından baytlara geri dönüş

Ters yön bir fetch ve bir array buffer işlemidir. MDN'un örneğinde, new Uint8Array([0,1,2])'den oluşturulan bir veri URI'sı 'data:application/octet-stream;base64,AAEC' şeklindedir ve baytları şu şekilde geri kazanırsınız:

const res = await fetch(dataUrl);
const bytes = new Uint8Array(await res.arrayBuffer());
// [0, 1, 2]

Bu makalenin var olma amacını özetleyen hatırlatma: Veri URI'ları oluşturmak için rastgele metin veya HTML üzerinde btoa() çağırmayın. Bu, bayttan bayta çalışan bir kodlayıcıdır ve Latin-1 dışı girdilerde hata verecektir.

Node.js: Buffer.from(str, 'base64') — ve bu yöntemin tek tehlikeli farkı

Node.js, TextEncoder işlemlerini tamamen atlayan kendi yöntemlerine sahiptir: Buffer.from('Hello, world! 🌍').toString('base64') başından beri baytlar üzerinde çalıştığı için Unicode'u otomatik olarak yönetir. Çözümleme için Buffer.from(encoded, 'base64').toString('utf8') kullanın.

Başka faydalı biçimler: Buffer.from(str).toString('base64url') (Node 16 ve üzeri) ve tüm dosyalar için fs.readFileSync('image.png').toString('base64').

const encoded = Buffer.from('Hello, world! 🌍').toString('base64');
const decoded = Buffer.from(encoded, 'base64').toString('utf8');

Node base64'ünüzü doğrulamaz (sessiz hatalar)

İnsanları şaşırtan kısım şu: Node.js'in base64 çözücüsü girdiyi doğrulamaz. Buffer.from('!!!!', 'base64').toString() hata vermeden '' döndürür ve Buffer.from('aGVsbG8!!!', 'base64') geçersiz (çöp) karakterleri sessizce atarak 'hello' sonucunu verir. Buna karşılık, atob('aGVsbG8!!!') bir InvalidCharacterError hatası fırlatır. Base64 verisi kullanıcılar, bir API veya üçüncü taraflardan geliyorsa, Node.js'te çözümden önce doğrulama yapın veya çalışma zamanları destekliyorsa Uint8Array.fromBase64() ile lastChunkHandling: 'strict' kullanın.

btoa/atob kullanımdan kaldırıldı mı? Tarayıcılar vs Node

Bu durum gerçekten çelişkili görünüyor, bu yüzden dürüst bir çözüm sunalım. Tarayıcılar için MDN, btoa() ve atob()'yi işaretler Temel özellik olarak Temmuz 2015'ten itibaren geniş ölçüde mevcut; artık kullanımdan kaldırılmadı. Node.js ortamında ise tip tanımları bu fonksiyonları @deprecated "yeni kodlarda asla kullanılmamalı" yorumuyla birlikte işaretler ve Buffer.from(str, 'base64') kullanımını önerir.

İyi bir kural: Bu kaldırılmış bir API değil, miras kalan (legacy) bir API'dir. Tarayıcı kodunda sorun yok; ancak Node'a özel kodlarda Buffer tercih edilmelidir. Topluluk görüşüne dayanarak (bir standart garantisi olmasa da), tarayıcılar, Deno ve Node ortamlarında bağımlılık olmadan aynı kodun çalışmasını istiyorsanız, pratik olarak çapraz ortam seçeneği btoa/atob olacaktır.

Aslında ne kullanılmalı

Bu makaleden yalnızca bir öneri alacaksanız, aşağıdaki üç tek satırlık kodu tercih edin. Düz ASCII metinler ve eski kod tabanları için btoa/atob'i kullanın; toBase64() tüm kitleyi kapsayana kadar tarayıcı yedek çözümü olarak bytesToBase64 yardımcı fonksiyonunu tercih edin.

// Modern browsers (2025+)
const enc = new TextEncoder().encode(str).toBase64();
const dec = new TextDecoder().decode(Uint8Array.fromBase64(b64));

// Browser fallback (MDN helper)
const encFallback = bytesToBase64(new TextEncoder().encode(str));

// Node (validate input first if it isn't yours)
const encNode = Buffer.from(str).toString('base64');

Göndermeden önce, tarayıcı aracında hızlı bir dönüşüm testiyle çıktınızı doğrulayın. 'Hello, world!' değerini Tool Cloud'un ücretsiz Base64 Kodlayıcı / Çözücü sayfasına yapıştırın, 'SGVsbG8sIHdvcmxkIQ==' sonucunu aldığınızdan emin olun ve ardından kodu çözerek orijinal metinle aynı olduğunu kontrol edin. Ayrıca ayrı Metinden Base64'e dönüştürücü ve Base64'ten Metne dönüştürücü araçları da mevcuttur; yüklenen dosyalar otomatik olarak silinir ve hiçbir şey kurmanıza gerek yoktur.

Sıkça sorulan sorular

Neden btoa() emoji üzerinde başarısız olurken İngilizce metinde çalışır?

btoa(), her karakteri tek bir bayt olarak ele alır ve her kod noktasının 256'nın altında olmasını gerektirir (güvenilir şekilde yalnızca 0x7F'e kadar). Emoji, vurgulu karakterler ve Çince/Korece/Japonca (CJK) metin birden fazla bayt gerektirdiğinden DOMException: InvalidCharacterError tetiklenir. Önce metni UTF-8 baytlarına dönüştürün, ardından baytları kodlayın.

btoa() kullanımdan kaldırıldı mı?

Hayır, tarayıcılarda kullanımdan kaldırılmadı — MDN, btoa() ve atob()'yu Temmuz 2015'ten bu yana Baseline widely available (geniş çapta kullanılabilir) olarak işaretler. Ancak Node'un tür tanımları, bunları Node'a özgü kodlarda Buffer.from(str, 'base64') lehine kullanımdan kaldırılmış olarak işaretler. Bunlar kaldırılmış değil, eski (legacy) bir API'dir.

Unicode metni (vurgular, Çince, emoji) nasıl Base64'e kodlarım?

UTF-8 baytlarını almak için new TextEncoder().encode(str) kullanın, ardından baytları kodlayın (btoa() aracılığıyla bir bayt dizisi yardımcı fonksiyonu veya modern tarayıcılarda Uint8Array.toBase64()). Baytları geri almak için çözmeye Uint8Array.fromBase64() veya atob() ile başlayın, ardından new TextDecoder().decode(bytes) ile metne çevirin.

base64 ile base64url arasındaki fark nedir?

base64url (RFC 4648 §5), '+' ve '/' yerine '-' ve '_' kullanır ve genellikle '=' dolgu karakterini atlar. Çıktı URL'lere veya JWT'lere gidecekse base64url kullanın; standart base64, yol parçası veya sorgu dizesi içermeyen data: URL'leri için uygundur.

Neden Node.js geçersiz base64 için hata vermez?

Node.js'in Buffer.from(str, 'base64') yöntemi girişi doğrulamaz: geçersiz karakterleri sessizce yok sayar, bu nedenle Buffer.from('aGVsbG8!!!', 'base64').toString() 'hello' döndürür ve hata vermez. Tarayıcılarda ise atob() aynı girişte InvalidCharacterError fırlatır. Node.js'te çözümlerken güvenilmeyen base64'ü önceden doğrulayın.