Was trying to figure out why my character project .blend had ballooned past 800MB — definitely not 800MB worth of meshes. Turned out I had accumulated nearly 300 animation actions across months of work: retakes, variants, test poses, replaced mocap imports, old facial rigs. All sitting there with fake user flags keeping them alive.
Blender's built-in orphan purge (File → Clean Up → Purge All) only removes data with zero users and no fake user flag. Most of my dead actions had fake_user set from old imports or accidental F-key presses, so the purge did exactly nothing.
Wrote a script to actually surface what's referenced vs what's just floating:
import bpy
def get_referenced_actions():
referenced = set()
for obj in bpy.data.objects:
ad = obj.animation_data
if not ad:
continue
if ad.action:
referenced.add(ad.action.name)
for track in ad.nla_tracks:
for strip in track.strips:
if strip.action:
referenced.add(strip.action.name)
return referenced
def audit_orphaned_actions(purge=False):
referenced = get_referenced_actions()
orphans = [a for a in bpy.data.actions if a.name not in referenced]
print(f"Referenced: {len(referenced)}, Orphaned: {len(orphans)}")
for action in orphans:
print(f" {action.name!r} fake_user={action.use_fake_user} users={action.users}")
if purge:
action.use_fake_user = False
if purge:
bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=False, do_recursive=True)
print("Purge complete.")
# Run audit first to see what you've got
audit_orphaned_actions(purge=False)
# Uncomment when ready to actually purge
# audit_orphaned_actions(purge=True)
Run it from the Scripting editor, check the output, then flip purge=True when you're confident. Save a backup first. Once those actions are gone they're gone — Blender won't ask twice.
Dropped my file from 840MB to 390MB. The remaining 390MB is apparently actual geometry so I can only blame myself for that one.
One gap I haven't closed: this doesn't catch shape key actions or grease pencil animation data, which live in different datablock types. If anyone knows a cleaner way to walk the full bpy.data animation reference graph comprehensively, I'd love to see it.