Anyone know of a good snippet of JavaScript code to convert HEX encoded strings to base64 encoded strings?
Asked
Active
Viewed 5.2k times
48
-
8btoa("4142434445464748494a4b4c4d4e4f505152535455565758595a".match(/\w{2}/g).map(function(a){return String.fromCharCode(parseInt(a, 16));} ).join("")) – dandavis Apr 21 '14 at 03:33
-
There's a `` (zero-width non-joiner followed by a zero-width space) in @dandavis' comment, which makes the snipped fail with the rather cryptic error "SyntaxError: illegal character" in Firefox, and "SyntaxError: Unexpected token ILLEGAL" in Chrome. Here's the fixed code: `btoa("4142434445464748494a4b4c4d4e4f505152535455565758595a".match(/\w{2}/g).map(function(a){return String.fromCharCode(parseInt(a, 16));} ).join(""))` – waldyrious Mar 23 '15 at 22:03
-
**UPDATE:** I tried pasting a working version in my previous comment, but it seems it's StackOverflow who is adding the invisible characters -- what the hell?! So I guess, for now the only solution is to try copying the code to an editor that shows such invisible characters (try https://www.diffchecker.com/ if you don't have any at hand) and remove the culprit. It should work then. – waldyrious Mar 23 '15 at 22:09
-
Dear @Chris Dutrow please have sight on my question: http://stackoverflow.com/questions/34963963/converting-a-hex-string-of-a-raw-image-to-a-bitmap-image-in-javascript – Hosein Aqajani Jan 25 '16 at 07:28
-
3@dandavis For performance reasons, I would do it this way around: `btoa(String.fromCharCode.apply(null, hex.match(/\w{2}/g).map(function(a) { return parseInt(a, 16) })))` – yckart Jun 14 '16 at 15:11
5 Answers
101
If you're working in Node or using Browserify, you can use
var base64String = Buffer.from(hexString, 'hex').toString('base64')
or
var hexString = Buffer.from(base64String, 'base64').toString('hex')

Tim
- 6,265
- 5
- 29
- 24
-
1saved my more half a day worth of code which would have gone to trash without this knowledge. – Vikram Gulia Mar 10 '20 at 22:20
36
The excellent comment by @dandavis is modified by StackOverflow, and has some weird hidden characters.
Here it is as one liner :
btoa("a6b580481008e60df9350de170b7e728".match(/\w{2}/g).map(function(a){return String.fromCharCode(parseInt(a, 16));} ).join(""))
or :
function hexToBase64(hexstring) {
return btoa(hexstring.match(/\w{2}/g).map(function(a) {
return String.fromCharCode(parseInt(a, 16));
}).join(""));
}
hexToBase64("a6b580481008e60df9350de170b7e728");
Both return :
"prWASBAI5g35NQ3hcLfnKA=="
Note that the hex string should have an even length :
hexToBase64("00");
// => "AA=="
hexToBase64("000");
// => "AA=="

Eric Duminil
- 52,989
- 9
- 71
- 124
-
-
1And it also loses a character if the length is odd `hexToBase64('ab') === hexToBase64('abc')` – Christian Vincenzo Traina Dec 20 '19 at 15:09
-
@CristianTraìna: As far as I can tell, base64 `AA==` is the expected output for hex `00`. Every other function returns the same. Functions which accept odd-length hex input seem to pad the hex digits, so for example : `base64ToHex(hexToBase64('000')) // => "00 00"`. I'll edit the answer to specify that the length of input should be even. – Eric Duminil Dec 20 '19 at 16:17
22
if (!window.atob) {
var tableStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var table = tableStr.split("");
window.atob = function (base64) {
if (/(=[^=]+|={3,})$/.test(base64)) throw new Error("String contains an invalid character");
base64 = base64.replace(/=/g, "");
var n = base64.length & 3;
if (n === 1) throw new Error("String contains an invalid character");
for (var i = 0, j = 0, len = base64.length / 4, bin = []; i < len; ++i) {
var a = tableStr.indexOf(base64[j++] || "A"), b = tableStr.indexOf(base64[j++] || "A");
var c = tableStr.indexOf(base64[j++] || "A"), d = tableStr.indexOf(base64[j++] || "A");
if ((a | b | c | d) < 0) throw new Error("String contains an invalid character");
bin[bin.length] = ((a << 2) | (b >> 4)) & 255;
bin[bin.length] = ((b << 4) | (c >> 2)) & 255;
bin[bin.length] = ((c << 6) | d) & 255;
};
return String.fromCharCode.apply(null, bin).substr(0, bin.length + n - 4);
};
window.btoa = function (bin) {
for (var i = 0, j = 0, len = bin.length / 3, base64 = []; i < len; ++i) {
var a = bin.charCodeAt(j++), b = bin.charCodeAt(j++), c = bin.charCodeAt(j++);
if ((a | b | c) > 255) throw new Error("String contains an invalid character");
base64[base64.length] = table[a >> 2] + table[((a << 4) & 63) | (b >> 4)] +
(isNaN(b) ? "=" : table[((b << 2) & 63) | (c >> 6)]) +
(isNaN(b + c) ? "=" : table[c & 63]);
}
return base64.join("");
};
}
function hexToBase64(str) {
return btoa(String.fromCharCode.apply(null,
str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))
);
}
function base64ToHex(str) {
for (var i = 0, bin = atob(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) {
var tmp = bin.charCodeAt(i).toString(16);
if (tmp.length === 1) tmp = "0" + tmp;
hex[hex.length] = tmp;
}
return hex.join(" ");
}

coder hacker
- 4,819
- 1
- 25
- 50
-
Dear @coder hacker , please see my question: http://stackoverflow.com/questions/34963963/converting-a-hex-string-of-a-raw-image-to-a-hex-string-of-a-bitmap-image-in-java – Hosein Aqajani Jan 25 '16 at 06:18
-
4
I liked the approach from @eric-duminil nevertheless the solution below - avoiding regex - is ~2x faster.
Browser:
function hexToBase64(hexStr) {
return btoa([...hexStr].reduce((acc, _, i) =>
acc += !(i - 1 & 1) ? String.fromCharCode(parseInt(hexStr.substring(i - 1, i + 1), 16)) : ""
,""));
}
OR
// even a bit faster
function hexToBase64(hexStr) {
let base64 = "";
for(let i = 0; i < hexStr.length; i++) {
base64 += !(i - 1 & 1) ? String.fromCharCode(parseInt(hexStr.substring(i - 1, i + 1), 16)) : ""
}
return btoa(base64);
}
Node:
const base64 = Buffer.from(hexStr, 'hex').toString('base64');

Robin F.
- 1,137
- 11
- 19
2
Large strings, no btoa
Solution below is good for large strings - if you want to get bytes from base64 then look HERE
function bytesArrToBase64(arr) {
const abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // base64 alphabet
const bin = n => n.toString(2).padStart(8,0); // convert num to 8-bit binary string
const l = arr.length
let result = '';
for(let i=0; i<=(l-1)/3; i++) {
let c1 = i*3+1>=l; // case when "=" is on end
let c2 = i*3+2>=l; // case when "=" is on end
let chunk = bin(arr[3*i]) + bin(c1? 0:arr[3*i+1]) + bin(c2? 0:arr[3*i+2]);
let r = chunk.match(/.{1,6}/g).map((x,j)=> j==3&&c2 ? '=' :(j==2&&c1 ? '=':abc[+('0b'+x)]));
result += r.join('');
}
return result;
}
function hexToBytes(hexString) {
return hexString.match(/.{1,2}/g).map(x=> +('0x'+x));
}
// ---------
// TEST
// ---------
let hexString = "a6b580481008e60df9350de170b7e728";
let bytes = hexToBytes(hexString);
let base64 = bytesArrToBase64(bytes);
console.log(base64);

Community
- 1
- 1

Kamil Kiełczewski
- 85,173
- 29
- 368
- 345