The task that finally broke me was a crop-and-resize job. Two hundred product images, each one needing a 2000x2000px square crop, a white background fill, and an export at three different sizes for three different platforms. I did the first forty by hand before I stopped, stared at the screen, and did the math. At my current pace, this was going to eat my entire Thursday.

That afternoon I learned enough JavaScript to write my first Photoshop automation script. It took about four hours to build and test. It ran the remaining 160 images in eleven minutes. I have not manually repeated that task since, and that was fifteen years ago.

What Actions Can’t Do (And Why That Ceiling Exists)

Photoshop actions are brilliant for linear, repeatable sequences. You hit record, do the thing, stop recording, and you have a reusable macro. If you want to apply the same curve adjustment and sharpen to a hundred files, actions get you there. But actions are rigid. They don’t make decisions.

An action can’t look at a file and say “this one is landscape, so I’ll crop differently.” It can’t read a filename, parse out a SKU number, and route the file to a specific folder. It can’t skip a step based on whether a layer already exists. It records what you did, and it plays that back, every time, in exactly the same order. The moment your inputs vary even slightly, the action either fails or produces garbage.

This is where scripting, specifically ExtendScript or the newer UXP-based JavaScript API, picks up the load. Scripts are programs. They have conditional logic, loops, file system access, and the ability to interact with Photoshop’s object model directly. An action automates a gesture. A script automates a decision.

Building a Script That Actually Does Something Useful

Here is a real-world pattern I use constantly for e-commerce clients: a folder-watch batch script that processes incoming product shots to four export specs in one pass.

The script opens every TIFF in a source folder, checks canvas dimensions, smart-resizes to 3000x3000px using bicubic sharper if downsampling, runs a linked action set (white balance correction, shadow lift to 15, output sharpening at 0.5px radius), then exports four versions: a full-size TIFF for archive, a 2000px JPEG at quality 10 for the client’s CMS, a 1000px JPEG for marketplace listings, and a 500px WebP for mobile. Each version drops into its own subfolder, named with the original filename plus a suffix like _2k, _1k, _500w.

The script itself is about 90 lines of JavaScript. The action it calls does the heavy color work. The two together are what makes the system actually reliable. The action handles the subjective, repeatable adjustments. The script handles the routing, resizing logic, and export parameters. Neither one works as well alone.

To connect them, use app.doAction("ActionName", "ActionSetName") inside your script. This is the line most people miss. You can call any saved action from within a script, which means you can build your color work visually, save it as an action, and then let your script drive when and how it gets applied.

The Spreadsheet I’ve Been Keeping for Eight Years

I track every automation I build in a spreadsheet. Current tally: roughly 2,400 hours saved since I started logging. That number sounds theatrical but it comes from conservative estimates, actual file counts, and timed comparisons I ran on the same job done manually versus automated. The color-coded rows are organized by client type, task category, and year. Ad agency retouching is yellow. E-commerce batch work is green. The jobs that would have been physically impossible to deliver on time without automation are red. There are a lot of red rows.

The one that still stands out happened early in my consultancy, before I had staff. An ad agency called on a Friday afternoon with 500 product shots for a retail catalog. They needed web-ready deliverables by Monday morning. I had a Saturday and a Sunday. I spent Saturday building a batch system from scratch, tuning the sharpening curves, testing the export pipeline, and handling the edge cases, about 30 images that needed manual intervention because of clipping issues. Sunday morning I ran the whole job. The script processed the remaining 470 files in under two hours. I spent the rest of Sunday checking output and doing final QA.

That job paid for several months of operating costs. I could not have completed it as a one-person operation without that automation pipeline.

Where People Go Wrong With Automation

The most common mistake I see is trying to automate before you have a stable, proven manual process. If you do not fully understand every decision you make during a retouch, your script will just make wrong decisions faster.

The second mistake is building monolithic scripts that try to do everything. When something breaks at step 47 of a 60-step script, you will spend more time debugging than you saved. Build modular scripts that each do one thing cleanly. A resize script, a rename script, an export script. Chain them with a parent script if you need to, but keep each piece testable in isolation.

Also, always build in a dry-run mode. Before any script touches real files, I add a dryRun boolean at the top. When it is set to true, the script logs every action it would take to the console but does not write anything to disk. This has saved my source files more than once.

Testing Against Real Files Before You Trust the System

Before I hand any automated pipeline over to a client workflow, I run it against a test set of 20 files that includes intentional problem cases: a CMYK file, a file with layers not flattened, a file with a filename containing special characters, an image that is already smaller than the target export size. If the script handles all of those without crashing or corrupting output, it is ready for production.

If it fails on any of them, I know exactly what to fix before it fails on 400 files at 11 PM before a deadline.

The actual leverage in Photoshop automation is not the individual action or the clever script, it is the combination of both, built carefully, tested against edge cases, and trusted enough that you can walk away while it runs.