Custom Code Node
Write real Python inside your ComfyUI graph, no plugin required
- any0
- any1
- any2
- any3
- any4
- any5
- any6
- any7
- any8
- any9
- any10
- any11
- any12
- any13
- any14
- any15
- any16
- any17
- any18
- any19
- any20
- any21
- any22
- any23
- any24
- any25
- any26
- any27
- any28
- any29
- any30
- any31
- any32
- any33
- any34
- any35
- any36
- any37
- any38
- any39
- any40
- any41
- any42
- any43
- any44
- any45
- any46
- any47
- any48
- any49
- any50
- any51
- any52
- any53
- any54
- any55
- any56
- any57
- any58
- any59
- any60
- any61
- any62
- any63
You know the feeling: your workflow needs one tiny bit of logic - format a number, slice a string, compute a seed - and there is no node for it, and you are not about to write and install a whole custom node plugin for a three-line calculation. That's exactly the gap this node fills. Custom Code Node (class CustomCodeNode) is a text box sitting in your graph that runs whatever Python you type into it, live, against the values wired into it. ComfyUI ships with a graph-as-program philosophy; this is the part where the keyboard actually shows up.
It's a niche tool, and honestly that's the point. It ships in the comfyui-CustomCodeNode pack alongside two typed siblings - Custom Code (Image) and Custom Code (String) - all by the same author, all with the same "stop writing plugins for small functions" philosophy in the README.
How it works
The node compiles your code string and runs it with Python's exec(). What makes it usable in a graph is the pin convention: as you connect wires, the node's frontend extension grows matching var0, var1, var2… input and output sockets on the fly. Each input you connect arrives as a local variable of the same name, deep-copied in so your snippet can't mangle the upstream object. Assign a value back to that variable and it pops out the matching output pin. Need more than one in/out? Connect another wire and a new pair appears.
Two rules from the README are worth memorizing before you type anything:
- No bare
returnin the snippet. The code runs as a top-level block, so areturnis a syntax error. Want an early exit? Write a function that returns, then call it. - The output pin must exist to get a value back. The node only reads back variables that have a connected pin. Assign to a name with no socket and your result quietly evaporates.
The declared outputs are any0 through any63 - sixty-four wildcard * sockets, the same any-type trick used across the ecosystem - so whatever you wire out comes through regardless of type, be it an int, a string, or a tensor.
The inputs that matter
The fixed inputs are simple, and only a few of them do anything:
code- the multiline Python you want executed. This is the whole node.AlwaysExecute- ComfyUI aggressively caches nodes whose inputs haven't changed. That's great for speed and terrible for anything non-deterministic: if your snippet usesrandomor a timestamp, it'll be skipped as "unchanged." Flip this on and the node fires every single run (the implementation returns a NaN change-hash, the ecosystem's standard always-rerun trick).I(int) andF(float) - always available as variables inside your snippet even if you never wire them. Handy for a seed or a multiplier you want to tweak without touching code.
Installing it
Nothing heavy here - this pack has zero Python dependencies (the project file's dependency list is empty), downloads no models, and is pure stdlib. Through ComfyUI Manager, search for comfyui-CustomCodeNode, or clone it directly:
cd ComfyUI/custom_nodes
git clone https://github.com/What-a-stupid-username/comfyui-CustomCodeNode
Then restart ComfyUI and it's in the CustomCodeNode category.
Common issues & troubleshooting
"My random code never runs." Caching, as above - set AlwaysExecute to true. This is the #1 gotcha and it's in the README for a reason.
"Error Executing Custom Code" - the node prints a proper traceback to the console with the offending line and a caret under the exact column, then raises. Read the console, not the vague node error.
It's arbitrary code, and that's a real thing to respect. Your snippet runs as full Python with your user's privileges inside ComfyUI's process - no sandbox. The ecosystem's worst incidents (the LLMVISION malware, injected crypto-miners) are exactly this class of "install a node, run its code." Only paste code you actually understand, and remember that sharing a workflow containing this node shares your snippet with whoever loads it.
Type-erased pins are a debugging smell. An any-type socket can accept anything, which is convenient and also how workflows become unreadable - the community has pushed back on exactly this pattern. Use it for what it's for: small, surgical logic. Not your whole pipeline.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| I | INT | 0 | — |
| F | FLOAT | 0.50 | — |
| AlwaysExecute | BOOLEAN | false | If True, the node will always execute, even if the input is not changed. |
| code | STRING | print('Hello, World!') print(var0) | — |
Outputs (64)
| Name | Type | Description |
|---|---|---|
| any0 | * | — |
| any1 | * | — |
| any2 | * | — |
| any3 | * | — |
| any4 | * | — |
| any5 | * | — |
| any6 | * | — |
| any7 | * | — |
| any8 | * | — |
| any9 | * | — |
| any10 | * | — |
| any11 | * | — |
| any12 | * | — |
| any13 | * | — |
| any14 | * | — |
| any15 | * | — |
| any16 | * | — |
| any17 | * | — |
| any18 | * | — |
| any19 | * | — |
| any20 | * | — |
| any21 | * | — |
| any22 | * | — |
| any23 | * | — |
| any24 | * | — |
| any25 | * | — |
| any26 | * | — |
| any27 | * | — |
| any28 | * | — |
| any29 | * | — |
| any30 | * | — |
| any31 | * | — |
| any32 | * | — |
| any33 | * | — |
| any34 | * | — |
| any35 | * | — |
| any36 | * | — |
| any37 | * | — |
| any38 | * | — |
| any39 | * | — |
| any40 | * | — |
| any41 | * | — |
| any42 | * | — |
| any43 | * | — |
| any44 | * | — |
| any45 | * | — |
| any46 | * | — |
| any47 | * | — |
| any48 | * | — |
| any49 | * | — |
| any50 | * | — |
| any51 | * | — |
| any52 | * | — |
| any53 | * | — |
| any54 | * | — |
| any55 | * | — |
| any56 | * | — |
| any57 | * | — |
| any58 | * | — |
| any59 | * | — |
| any60 | * | — |
| any61 | * | — |
| any62 | * | — |
| any63 | * | — |