Performance and Multisite help — book a call with me via my Expert page on Clarity, I use this service for calls.

Delete unused images in WordPress: attachments, media, unattached images, 404, orphaned

!! Before anything: make sure you made a backup!

Remove unused images attachments (orphaned images that are not attached to any WordPress post, page or custom post)

When you delete your posts, attachments from them don’t get deleted automatically. They keep staying in the WordPress Media Library and on your web server eating disk space and messing things up.

The following function will delete them permanently. Both — from Media Library and from wp-content/uploads folder too.

Be careful with what you are doing. For example, in one of the projects we added images and descriptions on tags archive pages for SEO purposes and these images as you understand are not attached to any post, however that doesn’t mean we want to get rid of them.

If you’ve thoroughly thought this out and you are  sure you want to get rid of this orphaned media, here you go:

Delete all attachments related to a specific custom post type

This function is useful when you need to delete all images that are attached to a specified CPT.  For example, you used to have CPT on the side, and then deleted it or migrated leaving it behind.

Mind changing “card” to your custom post type name.

This will delete both — an attachment from WordPress, and an actual file from your web server.

Clean up WordPress Media Library: delete all attachments whose files are no longer present on a web server and give a 404 error (blank thumbnails in Media Library)

Is your Media Library populated with images that are not displayed? When you click them it says the image does not exist anymore and gives you 404 page?

This is a broken link issue. There is no file for that attachment stored on a web server anymore so you are seeing these empty squares in Media Library as ghosts of previously existing images.

You can delete images from WordPress Media Library with this function — it will clean up your Media Library from non-existent images by deleting all WordPress attachments whose files that no longer present on a web server.

Caution: resource greedy!

*Mind that if you have a link to such file somewhere in posts it will stay there and still give 404 to users. To explore this issue and find such broken links in posts I use Screaming Frog.

You are always making a backup before something like that. Right?

Reverse: How to find and delete unused images WordPress Uploads directory

Note: This part is not for attachments but for actual files, in your Uploads directory — reverse check!

If your website is more than a few months old you know how surprisingly large your wp-content/uploads can become one day. You don’t know where all that stuff comes from and where it goes but it just occupies all free space on your web server.

Here is how to define useless media correctly and get rid of it. Just watch out for what you are doing as delete means delete.

Case 1: all images on your site are stored as WP attachments

Good media: all WordPress attachments

Bad media: anything stored in uploads directory that is not WP attachment

This function will free up disk space on your hosting account. It will scan your wp-content/uploads directory (recursively) and check every found file whether it is WP attachment or not.

All files that are not WP attachments will be deleted. If you got a rather large uploads folder (say 5 GB) you might want to split the process into parts by folders.  I’ve got 1 GB checked and cleaned in 15 seconds (only 300 MB left!).

This is how we find and delete images which are not attachments.

But what if your images are not stored as WP attachments at all but are still used on your website?

Case 2: images on your site are uploaded through custom fields and are not stored as WP attachments

Good media: all images saved in specified custom fields

Bad media: anything else in uploads directory

Step 1: Define all good images


First, we need to get the combined list of all “good” images that are used on the website, so later we can delete all files that are not used.  

I’ll show one of the cases as an example. It’s an online bookstore. We’ve managed to get rid of 32 thousand of useless files and free up to 75% of disk space on a web server. 

Before: 42096 images 4767 MB

After: 9202 images 1251 MB

Cleaned 32894 images and saved 3516 MB disk space

Here we’ve got 3 post types: posts (used for books), book author and booklist. Image for every post type is stored in a separate custom field (book cover, author’s pic and book list image). We’ll obtain the list of images used for each CPT and combine them together to get a full list of good images. These are the images that we will preserve.

Step 2: Delete images not used by WordPress installation

So we’ve got the complete list of good images that are used on the website in variable $all_good_pictures. Now we’ll go through the wp-content/uploads directory and check every file whether it’s on the the list or not. If it’s not listed we’ll just delete it.

Okay, but EXACTLY what do you do with the code?

I was hesitant about adding this paragraph, but people keep asking me here, on GitHub, on Twitter, and via email, and everywhere — so:


If you don’t know what to do with these snippets, you added them to your functions.php nothing happened, and you don’t know WHY — my opinion: you should read about WP actions and hooks first, at the very least this short article.

In 2 words: all the snippets above are functions. (And yes, you need to place the needed one in functions.php of your child theme or via code snippet plugin if you use one.)
But those are functions.

You need to connect the needed function to the action to fire it.

For example, after_setup_theme action –> then to fire it you’ll use: add_action('after_setup_theme', 'function_name_here'); 
+ it would be very nice to check that the action you hooked to, runs only once.

Seriously, I would recommend getting acquainted with WP Actions and Hooks concept before all this. Or make a backup at least 🙂

Wrap up

Here is how we can get our WordPress install clean and well-organized, reduce data amount and CPU load and even move to a cheaper hosting plan as we won’t store gigabytes of trash anymore.

And just in case, you’ve made a backup, right? 🙂

Delete unused images in WordPress: attachments, media, unattached images, 404, orphaned

16 responses to “Delete unused images in WordPress: attachments, media, unattached images, 404, orphaned”

  1. agcyber4 Avatar

    How to use it? paste on which php file on wordpress?

    1. SZ Avatar
      SZ

      hey,
      All functions can be placed in functions.php file of the current theme or in the plugin and fired with actions like «init», «wp_head» etc or run with shortcode depending on your goals. Good luck!

  2. agcyber4 Avatar

    How to use it? paste on which php file on wordpress?

    1. SZ Avatar
      SZ

      hey,
      All functions can be placed in functions.php file of the current theme or in the plugin and fired with actions like «init», «wp_head» etc or run with shortcode depending on your goals. Good luck!

  3. Ruriko Avatar
    Ruriko

    It doesn’t work for me. I copied & paste the code into functions.php of the Twenty Seventeen theme right at the very bottom. I refresh my site but I don’t see it deleting unattachments

    1. sz Avatar

      Hi! See the section above: Okay, but EXACTLY what do you do with the code?

  4. Wayne Holmes Avatar

    Hi, I just came across your post here about deleting orphaned media. It looks great and just what I need. However I’m a little unsure just what to do with your code. Can you explain a little on what to do with it (for a relative newby)
    Many many thanks.
    Regards
    Wayne

    1. sz Avatar

      Hi Wayne! See the section above: Okay, but EXACTLY what do you do with the code?

  5. Jens Avatar
    Jens

    Hey, nice functions!

    I wonder if you have any ideas on the following use case:

    I have a lot of images on my site, WordPress combined with WooCommerce.

    WordPress is creating 4 different image sizes on my site (thumbnail, medium, medium_large and large).

    In addition to that WooCommerce adds 6 image sizes (woocommerce_single, woocommerce_gallery_thumbnail, shop_catalog, shop_single and shop_thumbnail).

    I have implemented a function that makes sure that if the upload of an image is done on a product post type, the default wordpress image sizes are disabled. It also works the other way around, if not on a product post type, the woocommerce image sizes will not be generated.

    But, and this is a big but ( 😀 ), this only works for new uploads. For all my other, thousands of images, I can’t come up with a way to remove the default wordpress image sizes attached to a product post type as well as the other way around, remove all the woocommerce product sizes attached to non product post types.

    Do you have any ideas around this?

    Thanks in advance!

    1. sz Avatar

      Hi Jens!
      “I have implemented a function that makes sure that if the upload of an image is done on a product post type, the default wordpress image sizes are disabled. It also works the other way around, if not on a product post type, the woocommerce image sizes will not be generated.” — this is cool.
      What you are doing here – is prohibitting creating new stuff.

      “For all my other, thousands of images, I can’t come up with a way to remove the default wordpress image sizes attached to a product post type as well as the other way around, remove all the woocommerce product sizes attached to non product post types.”
      What you need to do here — is to go through all you have and delete what’s not used.
      It would be 2 different tasks, 2 different functions.

      For example, “to remove the default wordpress image sizes attached to a product post type” -> use function from paragraph Delete all attachments related to a specific custom post type, but add an addtional check where you check for the post type (if ( ‘card’ == get_post_type($parent_id) ) {) — also check for the size of the image (have a look at wp_get_attachment_image_sizes) , and if it matches the one that you don’t need — then delete.
      Same for vice versa.

  6. […] This method is not for the faint of heart and should only be used by developers who know what they are doing. If you have a lot of unattached images that you want to remove, you can do so quickly by running a code snippet rather than using a plugin. Sabrina Zeidan has all the details here. […]

  7. What are Unattached Images in WordPress? | Web Training Wheels Avatar

    […] This method is not for the faint of heart and should only be used by developers who know what they are doing. If you have a lot of unattached images that you want to remove, you can do so quickly by running a code snippet rather than using a plugin. Sabrina Zeidan has all the details here. […]

  8. Ron Houp Avatar
    Ron Houp

    Okay, but EXACTLY what do you do with the code?

    1. sz Avatar

      Hi Ron! Take a look at “Okay, but EXACTLY what do you do with the code?” section above, named after your comment 🙂

  9. Sam Avatar
    Sam

    Hi Sabrina

    Great post. This is awesome stuff. I thought I would share with you a plugin we created since we do this quite a bit. It’s made our lives a bit easier helping us understand what is using up our disk space on the server.

    Please check out: https://wordpress.org/plugins/media-hygiene/

    I would love to get some feedback.

Leave a Reply to agcyber4 Cancel reply

Your email address will not be published. Required fields are marked *