112

I'm trying to fetch an image from the web and encode it with base64.

What I have so far is this:

var request = require('request');
var BufferList = require('bufferlist').BufferList;

bl = new BufferList(),

request({uri:'http://tinypng.org/images/example-shrunk-8cadd4c7.png',responseBodyStream: bl}, function (error, response, body) 
{
    if (!error && response.statusCode == 200) 
    {
        var type = response.headers["content-type"];
        var prefix = "data:" + type + ";base64,";
        var base64 = new Buffer(bl.toString(), 'binary').toString('base64');
        var data = prefix + base64;
        console.log(data);
    }
});

This seems to be pretty close to the solution, but I can't quite get it to work. It recognizes the data type and gives out this output:

data:image/png;base64

However, the bufferlist 'bl' seems to be empty.

6
  • Just a completely wild guess but I think it could be possible that the request() may be using a header indicating an agent that may be blocked by certain sites to minimize scraping. Commented Jun 15, 2013 at 13:50
  • @BrettZamir Do you think so? Blocking a request with a 200 response seems very nasty... Commented Jun 15, 2013 at 14:38
  • 1
    And may I ask: What is require('request')? Cannot find it in the documentation. All I know for this is http/https. Commented Jun 15, 2013 at 14:39
  • @Sebastian, yes, it is just a wild guess... But it is one of those problems which has recurred for me, so just offering it as a throwaway... Commented Jun 15, 2013 at 14:44
  • @SebastianG, if you can't find something being required in the docs, then that means it's from...? :D Commented Jun 15, 2013 at 23:22

11 Answers 11

193

BufferList is obsolete, as its functionality is now in Node core. The only tricky part here is setting request not to use any encoding:

var request = require('request').defaults({ encoding: null });

request.get('http://tinypng.org/images/example-shrunk-8cadd4c7.png', function (error, response, body) {
    if (!error && response.statusCode == 200) {
        data = "data:" + response.headers["content-type"] + ";base64," + Buffer.from(body).toString('base64');
        console.log(data);
    }
});
Sign up to request clarification or add additional context in comments.

7 Comments

encoding: null tells request that you want a buffer, not a string. A string gives you unusably garbled data, as the whole point of base64 is to encode binary. I got the answer about encoding in my own StackOverflow question stackoverflow.com/questions/16619980/…, so I'm happy to pay it forward.
Solution: Run production from localhost
May all Gods bless you... I knew it was an encoding problem, but I was struggling to find how to disable it on request library...
@DanKohn new Buffer is now deprecated. nodejs.org/api/buffer.html
request is also deprecated
|
64

If anyone encounter the same issue while using axios as the http client, the solution is to add the responseType property to the request options with the value of 'arraybuffer':

let image = await axios.get('http://aaa.bbb/image.png', {responseType: 'arraybuffer'});
let returnedB64 = Buffer.from(image.data).toString('base64');

Hope this helps

2 Comments

Thank you so much! Helped me saved a bunch of time and frustration!
I was having a lot of issues with this and axios, turns out the response type is what makes it. Thansk a lot!
45

DISCLAIMER: NO INSTALLATION REQUIRED

This works using built-in http module!

NOTE: I tried it in node version 6.x, also applicable to above versions.

var http = require('http');

http.get('http://tinypng.org/images/example-shrunk-8cadd4c7.png', (resp) => {
    resp.setEncoding('base64');
    body = "data:" + resp.headers["content-type"] + ";base64,";
    resp.on('data', (data) => { body += data});
    resp.on('end', () => {
        console.log(body);
        //return res.json({result: body, status: 'success'});
    });
}).on('error', (e) => {
    console.log(`Got error: ${e.message}`);
});

I hope it helps!

Also, check more about the http.get(...) here !

2 Comments

This works. I had to use both the http and https modules in my solution since most resources are https today. Unfortunately, you'll need to check manually which module to use. See stackoverflow.com/a/45215071/4978821.
Best answer for me!
27

Another way of using node fetch, which breaks down the steps per variable:

const fetch = require('node-fetch');

const imageUrl = "Your URL here";
const imageUrlData = await fetch(imageUrl);
const buffer = await imageUrlData.arrayBuffer();
const stringifiedBuffer = Buffer.from(buffer).toString('base64');
const contentType = imageUrlData.headers.get('content-type');
const imageBase64 = 
`data:${contentType};base64,${stringifiedBuffer}`;

1 Comment

fetch is available natively in node since v18, so you don't need node-fetch anymore.
16

If you know the image type, it's a one-liner with the node-fetch package. Might not suit everyone, but I already had node-fetch as a dependency, so in case others are in a similar boat:

await fetch(url).then(r => r.buffer()).then(buf => `data:image/${type};base64,`+buf.toString('base64'));

2 Comments

Nice and concise!
Works well! .buffer has been deprecated. This is the new way: const blob = await response.arrayBuffer(); return `data:${response.headers.get("content-type")};base64,${Buffer.from(blob).toString("base64")}`;
12

If you are using axios then you can follow below steps

var axios = require('axios');
const url ="put your url here";
const image = await axios.get(url, {responseType: 'arraybuffer'});
const raw = Buffer.from(image.data).toString('base64');
const base64Image = "data:" + image.headers["content-type"] + ";base64,"+raw;

you can check with decode base64.

Comments

9

You can use the base64-stream Node.js module, which is a streaming Base64 encoder / decoder. The benefit of this method is that you can convert the image without having to buffer the whole thing into memory, and without using the request module.

var http = require('http');
var base64encode = require('base64-stream').Encode;

http.get('http://tinypng.org/images/example-shrunk-8cadd4c7.png', function(res) {
    if (res.statusCode === 200)
        res.pipe(base64encode()).pipe(process.stdout);
});

Comments

3

I use for load and encode image into base64 string node-base64-image npm module.

Download and encode an image:

var base64 = require('node-base64-image');

var options = {string: true};
base64.base64encoder('www.someurl.com/image.jpg', options, function (err, image) {
    if (err) {
        console.log(err);
    }
    console.log(image);
});

Encode a local image:

var base64 = require('node-base64-image');

var path = __dirname + '/../test.jpg',
options = {localFile: true, string: true};
base64.base64encoder(path, options, function (err, image) {  
    if (err) { console.log(err); }  
    console.log(image);  
}); 

2 Comments

base64.encode(<URL>, <OPTIONS>, <CALLBACK>) api reference: github.com/riyadhalnur/node-base64-image/blob/HEAD/docs/docs.md
ECONNREFUSED error when trying this npm package. can see same issue opened in GitHub but no resolutions given
2

Oneliner:

Buffer.from(
    (
      await axios.get(image, {
      responseType: "arraybuffer",
    })
  ).data,
  "utf-8"
).toString("base64")

Comments

2

Old post but could help someone. On the basis of Dmytro response that help me.

const base64FromUrl = async (url: string) => {
  try {
    return Buffer.from((await axios.get(url, { responseType: "arraybuffer", })).data, "utf-8").toString("base64")
  } catch (error) {
    return ""
  }
}

I've just add error handling.

Comments

1

You can use image-to-base64 Node.js module

The benefit of using this module is that you convert your image hassle-free

const imageToBase64 = require('image-to-base64');

const imageLink = 'Your image link'
imageToBase64(imageLink);
.then((response) => {
    const base64Image = `data:image/png;base64,${response}`
    console.log(base64Image);
  })
  .catch((error) => {
    console.log(error);
  })

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.