How to remove unused images in WordPress: 3 reliable methods (without breaking your pages)

The Mediapapa Team Avatar

Your WordPress media library has become an attic. Eight years of test uploads, deleted drafts, old hero images, screenshots that were never used, product photos from a catalogue you no longer sell. The folder weighs several gigabytes, backups take forever and every time you open the media library you scroll past visual noise you have…

How to remove unused images in WordPress guide with a computer screen displaying software.

Your WordPress media library has become an attic. Eight years of test uploads, deleted drafts, old hero images, screenshots that were never used, product photos from a catalogue you no longer sell. The folder weighs several gigabytes, backups take forever and every time you open the media library you scroll past visual noise you have not seen on the live site in years.

So you decide to clean it up. And five minutes in, you hesitate. Deleting the wrong image breaks the hero on the homepage. Or the background on the contact page. Or that featured image on a popular blog post Google sends traffic to every week.

This guide gives you three reliable methods to remove unused images from a WordPress media library, ordered from the simplest to the most robust. Each one comes with the safety protocol you need to apply before deleting anything: find, verify, delete in small batches, check. Nothing here is theoretical. The goal is a cleaner library at the end of the afternoon, with zero broken pages.

What does “unused” actually mean in WordPress?

Before any cleanup, one distinction matters. WordPress shows a filter called Unattached in the media library. It is not what you think it is.

An attachment in WordPress is technically a custom post type. When you upload an image directly inside a post or page editor, that image becomes attached to that post. The Unattached filter shows you every image that was not uploaded through a post editor, or whose parent post has since been deleted.

That is a very narrow definition. Unattached does not mean unused. An image can be unattached and still appear everywhere on your site. Site logos uploaded through the customiser are unattached. Background images set in a page builder are unattached. Featured images chosen from the existing media library are usually unattached. Images called by a shortcode are unattached. CSS backgrounds, header decorations, footer assets, WooCommerce product gallery images that come from the library: all unattached, all in use.

So the working definition we need is different. An image is unused when nothing on your site references it: no post content, no template, no widget, no customiser setting, no CSS background, no shortcode, no plugin option, no theme option. The further your stack is from a plain text-only theme, the more places references can hide.

This is why every method below shares one principle: never trust a single signal. Verify usage with a quick proof before you delete.

Before you remove anything: the non-negotiable safety checklist

Five rules. Skip any of them and you will eventually break something.

Full backup, restorable

Not just a backup file sitting somewhere. A backup you have actually restored once, on staging or anywhere, so you know it works. A backup you cannot restore is decoration.

Staging if available

If you have staging, run the cleanup there first. Validate the site visually, then replicate on production. If you do not have staging, the next rules become non-negotiable.

Delete in small batches

Ten to fifty files at a time. Never a thousand. The whole point of batching is that if something breaks, you know which batch did it. Mass deletion makes diagnosis impossible.

Use the trash, not permanent delete

WordPress trashes media before permanent deletion. Use that intermediate state. Trash a batch, browse the site for ten minutes, then empty the trash only if nothing is broken.

The 60-second proof

Before trashing any image you are unsure about, run a quick check: copy the file URL, search for it inside the site (page content, templates, customiser settings). Open the pages where it might appear. Inspect them on desktop and mobile. If after sixty seconds you still cannot confirm the image is unused, do not delete it. Move on.

The most important rule

The cost of leaving a few unused images in the library is negligible. The cost of breaking the homepage on a Friday afternoon is not. When in doubt, do not delete.

Method 1: the small site approach (manual, native WordPress)

For small sites with a couple of hundred media files and no complex page builder, the native WordPress media library is enough. Budget: zero. Time: one afternoon.

Open the media library in list view. Use the date filter to look at older uploads first. Use the Unattached filter as a starting point, not an answer. Sort by date ascending so you see the oldest files at the top.

Step by step

  1. Click the file to open its details panel.
  2. Look at the “Uploaded to” field. If it is empty, the file is unattached.
  3. Check the file URL. Copy it.
  4. Use your browser’s search (Ctrl/Cmd+F) on the relevant pages or paste the URL into your site’s search bar.
  5. If nothing comes back, also check the customiser (logo, header, footer, widgets) and any global theme options.
  6. If still nothing, move the file to the trash.

After a batch of ten or twenty files, open the front-end. Check the homepage, two or three high-traffic pages, the header, the footer, the contact page. If everything looks right, empty the trash for those files.

What you get with this method: a clean library, no plugin installed, complete control. What you give up: speed and reliability on anything but a small site. If your theme uses background images set through theme options, or if you use a page builder, the native filters will miss references and you will trash files that are still in use.

The method works if your site is simple. It does not scale.

Method 2: a media cleanup plugin (recommended for most sites)

For most WordPress sites between a few hundred and several thousand media files, a dedicated plugin is the practical answer. The principle is the same as the manual method, but the scan covers more places: post content, post meta, term meta, widgets, customiser settings, common page builder data, sometimes CSS files.

A good media cleanup plugin gives you a list of candidate files, lets you exclude categories of media (featured images, WooCommerce variations, files in a specific folder), and offers a bulk action to move candidates to the trash.

The safe workflow with a plugin

  1. Backup the site. Take staging if you have it.
  2. Install the plugin and run a first scan on staging.
  3. Review the candidate list. Look for patterns: large batches of files from a specific date, files with names that match deleted pages, demo content from the original theme.
  4. Set up exclusions before deleting anything. Common exclusions: featured images, files used by your active page builder, files referenced in your theme options, WooCommerce product images and variations.
  5. Move a small batch to the trash. Do not empty it immediately.
  6. Browse the site for several minutes. Test the pages most likely to use older media.
  7. If everything works, empty that batch from trash. If something is broken, restore from trash and adjust your exclusions.
  8. Repeat in batches.

The honest limits of plugins

Most plugins detect references in content and templates, fewer detect CSS background images defined in custom stylesheets, almost none detect images called dynamically by a custom plugin or theme. After a recent migration or redesign, plugins also produce more false positives because old references in deleted posts are no longer there to anchor files that are still used elsewhere.

Treat the plugin output as a shortlist, not a verdict. The plugin proposes; you verify; you delete.

Mediapapa fits here. Mediapapa scans your entire library against every usage context WordPress knows about (post content, post meta, options, widgets, customiser, common page builders, ACF fields), produces a list of unused media, and refuses to let you delete anything that has a known reference. The usage index runs in the background and gets refreshed as you publish. Deletion Warnings flag files that have references the scan found in unusual places, so you get a second chance to confirm before trash. The free version handles unused media detection without volume caps. None of this replaces the verification step, but it makes the candidate list trustworthy enough that a small site can be cleaned in an hour and a large one in an afternoon.

Method 3: the advanced approach for large sites (WP-CLI and database checks)

For very large sites, e-commerce catalogues with tens of thousands of media files, news sites with deep archives, or any stack with custom plugins that touch media in non-standard ways, the plugin scan alone leaves too much uncertainty. The advanced method crosses two sources of truth: what is in the uploads folder, and what is referenced anywhere in the database.

What you are actually doing

  1. List every file currently sitting in /wp-content/uploads/.
  2. List every URL or attachment ID referenced anywhere in the database (post content, post meta, term meta, options, comments, custom tables if any).
  3. Cross-reference. Files in /uploads that nothing in the database mentions are your strong candidates. References in the database that point to files no longer in /uploads are broken links to fix.
  4. Apply the same verification step as the other methods on a sample before any deletion.

WP-CLI makes this manageable on large sites because you can run scans in batches on the server, output the results to a file and process them at your own pace. The same logic can run as a scheduled job for monthly maintenance.

wp media list --post_status=any --fields=ID,post_title,attachment_url --format=csv

This method is more reliable than a plugin at scale because it looks at raw data instead of relying on plugin support for every page builder, custom field type and edge case. It is also more technical. You need command-line access. You need to understand which database tables your stack uses for media references. You need to handle exclusions for files generated by image optimisation plugins.

Two extra checks for large sites

After deletion, look at server access logs for 404 errors on image URLs. A spike in image 404s after cleanup tells you exactly which files you should not have removed.

Check your CDN. A CDN may still serve a cached copy of a deleted file from edge nodes for hours. Purge the CDN after a deletion pass.

When to stop and call a professional

If the site is critical, if you have many custom templates, if your stack includes a headless setup or a heavy CDN configuration, or if the consequences of a broken page are commercial. The cost of a half-day consulting engagement is lower than the cost of a broken checkout.

Get the print-and-tick version

The full safety protocol from this article, condensed into a PDF you can print or share with your team. Five non-negotiables, three methods, the loop and the post-cleanup sweep.

After deletion: the no-broken-pages checklist

The cleanup is not finished when the trash is empty. Run through this every time.

  • Homepage, on desktop and mobile.
  • The five most-visited pages in your analytics.
  • Header, footer, sidebar widgets across page templates.
  • Category and tag archive pages.
  • The most recent ten blog posts.
  • Product pages and checkout, if you sell anything.
  • Internal search results page with a common query.
  • Browser console: open developer tools, browse a few pages, look for 404 errors on image URLs.

Clear your full-page cache. Purge your CDN. Check the site logged out, in a private browsing window. Some image issues only appear without admin styling overlays.

If you find a 404 on an image you deleted, restore it from your trashed-but-not-emptied batch (if you still have it) or from your backup. Then fix the reference in the page that needed it: re-upload, replace the URL, or change the source.

Most cleanups produce zero broken pages. The point of the checklist is that you find out within ten minutes, not three weeks later when a customer emails you.

How do you prevent unused images from coming back?

Cleanup is maintenance, not a one-time project. Without a routine, the library will be a mess again in eighteen months.

A realistic monthly routine

  • Run the unused media scan (plugin or WP-CLI).
  • Review only the files uploaded in the last month or two. The older the file, the more carefully it needs to be verified.
  • Trash and verify in small batches.
  • Check for obvious duplicates by name (image.jpg, image-1.jpg, image-2.jpg) and merge where possible.
  • Rename files with descriptive slugs before uploading new ones, so future you can find things by search.

Habits to adopt as a team

  • Search the library before uploading. Half of all duplicates come from someone re-uploading because they could not find the existing file.
  • Use the same naming convention across the team. A consistent prefix (year, project, type) makes search work.
  • Never upload demo or placeholder images to a production library. Use a folder you flag for deletion before launch.

Ten minutes a month, every month, is dramatically less work than a four-hour rescue cleanup once a year. And it stops the library from ever getting overwhelming again.

Get the print-and-tick version

The full safety protocol from this article, condensed into a PDF you can print or share with your team. Five non-negotiables, three methods, the loop and the post-cleanup sweep.

FAQ

Not without verification. Unattached in WordPress only means an image was not uploaded directly inside a post editor, or that its parent post was deleted. Many images that appear on your live site are unattached: logos, page builder backgrounds, featured images, header and footer assets, files used in widgets. Always verify usage before deleting an unattached file.

Most page builders store image references in post meta, not in the post content itself. A native search in WordPress for the file URL will miss them. Either use a media cleanup plugin that understands your page builder, or check each page in the page builder editor to confirm the image is or is not used.

CSS backgrounds are the most common source of false positives in media cleanup. If a background image is defined in a stylesheet (theme CSS, custom CSS in the customiser, page builder custom CSS), it may not show up in any database scan. Before removing files that look unused but have descriptive names suggesting they are backgrounds (hero, banner, header, bg-), open the relevant pages and inspect their styles.

Yes, if you used the trash. WordPress moves media to trash before permanent deletion. Files in trash can be restored. Once you empty the trash, recovery requires a backup. This is why the workflow above keeps batches in trash until you have visually confirmed nothing is broken.

Indirectly. Unused images do not slow down page loads because they are not served to visitors. They do slow down backups, migrations and admin operations. They also waste storage. Real speed improvements come from optimising the images that are actually displayed: format, compression, dimensions, lazy loading.

Treat them as protected. WooCommerce stores image references in product meta, in product variations and sometimes in gallery fields. A media cleanup plugin that does not understand WooCommerce will produce false positives. Either use a plugin with explicit WooCommerce support, or exclude WooCommerce image categories from your cleanup pass entirely.

Monthly for active sites with multiple contributors. Quarterly for sites with one or two editors. A short pass every month prevents the library from ever becoming overwhelming, and keeps you from making large mistakes during a one-time rescue cleanup.

Further reading

Related posts