Random Int
Roll a Random Integer in ComfyUI Without the Seed Rig
- VALUE
- RANGE_FROM
- RANGE_TO
ComfyUI gives you one kind of randomness for free: control_after_generate on the KSampler seed. That rolls the noise, which is great until you want randomness anywhere else - picking which of five LoRAs to load, which style prompt to run, how many steps to use, which aspect ratio wins. For that you've always had to rig a seed through a math chain or install a randomizer that drags in a dozen dependencies. Random Int is just the dice. Give it a range, it hands back a whole number in that range, and that's the whole job.
It's from Mistralys' tiny comfyui-random-nodes pack, which ships exactly two nodes. Zero pip dependencies, zero model downloads, MIT licensed - the pack is pure Python standard library sitting on ComfyUI's built-ins. It's also new (v1.0.0, mid-2026), so treat it as "works exactly as advertised, lightly battle-tested" rather than the decade-old utility you can't live without.
How it works
Under the hood it's a one-liner: random.randint(range_from, range_to). A few details are worth knowing because they define the behavior:
- The range is inclusive on both ends, unlike a lot of "random between" math you'll rig yourself.
- Bounds are swapped if you invert them. Put 10 in
range_fromand 1 inrange_toand you still get something between 1 and 10, not a crash. - There is no seed input. This node is deliberately non-reproducible - it can't replay a run. If you need "same random pick, deterministically," this isn't the tool; wire a seed through your normal sampler instead.
The clever bit is how it plays with ComfyUI's cache. This pack is written against the new V3 backend API (comfy_api.latest, the io.ComfyNode style with no NODE_CLASS_MAPPINGS dict - see the migration note in comfyui-ecosystem.md). When the randomized toggle is on, the node's fingerprint_inputs() returns the current timestamp, which makes the fingerprint different every run and forces re-execution. When randomized is off, the fingerprint is just the stored value, so ComfyUI can cache and reuse it. That's the V3-era version of the old float("NaN") IS_CHANGED trick.
The inputs and outputs that matter
Two of the inputs are real sockets you can wire from other nodes; the other two are controls living on the node face (V3 calls them socketless):
range_from/range_to- the only inputs other nodes can drive. Default 0 and 1. Wire these up if you want a range that shifts with your workflow, or just type numbers in.randomized- a checkbox on the node. Off by default. Off means "return whatevervalueis"; on means "roll a fresh number every run." This is the toggle you'll flip for batch variation.value- the stored number that comes out whenrandomizedis off. After a run it gets updated to whatever was just generated, which is how the "lock it in" flow works.
Then there are the two buttons the pack adds to the node face: New random value rolls once right now, and Use current: N restores the last generated value. Here's the subtle part people trip on: clicking "New random value" also switches randomized off. So the button means "roll once and freeze this result," while the toggle means "roll a new one on every single run." Same "random," two very different cadences.
Outputs: VALUE is the random integer. RANGE_FROM and RANGE_TO just echo their inputs back out, which is handy when you need to split a connection without repeating values.
Installing it
ComfyUI Manager is the easy route - search for comfyui-random-nodes. Or clone it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/Mistralys/comfyui-random-nodes.git
Then restart ComfyUI and find it under Add Node → random → Random Int. There are no extra Python packages to install and nothing to download. One real prerequisite: because this pack uses the V3 API, you need a ComfyUI build recent enough to ship comfy_api.latest - on an older install the pack just won't load, and no amount of dependency-fixing will help. That's a feature (it's future-proof), not a bug in the pack.
Where people get burned
The randomized/button confusion above is the main one - you click the button expecting "reroll each run," get one roll, and blame the node. Flip the checkbox instead. Second: with randomized on, this node re-executes every run by design, and so does everything downstream of it. Cheap math is fine, but don't hang an expensive sampler's settings off it and wonder why the graph never caches. And if you're chasing a reproducible series of picks, remember there's no seed - lock a good value with the checkbox off and call it done.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| range_from | INT | 0 | Minimum integer value to generate. |
| range_to | INT | 1 | Maximum integer value to generate. |
| value | INT | 0 | The randomized value. Reused when 'randomized' is off. |
| randomized | BOOLEAN | false | Whether to generate a new random value on the next run. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| VALUE | INT | The generated (or stored) integer value. |
| RANGE_FROM | INT | Passthrough of the input value. |
| RANGE_TO | INT | Passthrough of the input value. |