Random Person AIO (All-In-One)
Your batch is full of the same face. Fix it with one node.
- full_description
- sex
- age
- nationality
- complexion
- face
- hair
- facial_hair
- body_type
- expression
- accessories
- makeup
- shoulders
- chest
- bust
- clothing
- footwear
- seed
Prompt a model with just "a person" and it will lean on its trained default face. Generate a batch of five and you get the same person five times in slightly different poses - that "everyone looks the same" complaint is one of the oldest in the character-consistency threads, and it's not going away on its own. The fix is specificity: the model needs a concrete face, build, and outfit before it will stop recycling its own idea of a person.
That's the whole pitch of ComfyUI_RandomPerson, and Random Person AIO (All-In-One) is the flagship node in the pack. One node, on every run, hands you a complete comma-separated description covering nationality, age, complexion, skin texture, eyes, eyebrows, face shape, nose, mouth, distinctive features, hair, facial hair, build, shoulders, chest, bust, expression, accessories, makeup, clothing, and footwear. And the name is a half-lie: there's no AI in it. No API call, no model download, no key, no GPU. It's a curated JSON database plus a random picker, which is honestly the best thing about it.
A real female example straight from the docs:
43 year old Russian female, angular face, light medium complexion, smooth skin, natural grey eyes, button nose, wide-set lips, a faint scar through one eyebrow, red very short hair worn twist out, muscular build, reading glasses, bold lipstick
How it works
Every attribute is drawn from a bundled JSON file in data/, split into shared/, male/, and female/. Pick sex (or leave it random), and the node resolves to one list per category, then picks an entry. The descriptions are written to be unambiguous for diffusion - "muted natural green eyes" instead of a bare "green" - which is exactly the difference between this and a sloppy wildcard.
Each of the ~24 attributes gets three widgets, and this is the core loop of the whole pack:
<attr>_mode-random(any value),allow_list(a subset you type),fixed(the dropdown value), oroff(skip it entirely).<attr>_allow_list- comma-separated values forallow_list. Unknown values are kept as literal descriptors, so you can type things likeauburn, fire engine red.<attr>_fixed- the exact value to always use infixedmode.
Core identity categories default to random; the "flair" categories (skin texture, eyebrows, distinctive features, facial hair, expression, accessories, makeup, shoulders, chest, bust, clothing, footwear) default to off so your base person stays clean until you opt in. extra_attributes is free text appended verbatim - pose, props, setting, whatever.
randomize defaults on, which means the seed widget is ignored and you get a fresh person every run. Flip it off and the same seed reproduces the same person. Age lives here too: age_mode (random/fixed/off), age_min/age_max (0 = no bound, effectively 21–90), and age_fixed. Below 21 gets clamped - the author isn't generating minors, and neither should you.
Outputs and wiring
First pin is full_description, ready to feed straight into a CLIP Text Encode (or your text node of choice). Then a pin per attribute - sex, age, nationality, complexion, face, hair, facial_hair, body_type, expression, accessories, makeup, shoulders, chest, bust, clothing, footwear - plus seed as an INT. Route a single trait elsewhere if you need to, or concatenate the full description with your scene prompt using any string node.
Install
ComfyUI Manager is easiest: open Manager → Custom Nodes Manager, search for ComfyUI_RandomPerson, install, restart. Manual works the same as always:
cd ComfyUI/custom_nodes
git clone https://github.com/bradsec/ComfyUI_RandomPerson
Then restart ComfyUI. It appears under Add Node → Random Person. No pip dependencies, Python 3.10+ is all it asks, and it registers on both the legacy V1 and new V3 schema APIs, so it loads on old and new ComfyUI alike.
Gotchas
The node is tall - every category is exposed at once, so you'll scroll. That's the trade for the AIO. If it gets unwieldy, the pack ships segment nodes (Identity, Face, Hair, Body, Style) that each cover a slice. And remember: mode off makes a category vanish from the description, so if your output looks thin, check you haven't left the flair categories off. Edit the JSON under data/ to add your own values - but new entries need a ComfyUI restart to load. If randomize is on, the seed output is whatever it picked this run, not the number you typed, so use randomize: off when you want to reproduce a face exactly.
Inputs (80)
| Name | Type | Default | Description |
|---|---|---|---|
| seed | INT | 00–18446744073709550000 | Seed for reproducibility. With randomize off, the same seed reproduces the same person. |
| randomize | BOOLEAN | true | On: pick a new random person every run, ignoring the seed widget. Off: use the seed. |
| sex | COMBO | random | random, male, or female. male/female filter the sex-specific dropdowns in the UI. |
| nationality_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| nationality_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| nationality_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| complexion_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| complexion_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| complexion_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| skin_texture_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| skin_texture_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| skin_texture_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| eyes_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| eyes_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| eyes_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| eye_shape_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| eye_shape_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| eye_shape_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| eyebrows_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| eyebrows_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| eyebrows_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| face_shape_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| face_shape_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| face_shape_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| nose_shape_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| nose_shape_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| nose_shape_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| mouth_shape_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| mouth_shape_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| mouth_shape_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| face_feature_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| face_feature_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| face_feature_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| hair_color_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| hair_color_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| hair_color_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| hair_style_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| hair_style_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| hair_style_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| hair_length_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| hair_length_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| hair_length_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| facial_hair_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| facial_hair_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| facial_hair_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| body_type_mode | COMBO | random | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| body_type_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| body_type_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| shoulders_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| shoulders_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| shoulders_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| chest_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| chest_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| chest_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| bust_size_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| bust_size_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| bust_size_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| bust_shape_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| bust_shape_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| bust_shape_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| expression_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| expression_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| expression_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| accessories_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| accessories_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| accessories_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| makeup_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| makeup_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| makeup_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| clothing_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| clothing_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| clothing_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| footwear_mode | COMBO | off | How this attribute is chosen: random (any), allow_list (subset you list), fixed (the dropdown value), off (omit it). |
| footwear_allow_list | STRING | Comma-separated values used when mode=allow_list. Unknown values are added as literal descriptors. | |
| footwear_fixed | COMBO | (none) | Exact value used when mode=fixed. (none) falls back to random. |
| age_mode | COMBO | random | How to pick the age: random within range, fixed value, or off (no age in the description). |
| age_min | INT | 00–90 | Minimum age. 0 = no lower bound (defaults to 21). Cannot go below 21. |
| age_max | INT | 00–90 | Maximum age. 0 = no upper bound (defaults to 90). Minimum is always 21. |
| age_fixed | INT | 00–90 | Exact age when mode=fixed. 0 = ignored. Values below 21 are clamped to 21. |
| extra_attributes | STRING | Free text appended to the description as-is, comma-separated. Pose, setting, props, extra detail, etc. |
Outputs (18)
| Name | Type | Description |
|---|---|---|
| full_description | STRING | — |
| sex | STRING | — |
| age | STRING | — |
| nationality | STRING | — |
| complexion | STRING | — |
| face | STRING | — |
| hair | STRING | — |
| facial_hair | STRING | — |
| body_type | STRING | — |
| expression | STRING | — |
| accessories | STRING | — |
| makeup | STRING | — |
| shoulders | STRING | — |
| chest | STRING | — |
| bust | STRING | — |
| clothing | STRING | — |
| footwear | STRING | — |
| seed | INT | — |