Using the WordPress 3.5 Media Uploader in Your Plugin or Theme

Back in 2010, I wrote a post on Using the WordPress Uploader in Your Plugin or Theme that went on to be one of my most popular tutorials of all time. Then the WordPress team went and added a much cooler media uploader in version 3.5 and make that post outdated. Since most of you probably want to add the new uploader in a theme or plugin you’re working on right now, I figured it was time for an updated post.

WordPress 3.5 Media Uploader

The process required to add the new uploader is a bit different, but not too much more difficult. I was able to adapt the old tutorial a little, so it shouldn’t be too hard to replace some code in an existing project and get the new uploader instead of the old.

For the sake of simplicity, let’s start with the same HTML snippet as in the old tutorial. This goes along with the rest of the HTML for your admin page, or wherever in the admin you’re trying to add an upload field.

<label for="upload_image">
	<input id="upload_image" type="text" size="36" name="ad_image" value="http://" /> 
	<input id="upload_image_button" class="button" type="button" value="Upload Image" />
	<br />Enter a URL or upload an image

Now we need to load up the necessary JavaScript files.

add_action('admin_enqueue_scripts', 'my_admin_scripts');

function my_admin_scripts() {
	if (isset($_GET['page']) && $_GET['page'] == 'my_plugin_page') {
		wp_register_script('my-admin-js', WP_PLUGIN_URL.'/my-plugin/my-admin.js', array('jquery'));

We bind the my_admin_scripts() function to the admin_enqueue_scripts hook, and enqueue both the media scripts and our own JavaScript file. Also, the scripts will only be loaded if the current page is equal to “my_plugin_page,” which you would of course replace with the slug your admin menu has.

Now for the complicated part: the script that hooks into the uploader. Continuing with the above example, it would be named my-admin.js.


	var custom_uploader;

	$('#upload_image_button').click(function(e) {


		//If the uploader object has already been created, reopen the dialog
		if (custom_uploader) {;

		//Extend the object
		custom_uploader = ={
			title: 'Choose Image',
			button: {
				text: 'Choose Image'
			multiple: false

		//When a file is selected, grab the URL and set it as the text field's value
		custom_uploader.on('select', function() {
			attachment = custom_uploader.state().get('selection').first().toJSON();

		//Open the uploader dialog;



When the button is clicked, it creates a new instance of the object and configures it to only accept a single file, since the text field can only hold one file URL. Then it binds a function to the selection action, which gets the file attributes when an image is chosen and sets the #upload_image text field value to the file’s URL.

Providing everything went as expected, you should have a form field that will accept an arbitrary URL, or allow the user to upload one.

File Upload Field

  • Brian

    Thank you for this great tutorial! I was wondering if there is a similar way to add or customize the attachment editor dialog in posts and pages. It seems that when we add meta data at the upload stage then we attach the meta data to that specific attachment across all posts and pages, when in some cases it would be desirable to add meta data to an attachment on a post to post basis.

  • Nathan

    Thanks for the tutorial as it is very useful and informative for WordPress users in general. I am definitely going to use it for my WordPress Viewer plugin by GroupDocs. It has proved to be a handy tool to view various file formats and WordPress new Uploader will make it more easy for me. Thanks again!

  • Adal

    Hey Matt,

    Thanks for the great post. This is one of the articles that was great help in moving forward for my project.

    However I’ve run into a strange problem when trying to display thumbnails of images I just uploaded:

    // Show Thumbs
    var attachment_thumbs = {
    attachment = attachment.toJSON();
    console.log(‘sizes’, attachment);
    return ”;
    }).join(‘ ‘);

    When selecting images that were previously uploaded to the media gallery, this code works like a charm to display thumbnails as feedback to the user that their selection was successful (I’m doing front-end posting).

    The problem happens when I upload an image and select it right away (after waiting for upload to complete). The console log gives me an empty object:
    Object {id: “”, title: “”, caption: “”, description: “”}
    And I also get an error:
    Uncaught TypeError: Cannot read property ‘thumbnail’ of undefined

    I’ve tried waiting but that doesn’t help. The only thing that can force the media uploader to define the javascript image object completely seems to be selecting multiple other images (previously uploaded), using those, and then going back to the media uploader and picking the fresh images again.

    This seems very strange to me, and I can’t figure out where the source of the issue lies as the code behind the media uploader is compressed and far from transparent.

    • Adal

      So it turns out that the media uploader often creates a first empty object… not sure why. I simply filtered out any empty objects and it works fine now.

    • s7a8m

      This post is really useful, but i want to extend the current uploader adding a new Tab after “Media Library” Tab.

      How can i do that?

      Thanks in advance.

  • waqas

    Great tutorial. Thnk you. I have been trying to put this on the front-end, to give users the ability to upload an image, but nothing happens when i click upload image button, any tips? I would appreciate it

  • Sunith Babu

    Although I’m not that good at coding. I felt this will help me in configuring my blog.

    Kudos !

  • Cuong Nghiem

    How to get back a multiple attachment url into a for example!
    I’m not good at coding ><"!


      me too :(


        me too, too :v

        • Neo Do

          me too too too

    • Girl xinh

      When the button is clicked, it creates a new instance of the object and configures it to only accept a single file, since the text field can only hold one file URL. Then it binds a function to the selection action, which gets the file attributes when an image is chosen and sets the #upload_image text field value to the file’s URL.

  • Van Wilson


    I noticed in the attachment object that the 3.5 Uploader returns, there is the attachment ID. I’m saving this, instead of the attachment URL, so that I can show thumbnails of these extra images in the admin section and on my CTP single page, and then fetch a larger image with AJAX based on the attachment ID:

    In my meta box:
    <input name="pr_product_image1_id" id="pr_product_image1_id" class="pr-attachment-id" type="hidden" value="” />

    In my Javascript click handler:
    $( ‘.img_button’ ).click( function( e ) {
    attachment_id_field = $( this ).prev( ‘.pr-attachment-id’ ).attr( ‘name’ );

    ( same code as Matt used…)

    //When a file is selected, grab the URL and set it as the text field’s value
    custom_uploader.on( ‘select’, function() {
    var attachment = custom_uploader.state().get(‘selection’).first().toJSON();
    //Open the uploader dialog;

    This allows me to use “echo wp_get_attachment_image” to display the thumbnail in the metabox after the page is updated or when the user comes back to edit it later, but I’m still trying to figure out how to show the thumbnail immediately, as soon as the image is attached.

    Can anyone help?

  • Jessica

    WordPress Admin Themes are back please checkout the plugin –

    WQADIS001 Discount Code $10 OFF

  • Some Guy

    Thank you for this simple and easy article. It was exactly what I wanted!

  • Robert

    Matt – you are a lifesaver! I had implemented the earlier version of this code in custom admin pages on a number of websites for clients over the past years. Went to use it again with WP 3.5.1 and the upload button had stopped working (talking about the 2010 version of your code). In my desperate quest of many hours to figure out a fix, I luckily came across this updated version you posted. Works like a charm. Thanks a million for taking the time to post the update.

    • Matt

      Glad I could help. I figured people would be wanting to use the new, shinier option anyway. :)

  • Brendan

    Wow Matt,

    What a fantastic guide! This is what I’ve been looking for all day. Thank you so much!

    A quick question for anyone who may be reading this… I’m trying to limit the file types that the media box can see. I’ve seen other tutorials where they use ‘library’ – ‘type:”image”‘ in the javascript, but I cannot find any documentation. Does anyone know what kind of arguments I can use, or where I can find documentation? Thanks!

    • Matt

      I’m afraid documentation is still spotty. Sorry. :(

    • Denis Kuznetsov

      Hey, Brendan, did you found solution how to limit file types?

  • Ulrich

    For weeks I tried to make it work, and thanks to this tutorial I finally succeeded. Thanks a lot, Matt!

  • alvisir

    Hi Matt, thank you for this great tutorial. I’m developing a plugin in which there are more than one media uploader in the same page and i noticed that a conflict occurs between them. If I select an image and confirm, the modal window doesn’t close automatically as it should be (anyway the corresponding text field is filled with the url). However if I use one media uploader the problem doesn’t occur… Is it normal this issue? :(

    • alvisir

      If you need to add more than one uploader on the same page, just add “.unbind(‘click’)” after the click event, as follows:
      “$(‘.upload_image_button’).unbind(‘click’).click(function(e) {…”

      note: The object is a class (not an ID as in the tutorial) just because in this case there is more than one uploader.

      • tomncoffee

        Hey – great script – and for a non-programmer I am amazed I got it working – for only one uploader on a page.

        I have multiple uploaders in a theme options panel.
        The first one works great, the others do not pull up the upload panel.
        I tried your unbind(‘click’) solution, but that disables ALL uploaders including the first.

        Not sure what to do. Is there some kind of instance number that should be applied to each uploader?

        • tomncoffee

          I figured out this whole thing and have it working for more than one instance of the uploader on a page.

          And I have it built into an options panel for a theme I designed for shopping carts. If your’re interested in getting my solution, contact me.

          • Zach Rogers

            Do you still have this code that you could share?

          • Renzo Salvador

            Could you share it please?

    • rahul

      WP is not defined error is showing

  • Franco

    Hey, thanks for the tutorial. But I’m looking to see what other types of data JavaScript can retrieve from the selected image which is then sent to JSON. I know this isn’t very well documented so I wanted to find out.

  • Gabriel Merovingi

    Thank you for this tutorial!
    Any chance you could point someone in the right direction to change the title or button labels?

    • Peter

      Hi there, just change the value=”[any text for button label]” will do.

  • Peter

    I really really appreciate your post. It’s exactly what I was looking for! Luckily I met you before I customize WordPress TinyMCE style to hide out its toolbars HAHA !!

  • Reuven Karasik

    Wow! Thank You SO MUCH! so easy and works so good.

  • dev user

    For multiple uplaod buttons on the same page – just comment out the uploader reopen as below:
    //If the uploader object has already been created, reopen the dialog
    // if (custom_uploader) {
    // return;
    // }

    • Renzo Salvador

      That’s it? what about multiple: true?

    • Παντελής

      I am not sure (I am not a javascript developer) but since the :
      $(‘#upload_image_button’).click(function(e) {
      works on specific button click….

  • Melinda McCaw


    I have used your code to integrate the Media uploader into a metabox in a Custom Post Type and it works great. I have noticed thought that the uploader is missing the Attachment Display Settings that show up to the right of the images. All I get are the Attachment Details. Any idea how to get the Attachment Display Settings to show up?


  • Zapra Gartiast

    great post.. and i was test it in my project.. it’s failed for me
    I have question, should I add the jQuery to directory that my-admin.js placed?

  • Majo

    5 min implementation and works great. Well done, sir.

  • Nick Powers

    Thanks for a great tutorial, it was exactly what I needed for a plugin that I’m developing!


  • Giovani

    Hej there! Awesome tutorial!

    However I am stuck on something… Is there a way to make the window close right when we select one image? This is the regular behavior on wordpress, like, for example, when you set the featured image.

    Explaining in more details ~ when I pick one image from my uploaded images (click in one to mark it) and I press “Choose Image” everything works fine (I managed to send and print the img.src back to my plugin page), however the uploader window does not close. I need to de-select and select the image again, OR, I need to close manually the uploader.

    The same happens if I upload a brand new image. After uploading, I select it, then I choose it (everything ok until here), and then I need to manually close the uploader window.

    In the regular wordpress way, as soon as you select your featured image, the uploader window closes itself automatically.

    Any ideas?
    Does anyone noticed that?

    • Giovani

      If I have searched carefully before… ALVISIR had the same problem as me. ALVISIR already provided the solution previously!

      I have a theme options page using 2 tabbed sections, and I have one uploader on each. For some reason, every time I did open a media uploader, both were open layered one over another.

      After selecting the image, the window was closing itself fine, but I needed to close again bacause there was a second one initiated!

      So, I just added the “.unbind(‘click’)” before the “.click(function(e)”, just like ALVISIR stated, and the puzzle was solved!


    Sometime i upload, it got errors.

    Error: Can’t not upload.

  • Paul J

    For some odd reasons, I cannot view the media previously uploaded and adding the code below doesn’t work:

    // Show Thumbs
    var attachment_thumbs = {
    attachment = attachment.toJSON();
    console.log(‘sizes’, attachment);
    return ”;
    }).join(‘ ‘);

  • Gunaseelan

    I am creating a plugin and I have used the code for selecting an image. But when I click the “upload_image_button” image button, nothing happens. What I do wrong?. I have added the HTML code in the “form” function. What I have to give instead of “my_plugin_page’.

    function my_admin_scripts()
    if (isset($_GET[‘page’]) && $_GET[‘page’] == ‘my_plugin_page’) {

    I have added the screenshot for your reference.

    • barbie

      i’m also facing this problem.. did u solved this?

    • Veerendra Raghuvanshi

      Hey The code works flawlessly thanks.

      @Gunaseelan this is not the issue with the code you can just print the by “echo $_GET[‘page’] ” and you can get the exact page.

      And then you can put it in the condition and there is nothing happening clicking on the button because your .js file is not included due to wrong page condition.

  • Leandro Flaherty

    Very nice. Just want to add, anyone adding this who runs into problems, make sure that you dont have conflicts with jQuery. If its not working, try swapping out the $ in the javascript sections and type in jQuery instead, for example: $(‘something’).click(); becomes jQuery(‘something’).click(); .. I had to do this in my application. Cheers :)

  • Jordan Chase

    Thank you for the snippets! I wanted to add an input field for an image URL that’s saved to a particular custom taxonomy in my plugin and using WP’s built-in functions are always my preference to provide a consistent user experience. Cheers

  • Néstor Acevedo

    i get the following error:

    Cannot read property ‘frames’ of undefined

  • Piyush Dubey

    hi want this code to implement in my theme options.php page file please tell me how to implement this code i m not able to figure it out anybody please ……………

  • Yash Jain

    hi !! awesome script..I am new to wordpress and making plugin for the first time.. I’ve use this in my plugin and it works amazingly without any errors. Thanks for sharing it.

  • Peter Gallert

    I’ve been trying to get it to work with my theme options.
    Had to throw out your security page check, put wp_enqueue_media(); before the labels and insert the jscript into some script tags directly below the labels. not the prettiest way, but i am a noob ;)

  • jelewis8

    Awesome. Thanks!

  • Peter Gallert

    I am using this on the front-end, to let users upload images to the posts…
    is there a way to limit the media uploader, so that it only shows files uploaded to that particular post (instead of simply showing every single image ever uploaded to wordpress)…?

  • Jesse

    I too am getting an error on page load:

    Uncaught TypeError: Cannot read property ‘id’ of undefined

    Then, if I click the button, this comes up:

    Uncaught TypeError: Cannot read property ‘align’ of undefined

    I assume it’s because of the first error. Does anybody have any insight as to why?

  • Native Imaging

    How would I go about getting the option for external image url in the media uploader?

  • Renzo Salvador

    Excelent post, it works!

  • Mário Vital

    how can i save the upload image ?
    im using:
    if( isset( $_POST[ ‘upload-image’ ] ) ) {
    update_post_meta( $servicos_id, ‘upload-image’, $_POST[ ‘upload-image’ ] );


    and when update the post the value its lost and dont save at the database, any suggestions ?

  • Imran ali

    Simply Use cretak Multiple Uploader in wordpres

    $j = jQuery.noConflict();

    $j(document).ready(function() {

    /* user clicks button on custom field, runs below code that opens new window */

    $j(‘#upload_image_button’).click(function() {

    /*Thickbox function aimed to show the media window. This function accepts three parameters:


    * Name of the window: “In our case Upload a Image”

    * URL : Executes a WordPress library that handles and validates files.

    * ImageGroup : As we are not going to work with groups of images but just with one that why we set it false.


    tb_show(‘Upload a Image’, ‘media-upload.php?referer=media_page&type=image&TB_iframe=true&post_id=0′, false);

    return false;


    // window.send_to_editor(html) is how WP would normally handle the received data. It will deliver image data in HTML format, so you can put them wherever you want.

    window.send_to_editor = function(html) {

    var image_url = $j(‘img’, html).attr(‘src’);


    tb_remove(); // calls the tb_remove() of the Thickbox plugin




    <input class="webriti_inpute" type="text" value="” id=”upload_image_logo” name=”upload_image_logo” size=”36″ class=”upload has-file”/>

    <img style="height:60px;width:100px;" src="” />

  • Remy Sheppard

    This was amazing. Thank you.

  • Petr Novák

    Thanks you a lot. I have spent at least 20 hours by finding out how to handle that.. You are a saint.

  • Joe Rhoney

    Damn! You da man! Thank you so much!


    Very useful, thanks.

  • Beni

    Hi Matt,

    Thanks very much for this great tutorial.
    I got the upload working in my Themes Options Page.

    What I’m trying to do now is:
    – Only allow CSV-Files for upload
    – Convert the CSV-File directly after the upload to JSON (I already have code for the conversion) and save the path of the new JSON-File to the Themes Options

    Basically I need the JSON File in one of my Page-Templates.
    Could you help me out with this?

    Thank you!

  • sinta maharani

    WordPress 3.5 is better than ever and this is expected to penyebab keputihan gatal pada wanita

  • Zaheer Abbas

    it showing nothing and just loading ???

  • Alessio Ragni

    Many thanks!

  • Muhammad Sufiyan

    `wp_enqueue_media();` this is what I m missing .. in my own code.. thanks any ways..

  • Vance Three

    Please continue to share your knowledge and expertise, I’m sure many developers, drywall hanging and designers will appreciate the updated tutorial.