Clean up your WordPress media library safely, step by step

How to Clean Up Your WordPress Media Library Safely (2026)

Clean up your WordPress media library the wrong way and you get broken images on pages nobody checked. Do it in the right order and you get smaller backups, less disk use and a library you can actually search.

This guide covers the full process: what is safe to remove, what only looks unused, how to handle orphan files and extra thumbnail sizes, a WP-CLI route for large sites, and the checks to run after you delete anything.

Short version: back up, test on staging, remove obvious leftovers first, review everything a scanner flags, move files to a trash you can restore from, delete in small batches, then crawl your site for broken images.

Why clean up your WordPress media library?

Every image you upload is stored once as the original and again in each image size your theme and plugins register (thumbnail, medium, large, plus extra sizes like WooCommerce product sizes). One upload can become several files on disk. Over years, replaced banners, old product photos, test uploads and files from deleted posts pile up.

  • Backups get bigger and slower, because every unused file is backed up again and again.
  • Disk usage grows, which matters on hosting plans with storage limits.
  • The Media Library gets harder to use, so editors re-upload files they can’t find, which adds duplicates.

Be realistic about speed: unused files that no page loads do not make your pages slower for visitors. If page speed is your goal, compress and resize the images you do use (covered below).

What is clogging your media library

TypeWhat it isRisk if removedHow to find it
Unused mediaA Media Library item that nothing on the site referencesLow, once verifiedA usage scanner, then manual spot checks
Unattached mediaAn item not uploaded inside a post. Says nothing about whether it is usedHigh if you trust the labelMedia Library list view, “Unattached” filter
Orphan files on diskFiles in wp-content/uploads with no Media Library recordUsually low, but check theme/plugin foldersA disk/filesystem scan
Extra thumbnail sizesGenerated sizes from old themes or plugins you no longer useLow, if you regenerate the sizes you still needA thumbnail or image-size tool
DuplicatesThe same file uploaded more than onceMedium: both copies may be in useHash comparison
PDFs, videos, audioNon-image uploads, often the largest filesMedium: often linked from menus, emails or downloadsFilter by file type

“Unattached” does not mean “unused”

Your logo, site icon, Customizer images and most page builder images are “unattached” because they were not uploaded inside a post, yet they are all in use. Never bulk-delete from the Unattached filter.

Step 1: Prepare before you delete anything

  1. Take a full backup of the database and the wp-content/uploads folder, and confirm you can restore it.
  2. Use staging if you can. Clone the site, do the whole cleanup there first, then repeat on production with a fresh backup.
  3. Know that WordPress has no media trash by default. Clicking “Delete permanently” in the Media Library removes the file, all its sizes and its database record. Without a backup or a plugin trash, it is gone.
  4. List where your site stores images: page builder (Elementor, Divi, WPBakery, Beaver Builder), WooCommerce galleries, ACF or other custom fields, widgets, the Customizer, theme CSS, email templates, sliders and popups.

Step 2: Remove orphan files and extra thumbnails

These are often the biggest and safest storage wins, because they are leftovers that are not tied to Media Library items.

Orphan files on disk

Orphan files sit in wp-content/uploads without a Media Library record, typically left by migrations, failed imports, FTP uploads or deleted attachments whose sizes stayed behind. Some plugins write their own folders inside uploads (cache, logs, form uploads, backups), so never delete a whole folder you don’t recognise. Use a tool with a disk scan and review its list.

Thumbnail and image-size bloat

Changing themes or turning off plugins leaves their image sizes on disk. The fix: decide which sizes your current theme and plugins need, regenerate those, and only then remove sizes that are no longer registered. A thumbnail-regeneration tool or WP-CLI handles this; see Deeper cleanup below for the commands. Note: Media Purge works on Media Library items (it scans for references to your attachments). It does not scan the disk for orphan files or remove unregistered thumbnail sizes, so use a dedicated tool for this step.

Step 3: Find unused images and media

Manual check (small libraries)

Switch the Media Library to list view and sort by date. For each candidate, search your site for the filename, and check widgets, menus and the Customizer. This works for a few dozen files, but it cannot see page builder data, WooCommerce galleries or custom fields stored in post meta.

With a scanner (most sites)

A usage scanner checks post content and the places images hide: post meta, widgets, theme settings and page builder data. Whatever tool you use, treat its list as a starting point:
  1. Run the scan and read the results before acting. Avoid one-click “delete all”.
  2. Spot-check about 20 flagged files by hand. If even one is actually in use, the scanner does not understand part of your setup. Find out why before continuing.
  3. Exclude anything you know is used. In Media Purge, click Keep to add a file to the Whitelist so it is never flagged again.
Full walkthrough: how to find unused images in WordPress without breaking your layout.

Images that most scanners miss

  • CSS background images set in your theme’s stylesheet, Additional CSS or a child theme file. These are not stored as attachment references in the database.
  • Files hard-coded in theme or plugin PHP/JS, such as a logo path in a template.
  • Images used outside WordPress: email newsletters, social posts, other sites hotlinking your uploads.
  • PDFs and videos linked by URL from menus, buttons or emails.
Search your theme files for /wp-content/uploads/ and whitelist what you find. Builder background images are different: Media Purge reads Elementor background images from Elementor data. For other builders, see removing unused images in Divi and removing unused images in WPBakery.

PDFs, videos and other files

Non-image files are usually the largest items in a library. Filter by file type, sort by size, and check each large PDF or video against your menus, download buttons and email campaigns before removing it.

Step 4: Handle duplicates

When finding a file is harder than uploading it again, people re-upload. WordPress then stores another copy (often name-1.jpg) with its own set of sizes. Before removing a copy, check which one each page uses; both may be live. Byte-for-byte duplicates are best found by hash comparison. See how to find and remove duplicate images in WordPress safely.

Step 5: Delete safely, in batches

  1. Move files to a trash you can restore from instead of deleting permanently.
  2. Work in batches of 10 to 50 files. After each batch, open your homepage, top landing pages, shop and any page built with a page builder.
  3. Wait before you empty the trash. Some broken images only show up on pages people rarely visit.

Step 6: Check your site after cleanup

  • Clear caches: your caching plugin, server cache and CDN. Cached pages can hide a missing image for days.
  • Crawl the site for broken images. Any site crawler can list image requests that return 404.
  • Check Google Search Console over the following weeks for new “Not found (404)” URLs under /wp-content/uploads/.
  • Restore anything that broke from your plugin trash or backup, then whitelist it.

For developers: WP-CLI and SQL

On large libraries, WP-CLI is faster and more reliable than the admin screen. These are core WP-CLI commands:
# Count Media Library items
wp post list --post_type=attachment --format=count

# List the image sizes registered by the current theme and plugins
wp media image-size

# Regenerate only missing sizes (skips sizes that already exist)
wp media regenerate --only-missing --yes

# Export attachment IDs, file paths and dates for review
wp post list --post_type=attachment --fields=ID,post_title,post_date,guid --format=csv > media.csv
Run them on staging first and after a backup.

A safer SQL starting point

A common query only checks whether the attachment’s original URL (guid) appears in post content. That misses resized copies such as photo-300x200.jpg and block references like wp-image-123. Matching on the file’s base name and the attachment ID catches more. The query also strips the -scaled and -rotated endings WordPress adds to large or rotated uploads, because their resized copies are named after the original file (photo-scaled.jpg has sizes such as photo-1024x683.jpg):
SELECT a.ID, a.post_title
FROM wp_posts a
JOIN wp_postmeta f ON f.post_id = a.ID AND f.meta_key = '_wp_attached_file'
WHERE a.post_type = 'attachment'
  AND NOT EXISTS (
    SELECT 1 FROM wp_posts p
    WHERE p.post_type NOT IN ('attachment','revision')
      AND ( p.post_content LIKE CONCAT('%', SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(f.meta_value,'/',-1),'.',1),'-scaled',1),'-rotated',1), '%')
         OR p.post_content LIKE CONCAT('%wp-image-', a.ID, '"%') )
  )
  AND NOT EXISTS (
    SELECT 1 FROM wp_postmeta m
    WHERE m.meta_key = '_thumbnail_id' AND m.meta_value = a.ID
  );
This is still incomplete. It does not check Elementor data, WooCommerce galleries, ACF fields (stored by attachment ID under each field’s meta key), widgets or theme options in wp_options. Use it to build a review list, never as a delete list. Change the wp_ prefix if your site uses another one.

Deeper cleanup: orphan files, image sizes, CSS images, PDFs and videos

The steps above are enough for most sites. Older sites, migrated sites and large stores usually need a few extra checks. Every command in this section only reads data unless it says otherwise. Run anything that removes files on staging first, after a backup.

Find files on disk that are not in the Media Library

WordPress has no built-in report for orphan files, so compare two lists: every file the Media Library knows about, and every file in your uploads folder. The first command builds the known list. It includes each attachment’s main file, its generated sizes, the original of any image WordPress scaled down, and the backup copies the image editor keeps.

wp eval '
foreach ( get_posts( array( "post_type" => "attachment", "post_status" => "any", "numberposts" => -1, "fields" => "ids" ) ) as $id ) {
  $file = get_attached_file( $id );
  if ( ! $file ) { continue; }
  $dir = dirname( $file );
  echo $file, "\n";
  $meta = wp_get_attachment_metadata( $id );
  foreach ( $meta["sizes"] ?? array() as $size ) { echo $dir, "/", $size["file"], "\n"; }
  if ( ! empty( $meta["original_image"] ) ) { echo $dir, "/", $meta["original_image"], "\n"; }
  $backups = get_post_meta( $id, "_wp_attachment_backup_sizes", true );
  if ( is_array( $backups ) ) { foreach ( $backups as $b ) { if ( ! empty( $b["file"] ) ) { echo $dir, "/", $b["file"], "\n"; } } }
}' | LC_ALL=C sort -u > known-files.txt

find "$(wp eval 'echo wp_get_upload_dir()["basedir"];')" -type f | LC_ALL=C sort > disk-files.txt

# Files on disk that no attachment claims
LC_ALL=C comm -13 known-files.txt disk-files.txt > not-in-library.txt

Treat not-in-library.txt as a review list, not a delete list. It will include folders that plugins write into uploads (caches, form uploads, backups, Elementor’s generated CSS) and the index.php or .htaccess files that protect them. Leave those alone. What remains is usually left over from migrations, FTP uploads and attachments deleted without their sizes. Move those files to a folder outside uploads instead of deleting them, check your site for a week or two, then remove them. If your media is offloaded to S3 or another storage service, this disk comparison does not apply.

Image sizes and the “-scaled” copy

Core WordPress can create six sizes from each image: thumbnail (150 px), medium (300 px), medium_large (768 px), large (1024 px), 1536×1536 and 2048×2048. Themes and plugins add their own. Since WordPress 5.3, an image wider or taller than 2,560 px is also scaled down to a copy such as photo-scaled.jpg, which becomes the “full” size, while the original stays on disk. One large photo can easily become eight or more files.

# Sizes registered right now (core, theme and plugins)
wp media image-size

# Delete files for sizes that are no longer registered (removes files).
# Try one attachment ID first, then all images. Needs WP-CLI 2.11 or later.
wp media regenerate 123 --delete-unknown
wp media regenerate --delete-unknown --yes

Before you remove an old size, search your post content for its dimensions. Posts written in the classic editor often link straight to a file such as photo-640x480.jpg, and that image breaks once the size is gone. Be careful with plain wp media regenerate too: by default it deletes the existing thumbnails before it creates new ones, so if a size’s dimensions have changed, links to the old file names break. Add --skip-delete to keep the old files, or use --only-missing. Never delete the original that sits next to a -scaled file. WordPress makes the other sizes from it.

Build your whitelist before you trash anything

Every scanner has blind spots, so decide what must never be removed and exclude it first. In Media Purge, click Keep to add a file to the Whitelist, or whitelist many files at once with a bulk action. Usual candidates:

  • Images named in theme CSS, Additional CSS or template files (see the next section).
  • Files linked from menus, emails, newsletters, ads or other websites.
  • Images loaded by plugins the scanner doesn’t read, such as sliders, popups and form builders.
  • On WooCommerce stores, variation images, category thumbnails and the placeholder image, which Media Purge’s readme does not list. See how to delete unused WooCommerce product images safely.

Find images used in CSS

A CSS background image is a URL inside a stylesheet, not an attachment ID, so many scanners can’t link it to a Media Library item. Check three places. First, theme and child-theme files:

grep -rhoE "wp-content/uploads/[^\"') ]+" wp-content/themes/ | sort -u

Second, the Customizer’s Additional CSS, which WordPress saves as a custom_css post. Third, plugin and theme settings stored in wp_options. Both queries below are SELECTs and change nothing:

wp db query "SELECT ID, post_title FROM wp_posts WHERE post_type = 'custom_css' AND post_content LIKE '%wp-content/uploads%'"
wp db query "SELECT option_name FROM wp_options WHERE option_value LIKE '%wp-content/uploads%'"

Some plugins save settings as JSON with escaped slashes, so treat the results as a partial list. Page builders are a separate case: Media Purge reads Elementor background images from Elementor’s data, but CSS typed into a custom CSS box is still plain text. More on that in how to remove unused images in Elementor.

PDFs, videos and audio

Non-image files are often the largest items in a library, and they are linked in ways a scan rarely sees: menu links, download buttons, emails and other sites. Export them for review, and check which custom menu links point at uploads:

wp post list --post_type=attachment --post_mime_type=application/pdf --fields=ID,post_title,guid --format=csv > pdfs.csv
wp post list --post_type=attachment --post_mime_type=video --fields=ID,post_title,guid --format=csv > videos.csv

wp db query "SELECT post_id, meta_value FROM wp_postmeta WHERE meta_key = '_menu_item_url' AND meta_value LIKE '%wp-content/uploads%'"

Before you remove a large PDF or video, look for recent requests to its URL in your analytics or server logs. A file nothing on your site links to can still be downloaded every day from an old email or a partner’s page. In Media Purge, you can filter unused media by file type and see storage split into images, videos, audio and documents, so you can start with the biggest files.

CDN caches can hide broken images

A CDN can keep serving a deleted image from its cache, so a missing file may not show up as broken until the cache expires. Cloudflare, for example, caches a 200 response for 120 minutes by default when your server sends no cache headers, and image files often get much longer cache times. Purge the CDN before you test. If you restore a file, purge its URL again, because CDNs can cache the 404 as well (3 minutes by default on Cloudflare).

Media cleanup plugins compared

Disclosure: we make Media Purge. Details for other plugins are from their WordPress.org listings (WP Media Cleanup from Duplicator’s documentation, as it is not on WordPress.org), checked October 2026. Features change, so check each listing before you choose.
Plugin Good at Keep in mind
Media Purge (free) Unused media scan across content, post meta, widgets, Customizer, WooCommerce galleries and Elementor, Divi, WPBakery and Beaver Builder, all free. “Used In” links per file. Internal trash, recoverable for 30 days by default (adjustable). Whitelist, CSV export, duplicate view by MD5 hash. No disk scan for orphan files or thumbnail-size cleanup. Duplicate merge is planned, not available yet. Single-site only.
Media Cleaner (Meow Apps) Mature, widely used; internal trash before permanent delete; can also check the filesystem. Its listing points users with more complex setups to the Pro version for compatibility.
WP Media Cleanup (Duplicator) Removing unused image size variations (thumbnails, medium, large, custom sizes) while keeping originals; 30-day backup before removal; WP-CLI. Paid only, not on WordPress.org. It never deletes original uploads, so whole unused files stay in the library.
A thumbnail tool (e.g. Regenerate Thumbnails) Regenerating the sizes you need after a theme change. Not a usage scanner.
For a detailed side-by-side, read Media Purge vs Media Cleaner, Media Purge vs Media Hygiene or Media Purge vs WP Media Cleanup. If you are replacing Media Cleaner, see our Media Cleaner alternative guide.

How to clean up your media library with Media Purge

  1. Install Media Purge from Plugins → Add New and activate it.
  2. Go to Media → Media Purge and finish the short setup wizard (recent-upload protection, trash retention, WooCommerce scanning).
  3. Click Run Scan Now. The scan is read-only and runs in the background in small batches, so nothing changes on your site.
  4. Review each flagged file’s size and Used In list. Click Keep on anything your theme or another plugin loads.
  5. Trash files in batches and check your pages.
  6. Restore anything you need from the Recovery tab. Files stay there for 30 days by default, and you can change that in Settings.
Download Media Purge free. No scan limits and no file caps.

Keep it clean

  • Resize and compress before upload, or use an image optimisation plugin, and consider WebP for photos.
  • Use descriptive filenames and alt text so files are easy to find (and fewer get re-uploaded).
  • Repeat the review quarterly, or monthly on busy stores and news sites.

FAQ

How do I clean up my WordPress media library without breaking my site?

Back up first, work on staging if possible, and use a scanner that checks post meta and page builder data, not just post content. Spot-check flagged files, move them to a restorable trash, delete in small batches, then crawl for broken images.

Is it safe to delete unattached images?

Not without checking. Logos, site icons, Customizer images and most page builder images are unattached but still in use.

Does WordPress have a trash for media?

Not by default. Deleting from the Media Library is permanent unless you have a backup or use a plugin with its own trash.

Will removing unused images make my site faster?

Not for visitors, since unused files aren’t loaded. It mainly shrinks backups and disk use. For speed, optimise the images your pages actually load.

What about images in CSS or theme files?

Most scanners can’t see image paths written in stylesheets or templates. Search your theme for /wp-content/uploads/ and whitelist those files.

How often should I clean the media library?

Quarterly works for most sites; monthly for stores and sites with many uploads.

How do I find files in wp-content/uploads that aren’t in the Media Library?

Compare a list of every file the Media Library knows about, including generated sizes, with a list of the files in your uploads folder. Anything left over is a possible orphan. The WP-CLI steps in the deeper cleanup section above do this without changing anything. Leave plugin folders such as caches and form uploads alone.

What is a “-scaled” image, and can I delete the original?

Since WordPress 5.3, images larger than 2,560 px are scaled down to a “-scaled” copy that becomes the full size. WordPress keeps the original and makes the other sizes from it, so don’t delete it by hand.

Used Media Purge for this?

Share what worked, or what didn't, in a quick WordPress.org review. It helps other site owners find a safe cleanup tool.

Review Media Purge

Leave a Comment

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

Prove your humanity: 8   +   6   =