Python can produce any color in the full 24-bit RGB space — all 16,777,216 combinations — with a single call to random.randint(0, 255) for each of the three channels. That range matches what a standard screen can display, so a program written with three random integers pulls from exactly the same palette your monitor shows. From those three numbers you can format the result as a HEX string for CSS, an rgb() tuple for image editors, or an HSL triplet for human-readable color work. Python's standard library ships everything you need for this — no third-party packages, no API calls — and the code typically fits in three or four lines. This guide walks through the shortest code paths for each format, then shows the faster browser route when you only need the values, not a script.
Random colors in Python show up in mock data, placeholder avatars, chart series, and test fixtures. Designers prototyping in notebooks reach for matplotlib scatter plots with a random color per series; QA engineers seed fixtures with a random hex string; front-end developers stress rendering paths by drawing dozens of randomly colored elements on a canvas. For pure inspiration — the moment where you just want a fresh set of swatches to break a creative block — a dedicated random color tool can be quicker than opening a REPL. The rest of this article covers both options so you can pick whichever fits the moment.

Python's built-in tools for random colors
The shortest path starts with Python's random module, which ships in the standard library. To draw from the full 16,777,216-color RGB space, call random.randint(0, 255) once for each of the three channels. Because the function is inclusive on both ends, the result really does span every value a screen pixel can hold.
For something a little more uniform when seeding test data, the secrets module exposes the same kind of value through secrets.randbelow(256), which uses the operating system's cryptographically secure source. That is what you want for tokens and salts; for design and chart work, both modules give visually identical results, so reach for random unless there is a security reason to swap.
Two more standard-library helpers come up often:
- colorsys.rgb_to_hls(r, g, b) — converts an RGB triple (each value 0 to 1) into a hue-lightness-saturation triple. It returns (h, l, s), with h on a 0–1 scale and l and s on 0–1 scales as well.
- Format strings, either printf-style ('#%02X%02X%02X') or f-string style (f'#{r:02x}{g:02x}{b:02x}'), for turning those numbers into the exact strings CSS and design tools expect.
Together those three pieces cover every color format you will paste into real work without leaving the standard library.
One-line recipes for HEX, RGB, and HSL output
Three lines cover the common cases, starting from three random integers:
r, g, b = (random.randint(0, 255) for _ in range(3))
hex_color = f'#{r:02x}{g:02x}{b:02x}'
rgb_color = f'rgb({r}, {g}, {b})'
The f-string specifier :02x lowercases the hex and zero-pads each channel to two digits, which is the format every browser accepts. Swap the lowercase x for uppercase X in the format string if you want the canonical #3A9D7F style used in some design systems.
For HSL, run the same three integers through colorsys:
import colorsys
h, l, s = colorsys.rgb_to_hls(r/255, g/255, b/255)
hsl_color = f'hsl({round(h*360)}, {round(s*100)}%, {round(l*100)}%)'
The conversion is the standard RGB-to-HSL formula, and the multipliers in the f-string turn the 0–1 outputs of colorsys into degrees, percent saturation, and percent lightness — the units CSS expects.
Worked example
Suppose the three random integers come out as r = 100, g = 200, b = 150. Walking through each format:
- HEX — each value padded to two lowercase hex digits: 64, c8, 96. Result: #64c896.
- RGB — direct paste of the integers, comma-separated, inside rgb(). Result: rgb(100, 200, 150).
- HSL — divide each channel by 255 and feed into colorsys.rgb_to_hls(100/255, 200/255, 150/255), which returns approximately (0.417, 0.588, 0.476). Hue × 360 ≈ 150, saturation × 100 ≈ 48%, lightness × 100 ≈ 59%. Result: hsl(150, 48%, 59%).
All three strings describe the same swatch. Pick whichever format your downstream tool accepts.
| Format | Example output | Best used for |
|---|---|---|
| HEX | #64c896 | CSS, Figma, design tokens |
| RGB | rgb(100, 200, 150) | Image editors, canvas drawing, plot libraries |
| HSL | hsl(150, 48%, 59%) | Tweaking a random result into a usable hue family |
How to generate random colors with the Random Color Generator
When you are not running a Python script — say you are picking palette inspiration in a design tool, or you just need one or two good colors fast — the Random Color Generator does the same job in a single click. It draws from the same full 24-bit RGB space and shows every result in all three formats at once, so you can copy whichever string you need without retyping.
- Open the Random Color Generator in any modern browser.
- Set how many colors you want in the count field (1 to 100).
- Click Generate to produce a fresh batch of random colors.
- Click any swatch to copy its HEX, or click the RGB or HSL value to copy that format.
Re-roll as many times as you like. Because the source is the browser's built-in random function, each batch feels genuinely different from the last, which is what makes the tool useful for breaking out of a familiar palette. Everything runs locally — nothing is uploaded and no account is needed.
Python code or browser tool: which one fits the job
Both approaches sample from the exact same 16,777,216-color space, so the output quality is identical. The choice comes down to what surrounds the task.
| Situation | Reach for Python | Reach for the Random Color Generator |
|---|---|---|
| Need 100+ colors embedded in mock data | Yes — a one-line list comprehension beats clicking | No — too many individual clicks |
| Picking inspiration for a single design | Overkill — still need to eyeball the result | Yes — visual swatches, one-click copy |
| Seeding a deterministic test suite | Yes — set random.seed() for repeatable runs | No — browser draws are not seedable |
| Quick reference while writing CSS by hand | No — overhead of opening a REPL | Yes — keep the tab open and re-roll |
| Need RGB or HSL output alongside HEX | Yes — three format strings on one tuple | Yes — all three shown next to every swatch |
The general split: if the color lives inside a script, generate it inside the script. If the color is the goal — not a side effect of running code — open the Random Color Generator and copy the format you need.
Check contrast before a random color carries meaning
Random HEX, RGB, and HSL values are not guaranteed accessible. The contrast ratio between a random foreground and a random background spans the full range from 1:1 to 21:1, with most pairs landing somewhere in the middle. WCAG 2.2 defines 4.5:1 as the minimum for body text (AA) and 7:1 for the stricter AAA level. Whenever a color will hold text, an icon, or any signal a user has to read, run it through a contrast check before you ship.
A practical workflow is to generate a batch with the Random Color Generator, pick the swatches that look promising, then verify each one against its actual background. Random colors are great for breaking out of habit; they are not safe defaults for accessibility-critical UI.
For the rest of the path, three related tools round out the workflow: convert any HEX you copy into exact channel values with the HEX to RGB Converter, build a coordinated palette from a base color with the Color Palette Generator, or check a foreground-background pair against WCAG AA and AAA with the Color Contrast Checker. Together they cover the jump from a random swatch to a confirmed accessible color in real designs.