Encoding and Decoding Base64 Strings in Node.js

What is Base64 Encoding?

Base64 encoding is a way to convert data (typically binary) into the ASCII character set. It is important to mention here that Base64 is not an encryption or compression technique, although it can sometimes be confused as encryption due to the way it seems to obscure data. In fact, the size of a Base64 encoded piece of information is 1.3333 times the actual size of your original data.

Base64 is the most widely used base encoding technique with Base16 and Base32 being the other two commonly used encoding schemes.

How Does Base64 Work?

Converting data to base64 is a multi-step process. Here is how it works for strings of text:

  1. Calculate the 8 bit binary version of the input text
  2. Re-group the 8 bit version of the data into multiple chunks of 6 bits
  3. Find the decimal version of each of the 6 bit binary chunk
  4. Find the Base64 symbol for each of the decimal values via a Base64 lookup table

For a better understanding of this concept, let's take a look at an example.

Suppose we have a string "Go win" and we want to convert it into a Base64 string. The first step is to convert this string into binary. The binary version of "Go win" is:

01000111  01101111  00100000  01110111  01101001  01101110

You can see here that each character is represented by 8 bits. However as we said earlier, Base64 converts the data in 8 bit binary form to chunks of 6 bits. This is because Base64 format only has 64 characters: 26 uppercase alphabet letters, 26 lowercase alphabet letters, 10 numeric characters, and the "+" and "/" symbols for the new line.

Base64 doesn't use all the ASCII special characters, but only these few. Note that some implementations of Base64 use different special characters than "+" and "/".

Coming back to the example, let us break our 8 bit data into chunks of 6 bits.

010001  110110  111100  100000  011101  110110  100101  101110

You won't always be able to divide up the data into full sets of 6 bits, in which case you'll have to deal with padding.

Now for each chunk above, we have to find its decimal value. These decimal values have been given below:

Binary  Decimal
010001  17
110110  54
111100  60
100000  32
011101  29
110110  54
100101  37
101110  46

Finally we have to look at the Base64 value for each of the decimals that we just calculated from binary data. Base64 encoding table looks like this:

Here you can see that decimal 17 corresponds to "R", and decimal 54 corresponds to "2", and so on. Using this encoding table we can see that the string "Go win" is encoded as "R28gd2lu" using Base64. You can use any online text to Base64 converter to verify this result.

Why use Base64 Encoding?

Sending information in binary format can sometimes be risky since not all applications or network systems can handle raw binary. On the other hand, the ASCII character set is widely known and very simple to handle for most systems.

For instance email servers expect textual data, so ASCII is typically used. Therefore, if you want to send images or any other binary file to an email server you first need to encode it in text-based format, preferably ASCII. This is where Base64 encoding comes extremely handy in converting binary data to the correct formats.

Encoding Base64 Strings with Node.js

The easiest way to encode Base64 strings in Node.js is via the Buffer object. In Node.js, Buffer is a global object which means that you do not need to use a require statement in order to use the Buffer object in your applications.

Internally Buffer is an immutable array of integers that is also capable of performing many different encodings/decodings. These include to/from UTF-8, UCS2, Base64 or even Hex encodings. As you write code that deals with and manipulates data, you'll likely be using the Buffer object at some point.

Take a look at the following example. Here we will encode a text string to Base64 using the Buffer object. Save the following code in a file encode-text.js.

'use strict';

let data = 'stackabuse.com';
let buff = new Buffer(data);
let base64data = buff.toString('base64');

console.log('"' + data + '" converted to Base64 is "' + base64data + '"');

In the above script we create a new buffer object and pass it our string that we want to convert to Base64. We then call the toString method on the buffer object that we just created and pass it "base64" as a parameter. The toString method with "base64" as parameter will return data in the form of Base64 string. Before you run the above code, make sure you have Node.js installed. This updated guide to installing Node.js will walk you through all the steps. You shall see the following output after running the code.

$ node encode-text.js
"stackabuse.com" converted to Base64 is "c3RhY2thYnVzZS5jb20="
Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

In the output we can see the Base64 counterpart for the string that we converted to Base64.

Decoding Base64 Strings with Node.js

Decoding a Base64 string is quite similar to encoding it. You have to create a new buffer object and pass two parameters to its constructor. The first parameter is the data in Base64 and the second parameter is "base64". Then you simply have to call toString on the buffer object but this time the parameter passed to the method will be "ascii" because this is the data type that you want your Base64 data to convert to. Take a look at the following code snippet for reference.

'use strict';

let data = 'c3RhY2thYnVzZS5jb20=';
let buff = new Buffer(data, 'base64');
let text = buff.toString('ascii');

console.log('"' + data + '" converted from Base64 to ASCII is "' + text + '"');

Add the data to ascii.js file and save it. Here we have used "Tm8gdG8gUmFjaXNt" as the Base64 input data. When this data is decoded it should display "No to Racism". This is because from the last example we know that "No to Racism" is equal to "Tm8gdG8gUmFjaXNt". Run the above code with Node.js. It will display following output.

Encoding Binary Data to Base64 Strings

As mentioned in the beginning of the article, the primary purpose of Base64 encoding is to convert binary data into textual format. Let us see an example where we will convert an image (binary data) into a Base64 string. Take a look at the following example.

'use strict';

const fs = require('fs');

let buff = fs.readFileSync('stack-abuse-logo.png');
let base64data = buff.toString('base64');

console.log('Image converted to base 64 is:\n\n' + base64data);

In the above code we load an image into the buffer via the readFileSync() method of the fs module. The rest of the process is similar to creating a Base64 string from a normal ASCII string.

When you run the above code you will see the following output.

$ node encode-image.js
Image converted to Base64 is:

iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAADuUlEQVQ4EbVUTUtcZxR+7ufkXp1SZ4iZRE1EDVQRnTAhowsZMFm40I2rNqUIIev8hvoPQroQXBTqwiAWcd0EglEhiZNajVZrQGXAWAzaZpzMnZn7lXPeeIe5DaWb9Ax33vOec8/znI/3vVI6nfbxP4v8b/iSJIGfzyGfkPi+D13XUalUBL6qqmIvy5+8WuX/r2RCkUzAoIuLi2hqaoLrutjb28P6+josyxJkiqJA07SQXiqVwHaOZYx/itLc3Px9YIxEIlheXsbExATGxsYwMjIiwEdHRwXA/Pw8EokEcrkcDg4OYJomVlZWMDU1JSqfmZlBR0cHbNsOtVoNCHjlTFiSySQMwxAVxONxQbi0tIRMJoPe3l5MT0+jtbUVg4ODYGImY18qlcL4+DhisZjoggCjv1C7uOyenh7Mzs5iY2ND6FQpdnd3sba2JloSjUYxPDyM/v5+TE5OYn9/X9jZtrOzg+3t7WqyAUmoEu419/+HBw9E+eVymbJqAJP39fWBCR3HEU+hUMDQ0JCYGc8um81iYGAAjY2N8DwvwBdraCY8tHhDA1Y3N9Hd3S2yvH37O7RcbsF7AuUsD9+8wdOFBTx/8QJtbW1C5/nMzc3R0D2UyxXk83lRXcAk1V5GCT5sSUGDbeHxy9/EO98M9OOXzT9wfHISxKC1vR0GHfOtrS2g/SouWwU0Xkggu7qO9PUkJFULnbIQyTm6ewu2hF+vnOIIUQwdGlg8f4QF6wvMWBq+pAkaskSnx4FFVUf0CNpcC797KizXQ4oAHhVdXJJ81F7j6kwUynPHlXDPdFB2fRj+KVK0KvT2rbp3uKYryJU11Cke8qqMuOoioeeJ1MPDYxM36m1cNSq4GdFx58RAWvbx8TrXnK4IgR16Em5GK4iqHi5GHHxLgcSDn97WgZPoND+GGZRpPYH85cgiiRQl1ltXxmFFQ5PuopP8TrW5ZyRcWp7AbmkeZefg5+N6PPnbRJdpw/YlfB0vQiPQZwVdZNtFZEVK6D1VTnccJlXzuqTjvOZiq6Rhj2KqLSJsofOHgIl8+t0/qsfDioxmSUWGjrRFzhYi/5Oynrdl3KXHIZDXtF6hil8R6I9FBV/RvDLnXKxSbAdVYhNeINXBMwmXWCTQGG2Y+Jj+dFrfEmiMAtmeowpo9ojTvkD+A/L1UJUMmiVfkuz6WTyZhFRJAgP33j3bsM5k/Fng68UP21hYJyyxZwLWuS2cKMfUSm3rhD0g4E2g197fwMZ+Bgt8rNe2iP2BhL5dgfFzrx8AfECEDdx45a0AAAAASUVORK5CYII=

Although the actual image is very small (25x19), the output is still fairly large, partially because Base64 increases the size of the data, as we mentioned earlier.

Decoding Base64 Strings to Binary Data

The reverse process here is very similar to how we decode Base64 strings, as we saw in an earlier section. The biggest difference is the output destination and how data is written there. Let's see the example:

'use strict';

const fs = require('fs');

let data = 'iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAA' + 
'CA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEAmpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0' +
'YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly' +
'93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAg' +
'ICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZm' +
'Y6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAAADuUlEQVQ4EbVU' +
'TUtcZxR+7ufkXp1SZ4iZRE1EDVQRnTAhowsZMFm40I2rNqUIIev8hvoPQroQXBTqwiAWcd0EglEhiZNajVZrQGXAWAzaZpzMnZn7lXPeeIe5Da' +
'Wb9Ax33vOec8/znI/3vVI6nfbxP4v8b/iSJIGfzyGfkPi+D13XUalUBL6qqmIvy5+8WuX/r2RCkUzAoIuLi2hqaoLrutjb28P6+josyxJkiqJA' +
'07SQXiqVwHaOZYx/itLc3Px9YIxEIlheXsbExATGxsYwMjIiwEdHRwXA/Pw8EokEcrkcDg4OYJomVlZWMDU1JSqfmZlBR0cHbNsOtVoNCHjlTF' +
'iSySQMwxAVxONxQbi0tIRMJoPe3l5MT0+jtbUVg4ODYGImY18qlcL4+DhisZjoggCjv1C7uOyenh7Mzs5iY2ND6FQpdnd3sba2JloSjUYxPDyM' +
'/v5+TE5OYn9/X9jZtrOzg+3t7WqyAUmoEu419/+HBw9E+eVymbJqAJP39fWBCR3HEU+hUMDQ0JCYGc8um81iYGAAjY2N8DwvwBdraCY8tHhDA1' +
'Y3N9Hd3S2yvH37O7RcbsF7AuUsD9+8wdOFBTx/8QJtbW1C5/nMzc3R0D2UyxXk83lRXcAk1V5GCT5sSUGDbeHxy9/EO98M9OOXzT9wfHISxKC1' +
'vR0GHfOtrS2g/SouWwU0Xkggu7qO9PUkJFULnbIQyTm6ewu2hF+vnOIIUQwdGlg8f4QF6wvMWBq+pAkaskSnx4FFVUf0CNpcC797KizXQ4oAHh' +
'VdXJJ81F7j6kwUynPHlXDPdFB2fRj+KVK0KvT2rbp3uKYryJU11Cke8qqMuOoioeeJ1MPDYxM36m1cNSq4GdFx58RAWvbx8TrXnK4IgR16Em5G' +
'K4iqHi5GHHxLgcSDn97WgZPoND+GGZRpPYH85cgiiRQl1ltXxmFFQ5PuopP8TrW5ZyRcWp7AbmkeZefg5+N6PPnbRJdpw/YlfB0vQiPQZwVdZN' +
'tFZEVK6D1VTnccJlXzuqTjvOZiq6Rhj2KqLSJsofOHgIl8+t0/qsfDioxmSUWGjrRFzhYi/5Oynrdl3KXHIZDXtF6hil8R6I9FBV/RvDLnXKxS' +
'bAdVYhNeINXBMwmXWCTQGG2Y+Jj+dFrfEmiMAtmeowpo9ojTvkD+A/L1UJUMmiVfkuz6WTyZhFRJAgP33j3bsM5k/Fng68UP21hYJyyxZwLWuS' +
'2cKMfUSm3rhD0g4E2g197fwMZ+Bgt8rNe2iP2BhL5dgfFzrx8AfECEDdx45a0AAAAASUVORK5CYII=';

let buff = new Buffer(data, 'base64');
fs.writeFileSync('stack-abuse-logo-out.png', buff);

console.log('Base64 image data converted to file: stack-abuse-logo-out.png');

Here you can see that we start with the Base64 data (which could've also been received from a socket or some other communication line) and we load it into a Buffer object. When creating the buffer we tell it that it's in base64 format, which allows the buffer to parse it accordingly for internal storage.

To save the data back in its raw PNG format, we simply pass the Buffer object to our fs.writeFileSync method and it does the conversion for us.

Conclusion

Base64 encoding is one of the most common ways of converting binary data into plain ASCII text. It is a very useful format for communicating between one or more systems that cannot easily handle binary data, like images in HTML markup or web requests.

In Node.js the Buffer object can be used to encode and decode Base64 strings to and from many other formats, allowing you to easily convert data back and forth as needed.

Encoding and decoding Base64 strings is especially important for becoming an expert in working with Node.js. The growing demand for skilled developers opens up a world of career opportunities. If you're exploring new career paths, check out Node.js remote jobs to discover exciting roles that align with your skills.

What do you typically use Base64 formatting for in Node.js? Let us know in the comments!

Last Updated: November 25th, 2024
Was this article helpful?

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

© 2013-2024 Stack Abuse. All rights reserved.

AboutDisclosurePrivacyTerms