Working with Cloud Vision API from JavaScript

I ran into a case where I wanted to fool around with Cloud Vision API from pure JavaScript. Not node.js, just JavaScript running in a browser. There were no samples, so I figured I’d whip up some. So here is a little primer on how to do this from JavaScript in a browser.

First you have to take care of a few prerequisites:

Once you do this you’re ready to start developing. Make sure you hold on to the API key you created above.

The first thing you need to do is create an upload form.  This is pretty basic in HTML5.

<!DOCTYPE html>
<html lang="en">
	<meta charset="UTF-8">
	<title>Cloud Vision Demo</title>
	<form id="fileform" action="">
		<select name="type" id="type">
		</select><br />
		<input id="fileInput" type="file" name="fileField"><br /><br />
		<input type="submit" name="submit" value="Submit">

</body> </html>

Note that I’m using a select box to drive the type of detection I am doing.  There are more choices, but I’m sticking with landmark detection for now.

Next you need to convert the image to Base64 encoding to transmit the image data via a REST API. I looked around for how to do this “properly” and the best I came up with was the “easy way” mentioned in this Stack Overflow post – Get Base64 encode file-data from Input Form.

I use  readAsDataURL(). 

function uploadFiles(event) {
  event.stopPropagation(); // Stop stuff happening
  event.preventDefault(); // Totally stop stuff happening

  //Grab the file and asynchronously convert to base64.
  var file = $('#fileInput')[0].files[0];
  var reader = new FileReader()
  reader.onloadend = processFile

function processFile(event) {
  var encodedFile =;

Then I massage the content into the JSON format that the Cloud Vision API expects. Note that I strip out “data:image/jpeg;base64,”. Otherwise Cloud Vision sends you errors. And you don’t want that. 

var type = $("#type").val();

  // Strip out the file prefix when you convert to json.
  var json = '{' +
    ' "requests": [' +
    '	{ ' +
    '	  "image": {' +
    '	    "content":"' + content.replace("data:image/jpeg;base64,", "") + '"' +
    '	  },' +
    '	  "features": [' +
    '	      {' +
    '	      	"type": "' + type + '",' +
    '			"maxResults": 200' +
    '	      }' +
    '	  ]' +
    '	}' +
    ']' +

And then I send. With the API key.  That’s it. Nothing to it really.

    type: 'POST',
    url: "" + api_key,
    dataType: 'json',
    data: json,
    //Include headers, otherwise you get an odd 400 error.
    headers: {
      "Content-Type": "application/json",

    success: function(data, textStatus, jqXHR) {
    error: function(jqXHR, textStatus, errorThrown) {
      console.log('ERRORS: ' + textStatus + ' ' + errorThrown);

If you want to dig deeper into the Cloud Vision API you can

The code for all of this is now shared in the Cloud Vision repo on GitHub.

Github Ribbons in CSS

Github has these cool ribbon images that you can use if you want to encourage forking your project on your site. They’re great and I wanted to use them on a little project I am working on. However, one of my goals was not to use any images, but rather produce all display elements with CSS.

It was a little bit of trial and error but I got it working. Basically you do the following:

  • Create a link in a div with an id of “banner”
  • Force div#banner to be 149px x 149px.
  • Set overflow to “hidden”

This creates a square display area that won’t show things that stretch out past the bounds of the box.

  • Create an A link
  • Tilt it using a CSS transform
  • Use relative positioning to pull the ribbon into place
  • Use CSS shadows to tweak the text and ribbon shadows
  • Finally I use a CSS gradient in the background of the ribbon to give it the bands that run along the edge.


  • It’s not a pixel perfect representation.
  • It doesn’ work on IE before 9. It doesn’t appear at all.

I’m not sure if I’m going to use this. I’ll sound judgmental here, but the fact that it doesn’t show up on IE less than 9 seems like a good thing. Do I want a developer on my project that isn’t using the latest browser? Probably not.

See the live demo here.


A couple people pointed out that there was a weird doubling of the letters on their browser (Chrome on Windows, and Safari on iPad.) Looks like it was caused by a slight text-shadow I had on the text. The text on the original banner has some anti-aliasing going on, and on some browsers, the text shadow helps it look a little smoother, but on others you get that doubling. So I’ve removed the text shadow.  Display should be a little more consistent.