Media Library Unused Image Cleaner

19

Safely identifies and removes unused images from your media library through an intelligent 11-step detection system. It offers both manual review with a paginated interface and automatic batch cleanup via AJAX, protecting any images found in use across posts, products, widgets, and site settings. Built-in disk space tracking and progress monitoring make it easy to reclaim storage without risking deletion of essential images.

This plugin adds a Tools → Media Checker admin page where you can:

  • run an automatic batch cleanup (AJAX, chunked processing with progress bar)
  • review a paginated list of all images
  • manually select and delete only those images that are confirmed unused

The core of the plugin is an 11-step “in-use” detector that checks common WordPress and WooCommerce locations (content, product galleries, taxonomy metadata, widgets/options, Customizer settings, site logo and favicon, etc.).
If an image is detected as in use, it is protected from deletion, and the interface clearly shows where the image is used.

Admin interface (Tools → Media Checker)

  • Adds a management page under Tools
  • Shows a paginated table of images with:
    • thumbnail preview
    • attachment title + ID
    • usage status (in use / unused)
    • total disk size including generated thumbnails
    • “usage source” label (what triggered the protection)

Manual deletion mode

  • Only images detected as unused are selectable
  • Uses a nonce-protected form submission
  • Deletes selected attachments permanently

Batch (automatic) cleanup

  • Scans the entire Media Library via AJAX in batches of 100
  • Shows a progress bar and live stats:
    • scanned items
    • deleted items
    • freed disk space
  • Designed to avoid timeouts by chunking requests

Accurate size calculation

  • Calculates disk usage as:
    • original uploaded file size
    • plus every generated thumbnail size registered in attachment metadata

“In use” detection logic (11 checks)

For each image attachment ID, the plugin tries to prove it’s referenced somewhere.
If it finds a match, it returns a human-readable label and the image is considered protected.

  1. Featured image / product image
    Checks _thumbnail_id in postmeta.
  2. WooCommerce product gallery
    Checks _product_image_gallery and FIND_IN_SET().
  3. Embedded inside post content
    Searches published post content for:
  • the full image URL
  • the Gutenberg class pattern wp-image-{ID}
  1. Taxonomy thumbnail
    Checks termmeta.thumbnail_id (commonly used by Woo categories and similar taxonomies).
  2. Taxonomy description
    Searches term_taxonomy.description for the URL or wp-image-{ID}.
  3. Taxonomy meta fields
    Searches termmeta.meta_value for:
  • URL match
  • direct numeric ID match
  1. ACF / custom fields (non-hidden meta keys)
    Checks postmeta where meta_value = attachment ID and meta_key does not start with _.
  2. Widgets / site options
    Searches wp_options.option_value for:
  • the attachment ID
  • and the attachment URL
    (Used as a broad “this might be referenced in widgets/settings” safety net.)
  1. Site Logo
    Compares the attachment ID to get_theme_mod('custom_logo').
  2. Site Icon / favicon
    Compares the attachment ID to get_option('site_icon').
  3. Customizer theme mods
    Scans all get_theme_mods() values for either:
  • numeric ID match
  • URL substring match
    If found, reports which Customizer setting contains the reference.

If none of the checks hit, the image is treated as unused and becomes eligible for deletion.

How the batch cleanup works (AJAX flow)

  1. Fetch all image attachment IDs
  • wp_ajax_muc_get_all_images returns a full ID list (posts_per_page => -1)
  1. Process IDs in chunks
  • wp_ajax_muc_process_batch receives up to 100 IDs
  • For each ID:
    • run the 11-step check
    • if unused → calculate size → wp_delete_attachment( $id, true )
  • Returns:
    • number of deleted images
    • total bytes freed
  1. Frontend loop continues
  • updates progress bar
  • keeps running until all IDs are processed
  • retries after 3 seconds if an AJAX request fails

Important notes (very important)

1) This plugin permanently deletes files

It calls:

wp_delete_attachment( $id, true );

That means:

  • the attachment post is removed
  • the original file and generated thumbnails are deleted from disk

2) Performance considerations

  • Batch mode is chunked to reduce timeouts – good.
  • However, the “get all IDs” step loads the entire image ID list at once. On huge media libraries, that can be heavy.

3) Be aware

This logic is strong, but not omniscient. Images can still be referenced in ways not covered here, for example:

  • CSS files (background-image URLs)
  • theme templates hardcoding URLs
  • page builder data stored in custom tables
  • JSON in custom meta keys starting with _ (your ACF check skips hidden keys)
  • WooCommerce variation images via _thumbnail_id are covered, but other plugin-specific storage may not be

Where it fits best

  • Large WooCommerce sites that accumulated thousands of old images
  • Cleanup before migration / backup size reduction
  • Sites where editors upload lots of media and never reuse it

There are no reviews yet.

Be the first to review “Media Library Unused Image Cleaner”

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