Load Images From Folder (Seb)
The node that presses Run for you, 400 times
- image
- mask
- filename
- path
- index
- count
ComfyUI has no for-loop. Core's Load Image loads exactly one file, so if you want to upscale a folder of 400 photos, fix faces across a whole shoot, or convert a directory to WebP, the honest answer has always been "hand-queue it 400 times" or "write an API script." Load Images From Folder (Seb) is the in-graph version of that: point it at a directory, press Run once, and it walks the folder by re-queueing itself. One image at a time, results on disk as they finish.
That's the whole appeal. It's not glamorous, it's the node you reach for when the job is bulk.
Two modes, and they are genuinely different
The mode dropdown is the only setting that really changes what you get.
one per run (the default) is the interesting one. Each execution loads the single image at index. When that run finishes successfully, the node starts a background thread that waits for the prompt to land in ComfyUI's history, checks that its status is success, deep-copies the prompt, bumps index by one, and POSTs the new prompt back to ComfyUI's own /prompt endpoint. That is the loop: the node queues its own next iteration.
Three consequences fall out of that design, and all three are good. RAM stays flat, because only one image is ever in flight. Files hit disk one by one as they finish, so you get incremental results instead of a 40-minute wait and then a folder. And Cancel actually stops it, because the next iteration is only ever queued after the current one succeeded. An error ends the chain rather than trundling on through the rest of the folder.
all in one run hands everything downstream as a ComfyUI list. That sounds simpler and mostly isn't: list execution runs downstream nodes once per item but node by node - all encodes, then all samples, then all decodes, then all saves - so the whole folder sits in RAM until the last image is done, and nothing is written to disk before then. Fine for five images. Not what you want for a shoot.
Worth knowing: the node overrides ComfyUI's caching deliberately. In loop mode it returns NaN from IS_CHANGED, which the engine treats as "always changed," because a loop driver has to run every time it's queued. In list mode it hashes the folder contents (path, mtime, size per file) and re-runs only when something actually changed. That difference is why an unchanged folder in list mode is instant on the second run.
Inputs and outputs
The one input you actually touch is folder - an absolute path, or a name relative to ComfyUI's input folder. There's no file browser widget; it's a text field, ~ and environment variables get expanded, and surrounding quotes are stripped, so pasting a copied-as-path string works.
Then the fine-tuning: extensions (comma-separated, case-insensitive), include_subfolders, sort_by (name or date), start_index to skip N files and limit to cap the batch. index you leave alone at 0 - the node advances it itself.
Outputs are image, mask, filename, path, index and count, and every one of them is a list even in loop mode (a one-item list). That's the trick that makes a save node downstream behave normally while still receiving one image per run. filename is the one to wire - it carries the source stem, and the pack's own Save Image (Seb) has source modes that name the output after the original, land it next to the source, or replace it in place.
Installing it
ComfyUI Manager, search seb_nodes (or "Seb"), install, restart fully. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/cyberhirsch/seb_nodes
No models to download. Do expect a pause on first start: the pack's __init__.py pip-installs matplotlib, opencv-python, transforms3d, networkx and scikit-image if they're missing, using ComfyUI's own Python. If one of those installs fails it prints the error and carries on - so a later "missing module" complaint is worth checking against your startup log.
Where people get burned
"index N is past the end." You ran the folder, hit Run again, and the index is sitting where it stopped. Set index back to 0 and go again.
Nothing is on disk until the very end. You're in all in one run. Switch to one per run.
The mask output looks wrong on plain JPEGs. For an image with no alpha channel the node emits a 64×64 zeros tensor as the mask - the same placeholder core's Load Image uses for the same case. If you wire it into full-resolution mask arithmetic, resize or ignore it; there's nothing in there.
A file gets skipped. Unreadable images are logged and stepped over rather than killing the run; the console line names the file that failed.
"could not queue". The self-requeue POST didn't land. The node talks to the server over its own host and port (falling back to 127.0.0.1), so a reverse proxy, a custom auth layer, or ComfyUI bound to a host it can't reach itself is where to look. Everything else about the loop is unchanged.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| folder | STRING | Every matching image in here goes through the rest of the graph. Absolute path, or relative to the input folder. | |
| mode | COMBO | one per run: press Run once; each run handles one image and queues the next when it has finished -- results land on disk one by one, RAM stays flat, Cancel stops it. all in one run: everything in a single run as a list; nothing is saved until the last image is done. | |
| index | INT | 00–100000 | one per run: the image this run handles, 0 = first. Leave it at 0 -- the node advances it by itself. Ignored by 'all in one run'. |
| extensions | STRING | png,jpg,jpeg,webp,bmp,tif,tiff | Comma-separated, case-insensitive. |
| include_subfolders | BOOLEAN | false | — |
| sort_by | COMBO | 2 options: name, date | |
| start_index | INT | 00–100000 | Skip this many files (after sorting). |
| limit | INT | 00–100000 | 0 = all. Caps how many files are in play. |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| filename | STRING | — |
| path | STRING | — |
| index | INT | — |
| count | INT | — |