# Base64 encoding and decoding in JavaScript

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Feb 19, 2020, updated Oct 9, 2022. Topics: JavaScript.
Canonical URL: https://attacomsian.com/blog/javascript-base64-encode-decode

> A complete guide to learning how to Base64 encode and decode strings in JavaScript using built-in functions.

Base64 is a widely used binary-to-text encoding scheme that transforms binary data into an equivalent ASCII character set by translating it into a radix-64 representation. It is commonly used for encoding and transporting data over media incompatible with transferring binary data. Base64 makes sure that the binary data doesn't change during transportation.

It is important to remember that Base64 is **not** an encryption or compression scheme. It only transforms the binary data into an ASCII character set that is extremely useful for transferring obfuscated strings over the network. 

For instance, a simple example is sending an image or any other binary file to an email server that typically expects textual data. You first encode the binary file into a textual format, preferably ASCII.

In this article, you'll **learn how to encode and decode Base64 strings** in JavaScript. There are two built-in functions in JavaScript for encoding and decoding raw binary data into Base64 strings.

## Base64 encoding using `btoa()`

The `btoa()` function (stands for binary-to-ASCII) is used to create a Base64 encoded ASCII string from the binary data. It accepts the binary string as an argument and returns a Base64 encoded ASCII string.

The following example shows how you can use `btoa()` to Base64 encode a string in JavaScript:

```javascript
const str = 'JavaScript is fun!!'

// encode the string
const encodedStr = btoa(str)

// print encoded string
console.log(encodedStr)

// output: SmF2YVNjcmlwdCBpcyBmdW4hIQ==
```

By default, the `btoa()` method works fine for binary data consisting of 8-bit bytes. If your input data contains any character with more than 8 bits, for instance, a Unicode character, the `btoa()` function will throw an exception. 

Here is an example:

```javascript
const str = 'JavaScript is fun ?'

// encode the string
const encodedStr = btoa(str)

// print encoded string
console.log(encodedStr)
```

If you execute the above code, you should see the following error output:

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

To encode Unicode characters, you first need to escape the input string to an array of 8-bit bytes (like UTF-8) and then use `btoa()` to encode it to Base64, as shown in the following example:

```javascript
function encodeUnicode(str) {
  // First we use encodeURIComponent to get percent-encoded UTF-8,
  // then we convert the percent encodings into raw bytes which
  // can be fed into btoa.
  return btoa(
    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function toSolidBytes(match, p1) {
      return String.fromCharCode('0x' + p1)
    })
  )
}

encodeUnicode('JavaScript is fun ?') // SmF2YVNjcmlwdCBpcyBmdW4g8J+OiQ==
encodeUnicode('??') // 8J+UpfCfkqE=
```

## Base64 decoding using `atob()`

The `atob()` function (stands for ASCII-to-binary) decodes a string of data encoded using Base64 encoding back to normal text in JavaScript. Here is an example that shows how you can use `atob()` to decode a Base64 encoding string:

```javascript
const encodedStr = 'SmF2YVNjcmlwdCBpcyBmdW4hIQ=='

// decode the string
const str = atob(encodedStr)

// print decoded string
console.log(str)

// output: JavaScript is fun!!
```

The `atob()` function works perfectly if the Base64 encoded input string only has 8-bit bytes. However, it fails to properly decode if the encoded input string includes 16-bit Unicode characters, as shown in the following example:

```javascript
// Encode String: 'JavaScript is fun ?'
const encodedStr = 'SmF2YVNjcmlwdCBpcyBmdW4g8J+OiQ=='

// decode the string
const str = atob(encodedStr)

// print decoded string
console.log(str)

// output: JavaScript is fun ð
```

As you can see above, the Unicode character is not properly decoded. To handle Unicode DOM strings, you have to convert the Base64 encoded bytes to percent-encoded strings and then decode the percent-encoded string using `decodeURIComponent()` like the following:

```java
function decodeUnicode(str) {
  // Going backward: from byte-stream to percent-encoding, to original string.
  return decodeURIComponent(
    atob(str)
      .split('')
      .map(function (c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
      })
      .join('')
  )
}

decodeUnicode('SmF2YVNjcmlwdCBpcyBmdW4g8J+OiQ==') // JavaScript is fun ?
decodeUnicode('8J+UpfCfkqE=') // ??
```

## Conclusion

That's all folks for Base64 encoding and decoding in JavaScript. Base64 is a widely used encoding scheme for securely transmitting binary data as a stream of ASCII characters over the network.

Of course, you can still choose to send binary data over the network. But it can be risky sometimes, as not all applications and network communication devices can handle raw binary data. On the other hand, the ASCII character set is quite simple to consume for most applications.

For more information on Base64 encoding and decoding, read [this MDN guide](https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding).
