How to Generate a Random Hex Color
A random hex color is a six-character string like #a3f4c2 that represents a CSS color. You need one when you're seeding placeholder UI, assigning unique colors to dataset entries, building a color-picker demo, or stress-testing a design with unexpected colors.
The naive approach — pick three random bytes and format them as hex — works but produces muddy, unreadable colors roughly 80% of the time. This guide shows the naive approach first, then the smarter HSL-based method that gives you random but usable colors, plus how to pick random colors from a curated palette.
The naive approach: random bytes
Every hex color is three byte values (0–255) packed into #RRGGBB. The simplest random color picks three independent bytes.
JavaScript (browser + Node)
// Math.random — fine for visual placeholders, not cryptographically safe
function randomHex() {
return '#' + Math.floor(Math.random() * 0xffffff)
.toString(16)
.padStart(6, '0');
}
console.log(randomHex()); // e.g. "#4d9c2f"
The padStart(6, '0') is essential: Math.random() can produce values like 0x00a1c4, whose toString(16) is only five characters — without padding you'd get #a1c4 which is a valid three-character shorthand but not what you meant.
Python
import random
import secrets # use this instead if you need unpredictability
def random_hex():
return '#{:06x}'.format(random.randint(0, 0xFFFFFF))
def random_hex_secure():
return '#{:06x}'.format(secrets.randbelow(0x1000000))
print(random_hex()) # e.g. "#7e3ab1"
print(random_hex_secure()) # cryptographically random
Go
package main
import (
"crypto/rand"
"fmt"
"math/big"
)
func randomHex() string {
n, _ := rand.Int(rand.Reader, big.NewInt(0x1000000))
return fmt.Sprintf("#%06x", n)
}
func main() {
fmt.Println(randomHex()) // e.g. "#3f8c2a"
}
Go's crypto/rand is the idiomatic choice — there's no reason to use math/rand for something this simple.
PHP
function randomHex(): string {
return '#' . str_pad(dechex(random_int(0, 0xFFFFFF)), 6, '0', STR_PAD_LEFT);
}
echo randomHex(); // e.g. "#c2794d"
Use random_int, not rand. PHP's rand is seeded with a predictable value on some platforms.
The smarter approach: random HSL
Pure random RGB gives you colors across the full gamut, which includes very dark, very light, very saturated, and very grey colors. If you want colors that are visually distinct and reasonably legible on a white background, generate in HSL and convert to hex.
HSL stands for Hue (0–360°, the color wheel), Saturation (0–100%, how vivid), Lightness (0–100%, how bright). By fixing saturation around 60–70% and lightness around 50–60%, every random hue produces a clear, medium-tone color.
JavaScript
function hslToHex(h, s, l) {
s /= 100;
l /= 100;
const k = n => (n + h / 30) % 12;
const a = s * Math.min(l, 1 - l);
const f = n => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
const toHex = x => Math.round(x * 255).toString(16).padStart(2, '0');
return `#${toHex(f(0))}${toHex(f(8))}${toHex(f(4))}`;
}
function randomReadableHex() {
const h = Math.floor(Math.random() * 360); // full hue range
const s = 55 + Math.random() * 20; // 55–75 % saturation
const l = 45 + Math.random() * 15; // 45–60 % lightness
return hslToHex(h, s, l);
}
console.log(randomReadableHex()); // always a clear, medium-tone color
Python
import colorsys
import random
def random_readable_hex() -> str:
h = random.random() # 0–1 (full hue wheel)
s = random.uniform(0.55, 0.75) # moderate saturation
l = random.uniform(0.45, 0.60) # medium lightness
r, g, b = colorsys.hls_to_rgb(h, l, s) # Python uses HLS order!
return '#{:02x}{:02x}{:02x}'.format(
round(r * 255), round(g * 255), round(b * 255)
)
print(random_readable_hex())
Note the Python colorsys.hls_to_rgb argument order: H, L, S (lightness before saturation) — the reverse of the HSL convention you know from CSS.
Random color from a palette
When you want random but on-brand, define a palette of approved colors and pick from it randomly. This is the right approach for UI avatar backgrounds, chart series colors, and tag labels.
JavaScript
const PALETTE = [
'#ef4444', '#f97316', '#eab308', '#22c55e',
'#06b6d4', '#3b82f6', '#8b5cf6', '#ec4899',
];
function randomFromPalette() {
return PALETTE[Math.floor(Math.random() * PALETTE.length)];
}
Python
import random
PALETTE = [
'#ef4444', '#f97316', '#eab308', '#22c55e',
'#06b6d4', '#3b82f6', '#8b5cf6', '#ec4899',
]
def random_from_palette() -> str:
return random.choice(PALETTE)
Go
import (
"crypto/rand"
"math/big"
)
var palette = []string{
"#ef4444", "#f97316", "#eab308", "#22c55e",
"#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899",
}
func randomFromPalette() string {
n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(palette))))
return palette[n.Int64()]
}
PHP
$palette = [
'#ef4444', '#f97316', '#eab308', '#22c55e',
'#06b6d4', '#3b82f6', '#8b5cf6', '#ec4899',
];
function randomFromPalette(array $palette): string {
return $palette[array_rand($palette)];
}
Unique random colors for multiple items
If you're assigning a color to each item in a list (user avatars, chart lines, category labels), you need unique colors — no repeats. Shuffle the palette and take one per item.
// JavaScript: unique colors from a palette, no repeats
function shuffled(arr) {
const a = [...arr];
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
const colors = shuffled(PALETTE).slice(0, items.length);
If you have more items than palette colors, fall back to generated HSL colors with evenly spaced hues:
function evenlySpacedColors(count) {
return Array.from({ length: count }, (_, i) => {
const h = Math.round((i / count) * 360);
return hslToHex(h, 65, 52);
});
}
Evenly-spaced hues guarantee maximum perceptual difference between colors — the best choice for distinguishable chart series.
Quick reference
| Goal | Method | Example output |
|---|---|---|
| Any random color | Random 24-bit integer → hex | #4d3ab1 (may be dark/muted) |
| Legible random color | Random HSL, fixed S+L range | #6ab84e (always clear) |
| Brand-consistent color | random.choice(palette) |
#3b82f6 |
| Unique colors for N items | Shuffle palette, slice | No repeats |
| Max-distinct colors for N items | Evenly-spaced hue, fixed S+L | Maximum separation |
6 common mistakes
1. Forgetting padStart
Math.floor(Math.random() * 0xffffff).toString(16) can produce a 5-character string for small values. Always .padStart(6, '0') or format with %06x.
2. Using Math.random where security matters
For generating unique IDs, tokens, or anything an attacker could predict, Math.random is not cryptographically safe. Use crypto.getRandomValues (browser), crypto.randomBytes (Node), secrets.randbelow (Python), or crypto/rand (Go).
3. Ignoring readability
Pure random RGB produces gray and near-black colors constantly. If human readability matters, use the HSL approach with constrained saturation and lightness.
4. Generating colors inside a tight render loop
If you're generating a color every frame (animation, live preview), create the color once and store it — don't call the RNG on every render.
5. Assuming #fff and #ffffff are interchangeable in code
Three-character hex shorthand works in CSS but not everywhere. JSON config parsers, Python Pillow, and some SVG renderers expect the full six-character form. Always emit #rrggbb.
6. Storing colors as floats
After converting through HSL or generating as floats, round each channel to an integer before formatting. Math.round(r * 255), not Math.floor — floor causes systematic darkening at the top of each channel.
Frequently asked questions
What does "random hex color" mean exactly?
A hex color is a CSS color code in the format #RRGGBB, where each pair is a two-digit hexadecimal number (00–FF) representing the red, green, and blue channel intensity. A random hex color is one where those values are chosen by a random number generator rather than a human.
How many possible hex colors are there?
#000000 to #FFFFFF gives 16,777,216 (2²⁴) possible colors — one for every combination of 256 × 256 × 256 red/green/blue values.
How do I generate a random dark color for a dark-mode background?
Use the HSL approach and constrain lightness to 10–30%:
const h = Math.floor(Math.random() * 360);
const color = hslToHex(h, 30, 20); // dark, slightly tinted
How do I generate a random light color for a pastel look?
Constrain saturation to 40–60% and lightness to 75–90%:
const h = Math.floor(Math.random() * 360);
const color = hslToHex(h, 50, 82); // pastel
What's the difference between Math.random and crypto.getRandomValues for colors?
Math.random is a pseudo-random number generator (PRNG) — fast, but theoretically predictable if someone knows the seed. crypto.getRandomValues is a cryptographically secure PRNG (CSPRNG) sourced from OS entropy. For visual placeholders either is fine; for anything security-related (tokens, IDs) use the crypto version.
Can I convert the random hex to RGB or HSL for further processing?
Yes — use the Color Converter to convert between hex, RGB, HSL, and HSV instantly. If you need to do it in code, see the hex-to-RGB guide for formulas in all four languages.