Create a gist now

Instantly share code, notes, and snippets.

How to post a photo to Facebook from client-side Javascript
// This bit is important. It detects/adds XMLHttpRequest.sendAsBinary. Without this
// you cannot send image data as part of a multipart/form-data encoded request from
// Javascript. This implementation depends on Uint8Array, so if the browser doesn't
// support either XMLHttpRequest.sendAsBinary or Uint8Array, then you will need to
// find yet another way to implement this. (This is left as an exercise for the reader,
// but if you do it, please let me know and I'll integrate it.)
// from:
if ( XMLHttpRequest.prototype.sendAsBinary === undefined ) {
XMLHttpRequest.prototype.sendAsBinary = function(string) {
var bytes =, function(c) {
return c.charCodeAt(0) & 0xff;
this.send(new Uint8Array(bytes).buffer);
// This function takes an array of bytes that are the actual contents of the image file.
// In other words, if you were to look at the contents of imageData as characters, they'd
// look like the contents of a PNG or GIF or what have you. For instance, you might use
// pnglib.js to generate a PNG and then upload it to Facebook, all from the client.
// Arguments:
// authToken - the user's auth token, usually from something like authResponse.accessToken
// filename - the filename you'd like the uploaded file to have
// mimeType - the mime type of the file, eg: image/png
// imageData - an array of bytes containing the image file contents
// message - an optional message you'd like associated with the image
function PostImageToFacebook( authToken, filename, mimeType, imageData, message )
// this is the multipart/form-data boundary we'll use
var boundary = '----ThisIsTheBoundary1234567890';
// let's encode our image file, which is contained in the var
var formData = '--' + boundary + '\r\n'
formData += 'Content-Disposition: form-data; name="source"; filename="' + filename + '"\r\n';
formData += 'Content-Type: ' + mimeType + '\r\n\r\n';
for ( var i = 0; i < imageData.length; ++i )
formData += String.fromCharCode( imageData[ i ] & 0xff );
formData += '\r\n';
formData += '--' + boundary + '\r\n';
formData += 'Content-Disposition: form-data; name="message"\r\n\r\n';
formData += message + '\r\n'
formData += '--' + boundary + '--\r\n';
var xhr = new XMLHttpRequest(); 'POST', '' + authToken, true );
xhr.onload = xhr.onerror = function() {
console.log( xhr.responseText );
xhr.setRequestHeader( "Content-Type", "multipart/form-data; boundary=" + boundary );
xhr.sendAsBinary( formData );

I modified this code in: 'POST', ''+albumId+'/photos?access_token=' + authToken, true );

//post to graph album

But the function return this error:

400 (Bad Request)
   "error": {
      "message": "(#1) An unknown error occurred",
      "type": "OAuthException",
      "code": 1

Do you have any idea to fix this problems?


I would check to make sure the authToken you're using gives permission to post to the given album.


Hi, i'm trying to use your code getting the image source from a HTML5 canvas element:
after generating image with canvas i convert it with

  source = img.toDataURL('image/png'); 

and upload it on Fb calling your function:

  PostImageToFacebook( accessToken, 'img.png', 'image/png', source, 'js upload' );

but the function return this error:

  400 (Bad Request)
   "error": {
      "message": "(#1) An unknown error occurred",
      "type": "OAuthException",
      "code": 1

I'm sure that my authToken have the right permissions (i can do it in php!)
How can I fix it?
Thank you


Thanks Andy, this was very helpful!

coire1, I had the same "unknown error." In case you still need a solution, or for others who come across this, here's what worked for me:

You need to base64 decode the canvas output which can be done using this:

So my code ended up something like this:

var c = canvas.toDataURL('image/png');
var encodedPng = c.substring(c.indexOf(',')+1,c.length);
var decodedPng = Base64Binary.decode(encodedPng);

After that, I feed decodedPng into Andy's function, and it works great!


this is a great snippet, it seems ok on chrome but it fail on safari... can you help me?


I can confirm that it works on all decent browsers (i.e. all but IE), including Safari Mobile at iOS 5.1.
IE 9 (didn test 10) is the only one not supportting Uint8Array.

It is mandatory to use jsalden encoding/decoding approach.

Thanks a lot andyburke and jsalden. Doing this was the most hermetic stuff I've ever done in my developer career!!



and some keywords for google: canvas upload photo facebook javascript javascriptsdk


I had give up hope. After 4 months i googled the same keywords, found this thread with my comment and....A SOLUTION!!! Wonderful! Thanks andyburke and jsalden!




I am getting this. Can anybody help me out
[00:15:45.797] "{
"error": {
"message": "(#1) An unknown error occurred",
"type": "OAuthException",
"code": 1


thanks, you saved me :)

    var img = document.createElement('img');
    img.src = 'http://localhost/quadrinhos/shareImage.png';
    img.onload = function () {
        var canvas = document.createElement("canvas"); 
        canvas.width = img.width; 
        canvas.height = img.height; 
        var ctx = canvas.getContext("2d"); 
        var c = canvas.toDataURL('image/png');
        var encodedPng = c.substring(c.indexOf(',')+1,c.length);
        var decodedPng = Base64Binary.decode(encodedPng);

        PostImageToFacebook(response.authResponse.accessToken, 'shareImage.png', 'image/png', decodedPng, '');

This doesn't handle non-ASCII in the message part. Anyone know how to solve that?


I solved the charset problem using the following code in line 46:

formData += 'Content-Type: text/plain; charset=UTF-8\r\n';
formData += 'Content-Disposition: form-data; name="message"\r\n\r\n';
formData += unescape(encodeURIComponent(message)) + '\r\n'
formData += '--' + boundary + '--\r\n';

any one found a way to do this on IE9 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment