A virtual teacher who reveals to you the great secrets of Base64

JavaScript Base64 Polyfill

Old browsers (more exactly, lower than Chrome 4, Edge 12, Firefox 2, Internet Explorer 10, and Safari 3.1) do not support btoa and atob functions. If you want to support these browsers, you must implement the Base64 encoding and decoding algorithms yourself (that is, polyfilling it).

To help you, I developed the following Base64 polyfill, which adds Base64 support even for Internet Explorer 5. To use it, just include it in your project (for example, by prepending it to your current JavaScript code or by including it via <script src="base64.js"></script>). If you included it correctly, you can use btoa and atob functions, as they are supported by the browser.

(function () {
  // Do not implement polyfill if browser already support Base64 algorithms
  if (typeof btoa === 'function') {
    return false;
  }

  // A helper that returns Base64 characters and their indices.
  var chars = {
    ascii: function () {
      return 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    },
    indices: function () {
      if (!this.cache) {
        this.cache = {};
        var ascii = chars.ascii();

        for (var c = 0; c < ascii.length; c++) {
          var chr = ascii[c];
          this.cache[chr] = c;
        }
      }
      return this.cache;
    }
  };

  /**
   * Binary to ASCII (encode data to Base64)
   * @param {String} data
   * @returns {String}
   */
  window.btoa = function (data) {
    var ascii = chars.ascii(),
      len = data.length - 1,
      i = -1,
      b64 = '';

    while (i < len) {
      var code = data.charCodeAt(++i) << 16 | data.charCodeAt(++i) << 8 | data.charCodeAt(++i);
      b64 += ascii[(code >>> 18) & 63] + ascii[(code >>> 12) & 63] + ascii[(code >>> 6) & 63] + ascii[code & 63];
    }

    var pads = data.length % 3;
    if (pads > 0) {
      b64 = b64.slice(0, pads - 3);

      while (b64.length % 4 !== 0) {
        b64 += '=';
      }
    }

    return b64;
  };

  /**
   * ASCII to binary (decode Base64 to original data)
   * @param {String} b64
   * @returns {String}
   */
  window.atob = function (b64) {
    var indices = chars.indices(),
      pos = b64.indexOf('='),
      padded = pos > -1,
      len = padded ? pos : b64.length,
      i = -1,
      data = '';

    while (i < len) {
      var code = indices[b64[++i]] << 18 | indices[b64[++i]] << 12 | indices[b64[++i]] << 6 | indices[b64[++i]];
      if (code !== 0) {
        data += String.fromCharCode((code >>> 16) & 255, (code >>> 8) & 255, code & 255);
      }
    }

    if (padded) {
      data = data.slice(0, pos - b64.length);
    }

    return data;
  };
})();

Please note, that as well as built-in btoa and atob functions, this polyfill doesn’t support Unicode strings because it should not return unexpected results that differ from built-in functions. For more details please read Implementing Unicode support for btoa() and atob().

Add new comment

If you have any questions, remarks, need help, or just like this page, please feel free to let me know by leaving a comment using the form bellow.
I will be happy to read every comment and, if necessary, I will do my best to respond as quickly as possible. Of course, spammers are welcome only as readers.

Loading...