Skip to main content
Participant
October 2, 2019
Question

Script to Export Contents of all Smart Objects in a Photoshop file

  • October 2, 2019
  • 7 replies
  • 7469 views

I am trying to write a script that will batch export all smart objects as files.

 

Like using the menu ->  Layer/SmartObjects/Export Contents... but does it for every Smart Object is the photoshop file.

 

I have written some code that searches all layers and can determine if it is a Smart Object, but I am stuck on how to export the smart objects content as a file.

 

var oldPath = activeDocument.path;

function ExportSmartObject(layerNode) {
for (var i=0; i<layerNode.length; i++) {

ExportSmartObject(layerNode[i].layerSets);

for(var layerIndex=0; layerIndex < layerNode[i].artLayers.length; layerIndex++) {
var layer=layerNode[i].artLayers[layerIndex];
if (layer.kind == "LayerKind.SMARTOBJECT") {
alert("Smart Object Found")

// Export Smart Object Content

}
}
}
}


ExportSmartObject(app.activeDocument.layerSets);

7 replies

Participating Frequently
August 21, 2024

This thread is so awesome. Everyone contributing and helping. This script worked great for what I wanted. Thanks everyone! Maybe a GitHub would be good for this kind of thing?

Participant
October 10, 2025

Amazing guys. I'd love it if I could export the smart objects as a PSD file with all their layers. Is that possible? I'm an illustrator, so I know nothing about coding.

Stephen Marsh
Community Expert
Community Expert
October 10, 2025
quote

Amazing guys. I'd love it if I could export the smart objects as a PSD file with all their layers. Is that possible? I'm an illustrator, so I know nothing about coding.


By @AlexDantas

 

My script posted earlier in the topic does save to PSD retaining layers.

Participant
April 12, 2024

Thanks so much to all who worked on this script, it is super-helpful! I used the second-to-last iteration as I'm not dealing with pngs and it seems maybe that one had a glitch.

Stephen Marsh
Community Expert
Community Expert
January 4, 2021

I have wrapped the updated script in a try/catch as it would previously silently fail if being run on an unsaved document.

 

 

/*
//community.adobe.com/t5/Photoshop/Script-to-Export-Contents-of-all-Smart-Objects-in-a-Photoshop/td-p/10644877

Original script revised to include smart objects in layer sets (layer groups)... With special thanks to Christoph Pfaffenbichler for the recursive SO processing framework:
feedback.photoshop.com/photoshop_family/topics/rasterize_all_smart_objects_in_a_psd_file_to_shrink_down_its_size

January 3rd 2021: Thanks to schroef for adding handling for duplicate named layers!
*/

#target photoshop

/* Start Open/Saved Document Error Check - Part A: Try */
savedDoc();
function savedDoc() {
  try {
    app.activeDocument.path;
/* Finish Open/Saved Document Error Check - Part A: Try */

/* Main Code Start */
var myDocument = app.activeDocument;
myDocument.suspendHistory("processAllSmartObjects", "processSOLayers(myDocument)");

///////////////////////////////////////////////////////////////////////////////
// Object for timing things in JavaScript
///////////////////////////////////////////////////////////////////////////////
function Timer() {
	// member properties
	this.startTime = new Date();
	this.endTime = new Date();
	
	// member methods
	
	// reset the start time to now
    this.start = function () { this.startTime = new Date() };
	
	// reset the end time to now
    this.stop = function () { this.endTime = new Date() };
	
	// get the difference in milliseconds between start and stop
    this.getTime = function () { return (this.endTime.getTime() - this.startTime.getTime()) / 1000 };
	
	// get the current elapsed time from start to now, this sets the endTime
    this.getElapsed = function () { this.endTime = new Date(); return this.getTime() };
}

// Timer Tom Ruark
// Source: Getter.jsx
var totalTime = new Timer();

///////////////////////////////////////////////////////////////////////////////
// Function: countLayerNames
// Usage:  Count the comps' names collecting duplicates
// Input: collection of comps
// Return: object with names as keys and as values, an object with total count and an index (for incrementing during file naming)
// Source: Layer-Comps-To-Files.jsx
///////////////////////////////////////////////////////////////////////////////
function countLayerNames(list){
    var obj = {};
    for(var i = 0; i<list.length; i++){
        var name = list[i].name;
        if(name in obj){
            obj[name].total += 1;
		} else { 
            obj[name] = {total: 1, nameIndex: 1};
		}
	}
    return obj;
}

////// Function to process all smart objects ////// 
function processSOLayers(theParent) {
    var totalTime = new Timer(); // Tom Ruark > Getter.jsx
    var count = countLayerNames(theParent.layers);
    for (var m = theParent.layers.length - 1; m >= 0; m--) {
        var theLayer = theParent.layers[m];
        
        // apply the funtion to layersets; 
        if (theLayer.typename == "ArtLayer") {
            if (theLayer.kind == LayerKind.SMARTOBJECT) {
                var theVisibility = theLayer.visible;
                myDocument.activeLayer = theLayer;

                // Run the function to save out the layers
                soLayerSaver();

                // Start Main Function
                function soLayerSaver() {

                    app.displayDialogs = DialogModes.NO;
                    var layer = app.activeDocument.activeLayer;
                    var layerName = app.activeDocument.activeLayer.name;
                    var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                    var savePath = activeDocument.path;
                    
                    // check for dupli names
                    var nameEntry = count[theLayer.name];
                    if(nameEntry.total > 1) { // if > 2 then we add index numbers
                        layerName +=  '_' + nameEntry.nameIndex++;
                    }
                    var saveName = File(savePath + "/" + docName + "_" + layerName + "_SmartObjectLayer.psd");

                    function SavePSD(saveFile) {
                        psdSaveOptions = new PhotoshopSaveOptions();
                        psdSaveOptions.embedColorProfile = true;
                        psdSaveOptions.alphaChannels = true;
                        psdSaveOptions.layers = true;
                        app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);
                    }

                    if (layer.kind == "LayerKind.SMARTOBJECT") {
                        app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
                        SavePSD(saveName);
                    } else {
                        // Skip any layers that are not Smart Object layers    
                    }

                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

                }

                // Reset visibility; 
                theLayer.visible = theVisibility;
            }
        } else {
            processSOLayers(theLayer);
        }
    }
    
    alert("Script Time: " + totalTime.getElapsed());
}
/* Main Code Finish */
}

/* Start Open/Saved Document Error Check - Part B: Catch */
  catch (err) {
    alert("An image must be open and saved before running this script!");
  }
}
/* Finish Open/Saved Document Error Check - Part B: Catch */

 

 

Participant
October 27, 2021

Fantastic. Just what I needed when I found that Smartobject didn't export fully but cropped, if they were bigger than the visible canvas, when using Quick Export or Export As or any of the other options. So I made tiny updates to the script to export png where the filename is just the layername, and deactivated the timer. Thanks!

 

/*MODIFIED to export png using layer name only, deactivated Timer
//community.adobe.com/t5/Photoshop/Script-to-Export-Contents-of-all-Smart-Objects-in-a-Photoshop/td-p/10644877

Original script revised to include smart objects in layer sets (layer groups)... With special thanks to Christoph Pfaffenbichler for the recursive SO processing framework:
feedback.photoshop.com/photoshop_family/topics/rasterize_all_smart_objects_in_a_psd_file_to_shrink_down_its_size

January 3rd 2021: Thanks to schroef for adding handling for duplicate named layers!
*/

#target photoshop

/* Start Open/Saved Document Error Check - Part A: Try */
savedDoc();
function savedDoc() {
try {
app.activeDocument.path;
/* Finish Open/Saved Document Error Check - Part A: Try */

/* Main Code Start */
var myDocument = app.activeDocument;
myDocument.suspendHistory("processAllSmartObjects", "processSOLayers(myDocument)");

///////////////////////////////////////////////////////////////////////////////
// Object for timing things in JavaScript
///////////////////////////////////////////////////////////////////////////////
function Timer() {
// member properties
this.startTime = new Date();
this.endTime = new Date();

// member methods

// reset the start time to now
this.start = function () { this.startTime = new Date() };

// reset the end time to now
this.stop = function () { this.endTime = new Date() };

// get the difference in milliseconds between start and stop
this.getTime = function () { return (this.endTime.getTime() - this.startTime.getTime()) / 1000 };

// get the current elapsed time from start to now, this sets the endTime
this.getElapsed = function () { this.endTime = new Date(); return this.getTime() };
}

// Timer Tom Ruark
// Source: Getter.jsx
var totalTime = new Timer();

///////////////////////////////////////////////////////////////////////////////
// Function: countLayerNames
// Usage: Count the comps' names collecting duplicates
// Input: collection of comps
// Return: object with names as keys and as values, an object with total count and an index (for incrementing during file naming)
// Source: Layer-Comps-To-Files.jsx
///////////////////////////////////////////////////////////////////////////////
function countLayerNames(list){
var obj = {};
for(var i = 0; i<list.length; i++){
var name = list[i].name;
if(name in obj){
obj[name].total += 1;
} else {
obj[name] = {total: 1, nameIndex: 1};
}
}
return obj;
}

////// Function to process all smart objects //////
function processSOLayers(theParent) {
//var totalTime = new Timer(); // Tom Ruark > Getter.jsx
var count = countLayerNames(theParent.layers);
for (var m = theParent.layers.length - 1; m >= 0; m--) {
var theLayer = theParent.layers[m];

// apply the funtion to layersets;
if (theLayer.typename == "ArtLayer") {
if (theLayer.kind == LayerKind.SMARTOBJECT) {
var theVisibility = theLayer.visible;
myDocument.activeLayer = theLayer;

// Run the function to save out the layers
soLayerSaver();

// Start Main Function
function soLayerSaver() {

app.displayDialogs = DialogModes.NO;
var layer = app.activeDocument.activeLayer;
var layerName = app.activeDocument.activeLayer.name;
var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var savePath = activeDocument.path;

// check for dupli names
var nameEntry = count[theLayer.name];
if(nameEntry.total > 1) { // if > 2 then we add index numbers
layerName += '_' + nameEntry.nameIndex++;
}
var saveName = File(savePath + "/" + layerName + ".png");

function SavePng(saveFile) {
pngSaveOptions = new PNGSaveOptions();
pngSaveOptions.compression = 0;
pngSaveOptions.interlaced = false;
app.activeDocument.saveAs(saveFile, pngSaveOptions, true, Extension.LOWERCASE);
}

if (layer.kind == "LayerKind.SMARTOBJECT") {
app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
SavePng(saveName);
} else {
// Skip any layers that are not Smart Object layers
}

app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

}

// Reset visibility;
theLayer.visible = theVisibility;
}
} else {
processSOLayers(theLayer);
}
}

//alert("Script Time: " + totalTime.getElapsed());
}
/* Main Code Finish */
}

/* Start Open/Saved Document Error Check - Part B: Catch */
catch (err) {
alert("An image must be open and saved before running this script!");
}
}
/* Finish Open/Saved Document Error Check - Part B: Catch */

Participating Frequently
April 9, 2024

Hi - the last code creates very big files (100mb png) 

and it crashes photoshop on pdf or AI embedded files. 

;(

 

Stephen Marsh
Community Expert
Community Expert
March 16, 2020

This updated code will process standard layers and layers inside layer sets or nested layer sets. All of the previous limitations still apply, such as duplicate layer names are not supported.

 

/*
//community.adobe.com/t5/Photoshop/Script-to-Export-Contents-of-all-Smart-Objects-in-a-Photoshop/td-p/10644877

Note: There is no error checking for duplicate layer names (therefore the lowest layer in the stack with the same name would be saved).

Original script revised to include smart objects in layer sets (layer groups)... With special thanks to Christoph Pfaffenbichler for the recursive SO processing framework:
feedback.photoshop.com/photoshop_family/topics/rasterize_all_smart_objects_in_a_psd_file_to_shrink_down_its_size
*/

#target photoshop

var myDocument = app.activeDocument;
myDocument.suspendHistory("processAllSmartObjects", "processSOLayers(myDocument)");

////// Function to process all smart objects ////// 
function processSOLayers(theParent) {
    for (var m = theParent.layers.length - 1; m >= 0; m--) {
        var theLayer = theParent.layers[m];
        
        // apply the funtion to layersets; 
        if (theLayer.typename == "ArtLayer") {
            if (theLayer.kind == LayerKind.SMARTOBJECT) {
                var theVisibility = theLayer.visible;
                myDocument.activeLayer = theLayer;

                // Run the function to save out the layers
                soLayerSaver();

                // Start Main Function
                function soLayerSaver() {

                    app.displayDialogs = DialogModes.NO;
                    var layer = app.activeDocument.activeLayer;
                    var layerName = app.activeDocument.activeLayer.name;
                    var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                    var savePath = activeDocument.path;
                    var saveName = File(savePath + "/" + docName + "_" + layerName + "_SmartObjectLayer.psd");

                    function SavePSD(saveFile) {
                        psdSaveOptions = new PhotoshopSaveOptions();
                        psdSaveOptions.embedColorProfile = true;
                        psdSaveOptions.alphaChannels = true;
                        psdSaveOptions.layers = true;
                        app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);
                    };

                    if (layer.kind == "LayerKind.SMARTOBJECT") {
                        app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
                        SavePSD(saveName);
                    } else {
                        // Skip any layers that are not Smart Object layers    
                    }

                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

                }

                // Reset visibility; 
                theLayer.visible = theVisibility;
            };
        } else {
            processSOLayers(theLayer)
        }
    }
    return
};
schroef
Inspiring
January 2, 2021

@Stephen Marsh 

 

I hope you dont mind. I added something parts from "Layer Comps to Files" so when there are layers with the same name it will index those. I added a little timer i found in one of Tom Ruarks script, so i could time the difference. I dint really notice a big impact of the extra check. You can find that check in the beginning of the main function.

 

Below you see layers with the same name get an index, therefor they wont be overwritten. I thought that would be nice

 

/*
//community.adobe.com/t5/Photoshop/Script-to-Export-Contents-of-all-Smart-Objects-in-a-Photoshop/td-p/10644877

Note: There is no error checking for duplicate layer names (therefore the lowest layer in the stack with the same name would be saved).

Original script revised to include smart objects in layer sets (layer groups)... With special thanks to Christoph Pfaffenbichler for the recursive SO processing framework:
feedback.photoshop.com/photoshop_family/topics/rasterize_all_smart_objects_in_a_psd_file_to_shrink_down_its_size
*/

#target photoshop

var myDocument = app.activeDocument;
myDocument.suspendHistory("processAllSmartObjects", "processSOLayers(myDocument)");


///////////////////////////////////////////////////////////////////////////////
// Object for timing things in JavaScript
///////////////////////////////////////////////////////////////////////////////
function Timer() {
	// member properties
	this.startTime = new Date();
	this.endTime = new Date();
	
	// member methods
	
	// reset the start time to now
	this.start = function () { this.startTime = new Date(); }
	
	// reset the end time to now
	this.stop = function () { this.endTime = new Date(); }
	
	// get the difference in milliseconds between start and stop
	this.getTime = function () { return (this.endTime.getTime() - this.startTime.getTime()) / 1000; }
	
	// get the current elapsed time from start to now, this sets the endTime
	this.getElapsed = function () { this.endTime = new Date(); return this.getTime(); }
}

// Timer Tom Ruark
// Source: Getter.jsx
var totalTime = new Timer();


///////////////////////////////////////////////////////////////////////////////
// Function: countLayerNames
// Usage:  Count the comps' names collecting duplicates
// Input: collection of comps
// Return: object with names as keys and as values, an object with total count and an index (for incrementing during file naming)
// Source: Layer-Comps-To-Files.jsx
///////////////////////////////////////////////////////////////////////////////
function countLayerNames(list){
    var obj = {};
    for(var i = 0; i<list.length; i++){
        var name = list[i].name;
        if(name in obj){
            obj[name].total += 1;
		} else { 
            obj[name] = {total: 1, nameIndex: 1};
		}
	}
    return obj;
}

////// Function to process all smart objects ////// 
function processSOLayers(theParent) {
    var totalTime = new Timer(); // Tom Ruark > Getter.jsx
    var count = countLayerNames(theParent.layers);
    for (var m = theParent.layers.length - 1; m >= 0; m--) {
        var theLayer = theParent.layers[m];
        
        // apply the funtion to layersets; 
        if (theLayer.typename == "ArtLayer") {
            if (theLayer.kind == LayerKind.SMARTOBJECT) {
                var theVisibility = theLayer.visible;
                myDocument.activeLayer = theLayer;

                // Run the function to save out the layers
                soLayerSaver();

                // Start Main Function
                function soLayerSaver() {

                    app.displayDialogs = DialogModes.NO;
                    var layer = app.activeDocument.activeLayer;
                    var layerName = app.activeDocument.activeLayer.name;
                    var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
                    var savePath = activeDocument.path;
                    
                    // check for dupli names
                    var nameEntry = count[theLayer.name];
                    if(nameEntry.total > 1) { // if > 2 then we add index numbers
                        layerName +=  '_' + nameEntry.nameIndex++;
                    }
                    var saveName = File(savePath + "/" + docName + "_" + layerName + "_SmartObjectLayer.psd");

                    function SavePSD(saveFile) {
                        psdSaveOptions = new PhotoshopSaveOptions();
                        psdSaveOptions.embedColorProfile = true;
                        psdSaveOptions.alphaChannels = true;
                        psdSaveOptions.layers = true;
                        app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);
                    };

                    if (layer.kind == "LayerKind.SMARTOBJECT") {
                        app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
                        SavePSD(saveName);
                    } else {
                        // Skip any layers that are not Smart Object layers    
                    }

                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

                }

                // Reset visibility; 
                theLayer.visible = theVisibility;
            };
        } else {
            processSOLayers(theLayer)
        }
    }
    
    alert("Script Time: " + totalTime.getElapsed())
};

 

 

Stephen Marsh
Community Expert
Community Expert
January 3, 2021

No, I don't mind if you improve my scripts! Can I notify you whenever I write a script and ask for you to improve it? I am of course (mostly) joking...

 

 

Stephen Marsh
Community Expert
Community Expert
March 15, 2020

Thanks for the bump, I just realised that I never updated my previous post with the updated code to loop over all layers:

 

//community.adobe.com/t5/Photoshop/Script-to-Export-Contents-of-all-Smart-Objects-in-a-Photoshop/td-p/10644877
//Script to Export Contents of all Smart Objects in a Photoshop file
// Note: There is no error checking for duplicate layer names (therefore the lowest layer in the stack with the same name would be saved).

#target photoshop  

// Start Loop over all layers
  
var doc = app.activeDocument;  
var layerVisble  
  
doc.activeLayer = doc.layers[0];  
  
for(var i=0;i<doc.layers.length;i++){  
    doc.activeLayer = doc.layers[i];  
    layerVisible = doc.activeLayer.visible;  
    doc.activeLayer.visible = true;  
    run ();  
    doc.activeLayer.visible = layerVisible;  
    }  

// End Loop over all layers

// Start Main Code
function run(){  

app.displayDialogs = DialogModes.NO; 
var layer = app.activeDocument.activeLayer;
var layerName = app.activeDocument.activeLayer.name;
var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var savePath = activeDocument.path;
var saveName = File(savePath + "/" + docName + "_" + layerName + "_SmartObjectLayer.psd" );

function SavePSD(saveFile){    
psdSaveOptions = new PhotoshopSaveOptions();    
psdSaveOptions.embedColorProfile = true;    
psdSaveOptions.alphaChannels = true;     
psdSaveOptions.layers = true;     
app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);    
}; 

if (layer.kind == "LayerKind.SMARTOBJECT") {
app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
SavePSD(saveName); 
}
else
{
// Skip any layers that are not Smart Object layers    
}

app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

}

// End Main Code
Stephen Marsh
Community Expert
Community Expert
March 15, 2020

Being new to scripting, my script is very simple... 

 

The main file that holds the SO layers must be saved, there is no error checking in the script for this.

 

If there are layer sets/groups, then the file will close and nothing will be saved – there is no error checking in the script for this.

 

The script simply saves a PSD version of each smart object layer to the original document path. If your main file is on the desktop, then that is where each smart object will be saved. This behaviour is easy to change if desired. The SO files could be saved as a PSD to a folder of your choice via a window to select the save folder. Or the files could be saved to a fixed path/location. Or the files could be saved into a sub-folder in the folder where the main file is currently saved.

 

The saved PSD files will have the following suffix added to the layer name:

 

_SmartObjectLayer.psd

 

As mentioned in the script comments, if you have multiple SO layers with exactly the same name, then only the lowest layer in the layer stack would be saved.

hakzter
Known Participant
March 16, 2020

Many thanks for your work Stephen!

Can you please clarify "If there are layer sets/groups, then the file will close and nothing will be saved – there is no error checking in the script for this."

You mean if I have groups like this?

Stephen Marsh
Community Expert
Community Expert
October 3, 2019

Being new to scripting, I would have done it as below... This code is only for the active layer, it would need to be looped/iterated over all layers. Note: There is no error checking for duplicate layer names (therefore the lowest layer in the stack with the same name would be saved).

 

 

 

 

 

#target photoshop
// Save Active Smart Object Layer as PSD
app.displayDialogs = DialogModes.NO; 
var layer = app.activeDocument.activeLayer;
var layerName = app.activeDocument.activeLayer.name;
var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var savePath = activeDocument.path;
var saveName = File(savePath + "/" + docName + "_" + layerName + "_SmartObjectLayer.psd" );

function SavePSD(saveFile){    
psdSaveOptions = new PhotoshopSaveOptions();    
psdSaveOptions.embedColorProfile = true;    
psdSaveOptions.alphaChannels = true;     
psdSaveOptions.layers = true;     
app.activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE);    
}; 

if (layer.kind == "LayerKind.SMARTOBJECT") {
app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
SavePSD(saveName); 
}
else
{
// Skip any layers that are not Smart Object layers    
}

app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

 

 

 

 

 

 

Stephen Marsh
Community Expert
Community Expert
October 5, 2019

I can’t believe how hard it is proving to find easily adaptable code examples to loop/iterate over all layers in a file.

 

OK, I managed to graft on some code that works, the issue was ESTK throwing up an error that does not happen when the script is run directly from Photoshop.

Kukurykus
Legend
October 2, 2019

 

sTT = stringIDToTypeID; (dsc = new ActionDescriptor())
.putPath(sTT('null'), File('~/desktop/' + i + '.psb'))
executeAction(sTT('placedLayerExportContents'), dsc)