The WindowOrWorkerGlobalScope.btoa() method creates a base-64 encoded ASCII string from a binary string (i.e., a String object in which each character in the string is treated as a byte of binary data).

Note: Since this function treats each character as a byte of binary data, regardless of the number of bytes which actually make up the character, an InvalidCharacterError exception is thrown if any character's code point is outside the range 0x00 to 0xFF. See Unicode strings for an example demonstrating how to encode strings with characters outside the 0x00 to 0xFF range


var encodedData = scope.btoa(stringToEncode);


The binary string to encode.

Return value

An ASCII string containing the Base64 representation of stringToEncode.



var encodedData = window.btoa('Hello, world'); // encode a string
var decodedData = window.atob(encodedData); // decode the string


You can use this method to encode data which may otherwise cause communication problems, transmit it, then use the atob() method to decode the data again. For example, you can encode control characters such as ASCII values 0 through 31.

btoa() is also available to XPCOM components implemented in JavaScript, even though Window is not the global object in components.

Unicode strings

In most browsers, calling btoa() on a Unicode string will cause an InvalidCharacterError exception.

One option is to escape any extended characters so that the string you actually encode is an ASCII representation of the original. Consider this example, noted by Johan Sundström:

// ucs-2 string to base64 encoded ascii
function utoa(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
// base64 encoded ascii to ucs-2 string
function atou(str) {
    return decodeURIComponent(escape(window.atob(str)));
// Usage:
utoa('✓ à la mode'); // 4pyTIMOgIGxhIG1vZGU=
atou('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"

utoa('I \u2661 Unicode!'); // SSDimaEgVW5pY29kZSE=
atou('SSDimaEgVW5pY29kZSE='); // "I ♡ Unicode!"

A better, more faithful and less expensive solution is to use typed arrays to do the conversion.


Specification Status Comment
HTML Living Standard
The definition of 'WindowOrWorkerGlobalScope.btoa()' in that specification.
Living Standard Method moved to the WindowOrWorkerGlobalScope mixin in the latest spec.
HTML 5.1
The definition of 'WindowBase64.btoa()' in that specification.
Recommendation Snapshot of HTML Living Standard. No change.
The definition of 'WindowBase64.btoa()' in that specification.
Recommendation Snapshot of HTML Living Standard. Creation of WindowBase64 (properties where on the target before it).


// Polyfill from
(function() {
    // base64 character set, plus padding character (=)
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

        // Regular expression to check formal correctness of base64 encoded strings
        b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;

    window.btoa = window.btoa || function(string) {
        string = String(string);
        var bitmap, a, b, c,
            result = "",
            i = 0,
            rest = string.length % 3; // To determine the final padding

        for (; i < string.length;) {
            if ((a = string.charCodeAt(i++)) > 255 ||
                (b = string.charCodeAt(i++)) > 255 ||
                (c = string.charCodeAt(i++)) > 255)
                throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");

            bitmap = (a << 16) | (b << 8) | c;
            result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) +
                b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);

        // If there's need of padding, replace the last 'A's with equal signs
        return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;

    window.atob = window.atob || function(string) {
        // atob can work with strings with whitespaces, even inside the encoded part,
        // but only \t, \n, \f, \r and ' ', which can be stripped.
        string = String(string).replace(/[\t\n\f\r ]+/g, "");
        if (!b64re.test(string))
            throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");

        // Adding the padding if missing, for semplicity
        string += "==".slice(2 - (string.length & 3));
        var bitmap, result = "",
            r1, r2, i = 0;
        for (; i < string.length;) {
            bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 |
                (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));

            result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255) :
                r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255) :
                String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
        return result;

Browser compatibility

Update compatibility data on GitHub
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung Internet
btoaChrome Full support YesEdge Full support YesFirefox Full support 1
Full support 1
Full support 52
Notes btoa() now defined on WindowOrWorkerGlobalScope mixin.
IE Full support 10Opera Full support YesSafari Full support YesWebView Android Full support YesChrome Android Full support YesFirefox Android Full support 4
Full support 4
Full support 52
Notes atob() now defined on WindowOrWorkerGlobalScope mixin.
Opera Android ? Safari iOS Full support YesSamsung Internet Android Full support Yes


Full support  
Full support
Compatibility unknown  
Compatibility unknown
See implementation notes.
See implementation notes.

See also