Code Snippet — Accessing Clipboard Images with Javascript

December 3rd, 2011 :: Web Development

a clipboard
The system clipboard is a feature that most of us heavy computer users probably couldn’t survive a day without. While it’s mostly used for copying and pasting text, images can also be stored in the clipboard, by for example using the print screen key. Today I want to share with you how you can access these images with a bit of Javascript code. This works in modern versions of Chrome and Firefox, but the technique differs a bit between them.

Here’s the code:

// We start by checking if the browser supports the 
// Clipboard object. If not, we need to create a 
// contenteditable element that catches all pasted data 
if (!window.Clipboard) {
	var pasteCatcher = document.createElement("div");
	
	// Firefox allows images to be pasted into contenteditable elements
	pasteCatcher.setAttribute("contenteditable", "");
	
	// We can hide the element and append it to the body,
	pasteCatcher.style.opacity = 0;
	document.body.appendChild(pasteCatcher);

	// as long as we make sure it is always in focus
	pasteCatcher.focus();
	document.addEventListener("click", function() { pasteCatcher.focus(); });
} 
// Add the paste event listener
window.addEventListener("paste", pasteHandler);

/* Handle paste events */
function pasteHandler(e) {
	// We need to check if event.clipboardData is supported (Chrome)
	if (e.clipboardData) {
		// Get the items from the clipboard
		var items = e.clipboardData.items;
		if (items) {
			// Loop through all items, looking for any kind of image
			for (var i = 0; i < items.length; i++) {
				if (items[i].type.indexOf("image") !== -1) {
					// We need to represent the image as a file,
					var blob = items[i].getAsFile();
					// and use a URL or webkitURL (whichever is available to the browser)
					// to create a temporary URL to the object
					var URLObj = window.URL || window.webkitURL;
					var source = URLObj.createObjectURL(blob);
					
					// The URL can then be used as the source of an image
					createImage(source);
				}
			}
		}
	// If we can't handle clipboard data directly (Firefox), 
	// we need to read what was pasted from the contenteditable element
	} else {
		// This is a cheap trick to make sure we read the data
		// AFTER it has been inserted.
		setTimeout(checkInput, 1);
	}
}

/* Parse the input in the paste catcher element */
function checkInput() {
	// Store the pasted content in a variable
	var child = pasteCatcher.childNodes[0];

	// Clear the inner html to make sure we're always
	// getting the latest inserted content
	pasteCatcher.innerHTML = "";
	
	if (child) {
		// If the user pastes an image, the src attribute
		// will represent the image as a base64 encoded string.
		if (child.tagName === "IMG") {
			createImage(child.src);
		}
	}
}

/* Creates a new image from a given source */
function createImage(source) {
	var pastedImage = new Image();
	pastedImage.onload = function() {
		// You now have the image!
	}
	pastedImage.src = source;
}

With Chrome we can access the image in the clipboard through the clipboardData object, but this can only be done inside a paste event handler. Inside the event handler, we loop through all items and search for an image. If we find one, we create a Blob of the image, and use the URL of it as the image source.

Firefox on the other hand does not have the clipboardData object, but we can work around this. In Firefox, it’s possible to paste images into elements with the contenteditable attribute set. By creating an invisible contenteditable element which always is focused, we can catch everything that the user pastes. So, everytime the user pastes something, we read through the content in the catcher element and check if it was an image. If it is, we simply take the source of that image and clear the element.

That nasty bit of code you see on line 48, setTimeout(checkInput, 1);, is a way to work around the fact that contenteditable elements don’t trigger oninput events in Firefox. Since the paste event triggers before anything is inserted into the element, we set a 1 ms timeout before we read the element’s content. This is enough time for the pasted content to be inserted.

Once we have the image, we can do anything we want with it, e.g append it to the page, draw it onto a canvas, upload it to a server, etc.

  • Murray

    Great job Joel.  

  • Murray

    It’s amazing what you have managed to do with some neat javascript functions.  Just one question – what format is the image when it arrives at the server.  I’m using this system for my customers to paste screen shots when they come across bugs, and I have the image in the “toDataURL” format, so how do I convert this back into a png (using PHP)?

    • JoelBesada

      The “toDataURL” format is a base64 encoded png image. To convert this back into a regular png file, simply use the base64_decode() function in PHP. :)

  • Sachin_shr

    Hi Joel,

    This really is an amazing and cool tool.PasteShack is exactly what I need. Because I am new to jQuery & Ajax, I am struggling to upload the selected image to server. It would be a great help if you could provide me the sample of upload page in PHP.

    Thanks a lotSachin

  • Nehem_high

    This really is amazing. 

  • Mondersky

    great way to paste images from clipboard, but is there a way to make it work on internet explorer??

  • Hgfds

    thx but, how integrated this with cross browser?

  • NilsNoreyson

    Hi Joel,

    i would like to thank you for providing this nice example on integrating the clipboard image data in an html5 canvas application.

    Thanks, Peter

  • http://profiles.google.com/atrabert Andreas Trabert

    nice tutorial, thx!
    Is there a WYSIWYG online Editor including the image paste feature ?

    • Alex V. Kostyukov

      Check TinyMCE

  • http://www.facebook.com/profile.php?id=100000334661051 Viktor Reisz

    Cool one! Now, I have an image. How can I send it to my server and save it? :) Thank you!

    • Vaibhav 1701sh

      Hi Viktor did u get any help on how to send it to the server and save it?? I too need the same.
      Thanks

    • Muhammad Akhtar

      Hi Vaibhav. Did you find a way to upload the file to the server using the url reference.. thanks.

    • Alex V. Kostyukov

      replace “for” content with this one:

      var imgBase64 = null
      var reader = new FileReader();
      reader.onload = function(event) {
      imgBase64 = event.target.result.replace(/^data:image/(png|jpg);base64,/, “”);
      createImage(event.target.result);
      };
      reader.readAsDataURL(items[i].getAsFile());// Blob to base64

  • Charles Scalfani

    This doesn’t work in the latest version of Firefox 15.0.1.

  • Deepakpoda2000

    Hi… I used the code as above.. but I dont see an image pasted on the web page… can someone please let me know if some thing else has to be added other that what exactly is    given above?
     something has to be added in createImage? 

  • Donmura

    ehm how to use this Code?

  • Shaify Mehta

    how to use this code…. ???

  • pratheeswaran

    For Internet Explorer, we can paste images from clipboards using Java Applets.

    Refer this post : http://www.vettyofficer.com/2012/11/how-to-paste-image-from-clipboard-using.html

  • Patrick

    Amazing!
    I’m developing a html5 image editor with paperJS and I’ve already implemented a drag n’ drop function for images, but I’ve needed one to import images from the clipboard too. Your code worked perfect and I bow to your skills.

  • Elfstone

    I know this is old, but I find it very useful. If I could get it to work.

    First off, for some reason, 1 ms delay doesn’t work – so I increased that to 500 ms and it works well in Firefox.

    But in Chrome… everything seems to work, the respective Blob is created, but I cannot seem to be able to use it as I can with the image created in Firefox!… Any pointers?

  • mahendra

    How to make it work in Safari ..???

  • Petes

    Is there any license for this?

  • san

    I got this javascript error ‘TypeError: document.body is null on this line document.body.appendChild(pasteCatcher)’ In chrome working fine.

  • mp singh

    thank ultimate script runn it all browser thanks

  • SanVar

    Thanks.. great code!! but doesnt support IE, Safari and Opera !!!

  • bern

    Hi,

    thanks for sharing the example. I can copy images from one browser to the other. But i can´t get it work copying images from the local file system to the browser window.

    Any ideas in this case?

  • Nicolas B.

    Joel,

    Pasteboard is great, but in Pasteboard pasting the image does not work in Mavericks’ Safari 7. It works in Firefox 25.0.1.

  • Vlad

    Joel, I took your code and some other sources and wrapped it in a plugin for pasting images in Firefox and Chrome:

    https://github.com/vladmalik/pasteimage

    There are some limitations. I figured putting it all together will help the community improve it. Thanks. Your site was a tremendous help.

  • noyo

    Seems window.Clipboard is gone as of Chrome 35, so the detection step won’t work.

  • mohanraj

    how to use this code?

  • ys

    brilliant! but transparency lost after pasting the image to browser…any way to work around with this issue?