How detection works
A scan looks at one attachment at a time. It collects every name that file answers to, runs ten detectors over the places a reference can hide, and records what each one found. Any confirmed or possible reference makes the file used. Only a file with nothing at all against it lands on the Unused list.
What the file is known by
Before anything is searched for, the scan collects the file's identity: its attachment ID, its stored path, the original file where one was kept, every registered size (photo-300x200.jpg), the -scaled variant, and the alternate-format copies recorded in the attachment's metadata — the WebP and AVIF versions of the original and of each size.
So a reference to a thumbnail, or to the WebP of a thumbnail, resolves back to the original attachment and keeps it. Matching is on basenames, not URLs, which is also why a library served from external storage still matches: the filename is in the URL wherever the URL points.
Where it looks
| Detector | Reads | Finds, among other things |
|---|---|---|
| Post meta | postmeta |
Custom fields — image, gallery and file values, including serialized values and repeater/flexible sub-fields, verified against the field-key meta; featured images; product galleries; page-builder data |
| Post content | posts |
Image and gallery blocks, wp-image-N classes, [gallery] and [playlist], page-builder shortcodes carrying an ID (image="123"), raw file URLs, excerpts, custom-field values stored inside block markup, and unsaved edits held in autosaves |
| Options | options |
Site icon, custom logo, widgets, customizer settings and theme mods — serialized or JSON, at any depth |
| Term meta | termmeta |
Fields on categories, tags and custom taxonomies |
| Term description | term_taxonomy |
The description of a category, tag or product category — an <img> or file link in it, a link to the file's attachment page, or an ID parked there as stored data |
| User meta | usermeta |
Fields on profiles |
| Comments | comments, commentmeta |
A file linked in a reply, review photos |
| Recent upload | posts |
Files uploaded inside the grace window (24 hours by default) |
| Attached | posts |
The Uploaded to relation — recorded as information only |
| File claim | posts, postmeta |
Not a reference: another library entry standing on the same physical file — its own attached file, or a file its metadata names as the original or a size — which deleting this entry would take with it. Confirmed, so it blocks deletion |
IDs and URLs are found inside JSON stored under any key, including JSON nested inside serialized settings, and non-ASCII filenames are matched in their percent-encoded and JSON-escaped spellings as well as plainly.
Confidence, and what each level does
Every reference carries one of three confidence levels, and the meta box shows it:
- confirmed — an unambiguous reference. Counts as used.
- possible — a match that is real but not provably a content reference; a reference from a trashed post or comment, for instance, because a trashed object can be restored. Counts as used.
- record only — not a content reference — the Uploaded to relation. Shown as evidence, never counts as usage. That unreliable signal is exactly what this plugin exists to replace.
Each reference is also labelled with the kind of thing it is — Custom field, Block field, Featured image, Shortcode attribute, Image in content, Gallery, File URL, Widget, Customizer setting, Unsaved edit, Uploaded recently, and so on — with a link to the post, term, user, comment or Customizer it was found in.
Deliberately wrong in one direction
Deleting media is destructive, so where the scan cannot be certain it keeps the file.
- Ambiguity counts as used. A bare attachment ID in a meta key the plugin has never seen keeps the file.
- Matches are boundary-checked. Attachment 123 is never matched by
wp-image-1234, andphoto.jpgis never matched bymy-photo.jpg. - A reference in the trash still counts. A trashed post or comment can be restored, so the files it uses are kept.
- Files uploaded in the last 24 hours count as in use. An editor may still be placing them, so a clean-up never removes work in progress. The window is configurable, including down to zero — see Extending.
- Unsaved edits count; old revisions do not. An autosave holds an edit nobody has saved yet, so it protects its files. A file removed from a post in a past revision is meant to become findable.
- A saved draft protects its images —
draft,pending,privateandfutureare all read. Onlyauto-draftis skipped: a post that has never been saved has no reference anywhere in the database for any scanner to find, which is the case the upload grace covers.
What it cannot see, said plainly
The scan reads posts, post meta, options, term meta, term descriptions, user meta, comments and comment meta. Anything outside those tables is outside its reach, and the blind spot most worth knowing about is inside your own database:
References kept in a plugin's own custom database tables. Form entries, slider records, page-builder tables — any plugin that stores attachment IDs or file URLs in a table of its own shape. No query-based scanner can find a reference in a table it has never seen. If a plugin on your site works that way, check what it holds before deleting.
The same applies to references hard-coded in theme or plugin files, references held by an external service, references on other sites of a multisite network (network-wide options included), and the legacy Links manager.
Multisite is untested. There is no multisite-specific code in the plugin: each site's library would be scanned from that site's own admin, which is how it is expected to behave, but nothing here proves it and the uninstall routine clears the current site only. Treat a network install as unsupported for now. Either way, another site of the network embedding this site's file URL is not detected.
What the verdicts are a statement about
A scan reads the site's content once, in a first phase, and then answers file by file out of that reading. On a large library the second phase runs for hours after the first — so the verdicts describe the site as it was read at the start of the scan, not as it is this second. Three consequences, and the plugin is explicit about each:
- Both tabs date the reading, and the Scan tab adds Content has changed since — this may be stale when something has been saved after it. The exportable evidence report [Pro feature] carries the same moment as a
read_atcolumn. - A file uploaded after the reading was taken is asked live rather than answered out of it, because the reading holds nothing for it and silence there is indistinguishable from no references found.
- A reference added to existing content while the scan was running is not — it is picked up by the next scan. What stands between that and a lost file is the re-check: every file is re-read against the site as it is in the instant before it is deleted, and a file that has become used is skipped.
The evidence that is stored
Every reference found is recorded against the attachment, for used and unused files alike, with its detector, the object it lives in, the field or option it was found in, the kind of match and its confidence. The first twenty are kept, confirmed ones first; the true total is stored alongside them, and the badge above the list carries the number of confirmed places found — so a heavily-referenced file reads Used (43 references) over the twenty it shows, rather than letting twenty stand in for the count.
To see all of them for one file, use the Used view [Pro feature], which re-reads that single file on demand.
Next: Deleting safely.