If you have been running a WordPress site for a year or more, there is a good chance your media library holds files no page is actually using. Leftover thumbnails from deleted posts, images swapped out during a redesign, assets from a builder experiment that never shipped. They accumulate quietly.
The problem is not finding them. The problem is deleting the wrong one. According to the HTTP Archive Web Almanac, the median desktop home page loads 19 images, and page weight has grown over 110% in the past decade. Httparchive Most of those images are served correctly. A small number are orphaned in the database, doing nothing. Telling the two apart reliably is what this guide is about.
This guide walks you through how to find, verify and delete unused media files safely, in that exact order.
What does “unused” actually mean in WordPress?
Before touching anything, it is worth understanding what WordPress tracks and what it does not.
In WordPress, every uploaded file is registered as an attachment: a post type with its own database entry. When you delete a page or a post, WordPress does not automatically remove the media that was used in it. The files stay on the server, the database records remain and nothing points to them anymore. These are the cleanest candidates for deletion.
The trap is the word “unattached.” WordPress marks an image as unattached when it has no parent post relationship in the database, typically because it was uploaded directly to the media library rather than from within a post’s edit screen. An unattached image can still be actively displayed on dozens of pages, in a theme header, a widget, a builder block or a custom field. As noted in the WordPress developer documentation, the attachment relationship tracks the upload origin, not active usage. Deleting based on the unattached filter alone is one of the most common ways cleanups go wrong.
If you want to understand in detail why the unattached filter is not a reliable signal and how to build a candidate list before you delete anything, see: WordPress find unused media: the safe way to identify orphaned files.
Where can images hide on a WordPress site?
The WordPress media library only shows what it was designed to track. Images are actively used in far more places:
- Post and page content (classic editor and Gutenberg block attributes)
- Page builder settings (Elementor sections, Divi modules, background images)
- Theme customiser options (site logo, background image, header)
- Widget content and sidebar HTML
- Custom fields and ACF metadata (including repeaters and option pages)
- WooCommerce product galleries and variant images
- Plugin settings, sliders and gallery shortcodes
- Custom CSS and inline styles
A file can be in none of those locations, or in all of them. WordPress itself does not give you a unified view across all of them. That is the gap the safe deletion workflow addresses.
What should you check before deleting any media?
Media deletion in WordPress is permanent. There is no native trash for media attachments. One wrong click and the file is gone from every post, page or template it appeared on, replaced by a broken image icon. Work through this checklist before any cleanup session.
- Full backup complete, covering both files and database
- Restoration tested (at minimum, confirm the backup opens and is not empty)
- Staging environment used if the site is in production
- Candidate list ready: files identified for deletion, not yet deleted
- Starting with a small batch (10 to 20 files, not hundreds)
- Key pages noted for post-delete verification
The backup is not optional. Every other step depends on having a recovery point if something goes wrong.
How do you find unused media candidates?
The goal of this step is to build a candidate list, not to delete. A candidate is a file you suspect is unused, not one you have confirmed.
Method A: the native filter (quick first pass)
In the media library, switch to list view and use Filter by type â Unattached. This surfaces files with no parent post relationship in the database.
Use this as a starting point only. Every file in this list needs to be verified before it goes near a delete button.
Method B: a plugin with a real usage index (recommended)
At any volume above a few dozen files, manually verifying the unattached list is not practical. More importantly, it leaves blind spots the native filter cannot address: builder blocks, ACF fields, custom options and theme settings.
Mediapapa builds a usage index that tracks every file across all of these locations, covering posts, ACF fields, option tables, Gutenberg block attributes, Elementor data and more. When it surfaces a file as unused, it has checked your entire site, not just the fields WordPress exposes natively.
The Library Health dashboard then groups findings by priority, so you are not staring at a flat list of thousands of files trying to decide where to start.
Mediapapa also adds Deletion Warnings: if you attempt to delete a file that is still in use somewhere, it stops you before the deletion executes and shows you exactly where the file is referenced. WordPress has no equivalent. A native delete is immediate and silent.
Method C: WP-CLI (for large or developer-managed sites)
WP-CLI is the appropriate tool for high-volume sites: WooCommerce stores with thousands of product images, news archives, large multisite installs. It lets you run media queries as background processes without browser timeouts.
wp media list --post_status=any --fields=ID,post_title,attachment_url
This produces a raw list of registered attachments to cross-reference against your content. Blind spots include serialised data, theme customiser options and hardcoded URLs in templates, which require separate checks.
How do you verify a candidate is actually unused?
This is the step most guides skip, and the step that prevents broken pages.
For each candidate file, run the following proof check.
The proof workflow
Check the file URL in your content. Copy the full attachment URL from the media details panel. In the WordPress block editor, use the search function. In the database, search wp_posts.post_content for the URL string.
Check post meta and custom fields. If you use ACF, theme options or any plugin that stores data in wp_postmeta or wp_options, a simple content search will not surface these. This is where the native method has its most significant blind spot.
Check the theme customiser. Open Appearance â Customise and look through logo, background image and header settings. These are stored in wp_options under theme_mods_{themename} and will not appear in a content search.
Check widget content. Go to Appearance â Widgets and scan for any image blocks or HTML widgets referencing the file.
Check builder settings. If you use Elementor, Divi or similar tools, open a few key pages and inspect section background images, image widgets and popup triggers. Builders often store these references in serialised data that is invisible to a plain text search.
Special cases worth handling separately
Featured images. A featured image is stored in wp_postmeta as _thumbnail_id, not in post content. It will appear as unattached in the media library filter even if it is the hero image on your homepage.
PDFs and downloadable documents. A PDF with no database parent could be linked from an email newsletter, an external site or a pinned social post. Deletion removes the source file immediately. Check referrer data in your analytics before acting.
WooCommerce product images. Variant images, gallery images and product thumbnails are stored in product meta, not post content. A standard content search will not find them. Always use a tool with WooCommerce-aware scanning for shops.
How do you delete media files safely in WordPress?
Once you have a verified list of files confirmed unused across all the locations above, you can proceed with deletion. The method matters as much as the list.
Work in small batches
Delete 10 to 20 files at a time, then check your site before continuing. This is the only way to isolate a mistake before it multiplies. A bulk delete of 500 files leaves you no way to identify which one caused a broken image three posts later.
Verify the site after each batch
After each deletion pass, check the following pages manually:
- Homepage
- Main category or archive pages
- Top-traffic posts (use Google Analytics or Search Console to identify them)
- Any page that uses the header, footer or global template components
- Checkout and product pages if you run WooCommerce
What to look for: missing images, broken image icons, layout shifts from missing background images.
Check for 404 image errors
After the first batch, open your browser’s developer tools on a few key pages and check the Network tab filtered to images. Any 404 response on an image URL indicates a deletion that broke something. Catching these early makes correction straightforward.
Do not forget thumbnails and size variants
When WordPress deletes an attachment, it should cascade the deletion to all generated size variants. Most cleanup plugins handle this correctly. If you delete files manually via the WordPress admin or FTP, verify that the variants (image-300x200.jpg, image-1024x768.jpg and so on) are also removed.
CDN and caching
If you serve images through a CDN, deleting the source file does not automatically purge the cached version at the edge. After a cleanup session, purge your CDN cache manually. Until you do, posts and pages may appear intact while actually serving files that no longer exist on the origin.
What about leftover files on the server?
Deleting a media attachment in WordPress removes the database entry and, in most cases, the file itself. In some situations, however, files remain in /wp-content/uploads/ after the attachment record is gone.
When files stay after deletion
This happens most often after plugin migrations, CDN sync errors, bulk import tools that bypassed the WordPress media registration flow or manual FTP uploads that were never registered as attachments. These files exist on the server but have no corresponding entry in wp_posts, meaning WordPress is entirely unaware of them.
Before removing anything at the server level, confirm that a file has no corresponding attachment record and is not referenced anywhere in your database. Deleting files directly via FTP or your host’s file manager is irreversible and bypasses any plugin safety layer.
How to identify true server orphans
The most reliable approach is to compare your /wp-content/uploads/ directory against the list of registered attachment URLs. WP-CLI makes this practical for large sites:
wp media list --post_status=any --fields=attachment_url --format=csv
Export that list, then compare it against your uploads folder. Files present on the server but absent from the list are candidates for review. Verify each one before acting: a file absent from the attachment list could still be hardcoded into a theme template or referenced in a plugin configuration file.
After server-level cleanup
Run a broken link scan across your site after any server-level file removal. Tools such as Google Search Console (under Coverage) or a plugin-based link checker will surface any 404 responses caused by files that were still in use somewhere.
How do you prevent the next round of accumulation?
A single cleanup is worth doing. A cleanup paired with a governance routine is effortless to maintain.
According to the HTTP Archive Web Almanac, JPEG still accounts for nearly a third of all images served on the web, while adoption of modern formats like WebP has grown 34% since 2022 and AVIF has seen nearly four times more usage. Httparchive The format cleanup is one half of what a media governance routine addresses. The other half is preventing unused files from accumulating in the first place.
Four habits that keep the library clean
Name files before uploading. team-photo-2025-homepage.jpg is findable. IMG_4892.jpg is not, and it will be the one you cannot identify two years later.
Scan before re-uploading. Duplicate images are one of the most reliable sources of library bloat. Use the media library search to check whether an asset you need already exists before uploading a new version.
Delete media when you delete content. When removing a post or a product for good, take 60 seconds to check whether its featured image and gallery images are used anywhere else. If not, delete them in the same session.
Use a quarterly routine. Once per quarter: run an unused media scan, review the Library Health score in Mediapapa, delete confirmed candidates in small batches. A regular cadence keeps the volume of each session manageable and the library in good shape long-term.
FAQ
No. Unattached means an image has no parent post relationship in the WordPress database, typically because it was uploaded directly to the media library rather than from within a post’s edit screen. It can still be actively displayed in a widget, a theme setting, a builder block or a custom field. Always verify before deleting.
The most likely cause is that the image was in use somewhere the deletion check did not cover: a builder background image, a widget, a custom field or a theme option. WordPress does not warn you when you delete a file that is still referenced. This is exactly what Deletion Warnings in Mediapapa prevents.
Copy the full file URL from the media details panel and search for it in your post content. For a complete picture including custom fields, theme options and builder data, use a plugin with a proper usage index. Native WordPress search covers only post_content and will miss references stored elsewhere in the database.
Both builders store image references in their own data formats, often serialised in wp_postmeta. A standard WordPress content search will not surface these references. Mediapapa’s usage index covers Elementor blocks and options. For Divi, verify manually in the builder before deleting any candidate that could be a background or section image.
Not directly. Unused files in /wp-content/uploads/ are not rendered on the front end and do not affect page speed or crawl budget on their own. The real gains come from the habits that accompany a cleanup: removing oversized images, converting to WebP or AVIF and completing missing alt texts, all of which affect page performance and accessibility. According to the HTTP Archive Web Almanac 2024, over 71% of desktop pages are missing image-loading properties entirely â alt text and format gaps are where the SEO work actually lives.
Not through WordPress itself. Once permanently deleted, there is no native recovery path. This is why taking a full backup before any cleanup session is the first item on the checklist. If you use a plugin with a soft-delete or staging workflow, recovery is possible within the retention window. Check your plugin’s documentation for details.
No plugin covers 100% of edge cases. Files hardcoded into theme templates, referenced in external email newsletters or linked from third-party sites are outside the scope of any database-level scan. The proof workflow in Step 2 exists precisely to catch these cases before deletion.
A quarterly routine is enough for most sites. High-volume sites, active news publications and WooCommerce stores with frequent product turnover benefit from a monthly pass. Tracking your Library Health score over time gives you an early signal when accumulation is building before it becomes a maintenance problem.
Additional reading
- Use image and file attachments â WordPress.org official documentation on how attachments work in WordPress
- Media Library screen â WordPress.org official reference for the media library admin interface
- Tracking media usage and Deletion Warnings â how Mediapapa’s usage index and Deletion Warnings work
- Understanding Media Scores in Mediapapa â Media Score and Library Health explained
- Detecting and removing duplicate images â the deduplication workflow in Mediapapa




