Whether you're building a website, writing CSS, or passing colors between design tools and code, you will constantly encounter two color formats: hex codes (like #FF6B6B) and RGB values (like rgb(255, 107, 107)). Understanding how to convert between them — and why you'd want to — is a foundational skill for anyone working with digital color.
This guide covers everything: what hex and RGB actually mean, the exact conversion formula, worked examples, ready-to-use code in JavaScript, Python, and CSS, and the most common mistakes people make. By the end, you'll be able to convert any color in your head, in your code, or with our free online converter.
- What is a hex color code?
- What is RGB?
- The hex to RGB conversion formula
- Step-by-step examples
- Converting hex to RGB in JavaScript
- Converting hex to RGB in Python
- Using both formats in CSS
- When to use hex vs RGB
- 3-digit hex shorthand
- Common mistakes and how to avoid them
- Beyond RGB: HSL and HSV
- Frequently asked questions
1. What is a hex color code?
A hex color code is a way of expressing a color using the hexadecimal (base-16) number system. Hexadecimal uses 16 digits instead of the usual 10: 0–9, then A–F (where A=10, B=11, C=12, D=13, E=14, F=15).
A full hex color code looks like this: #FF6B6B
The # symbol is just a prefix that tells CSS and design tools "this is a hex color." The six characters after it are split into three pairs:
| Pair | Hex digits | Represents | Range |
|---|---|---|---|
| First pair | FF | Red channel | 00–FF (0–255) |
| Second pair | 6B | Green channel | 00–FF (0–255) |
| Third pair | 6B | Blue channel | 00–FF (0–255) |
Each pair represents a number from 00 (0 in decimal) to FF (255 in decimal). This gives us 256 possible values per channel and 256³ = 16,777,216 possible colors in total.
2. What is RGB?
RGB stands for Red, Green, Blue — the three primary colors of light. Screens create every visible color by mixing these three channels at different intensities. Each channel takes a value from 0 (off) to 255 (full intensity).
In CSS you write it as: rgb(255, 107, 107) or the modern syntax rgb(255 107 107).
Some common reference points:
| Color | RGB | Hex |
|---|---|---|
| Pure Red | rgb(255, 0, 0) | #FF0000 |
| Pure Green | rgb(0, 255, 0) | #00FF00 |
| Pure Blue | rgb(0, 0, 255) | #0000FF |
| White | rgb(255, 255, 255) | #FFFFFF |
| Black | rgb(0, 0, 0) | #000000 |
| Mid Gray | rgb(128, 128, 128) | #808080 |
| Coral Red | rgb(255, 107, 107) | #FF6B6B |
3. The hex to RGB conversion formula
The conversion is straightforward: split the hex string into three two-character pairs, then convert each pair from base-16 to base-10.
In mathematical notation:
Given hex color: #RRGGBB R = parseInt(RR, 16) G = parseInt(GG, 16) B = parseInt(BB, 16)
parseInt(value, 16) means "convert this value treating it as a base-16 number." You can do this manually by multiplying the first digit by 16 and adding the second digit:
For hex pair "6B": 6 × 16 = 96 B (= 11) × 1 = 11 96 + 11 = 107 So "6B" in hex = 107 in decimal = the Green or Blue channel value.
4. Step-by-step examples
Example 1: #FF6B6B (Coral Red)
Hex: #FF6B6B Red pair: FF → F(15) × 16 + F(15) = 240 + 15 = 255 Green pair: 6B → 6 × 16 + B(11) = 96 + 11 = 107 Blue pair: 6B → 6 × 16 + B(11) = 96 + 11 = 107 Result: rgb(255, 107, 107)
Example 2: #1A237E (Dark Indigo)
Hex: #1A237E Red pair: 1A → 1 × 16 + A(10) = 16 + 10 = 26 Green pair: 23 → 2 × 16 + 3 = 32 + 3 = 35 Blue pair: 7E → 7 × 16 + E(14) = 112 + 14 = 126 Result: rgb(26, 35, 126)
Example 3: #00BCD4 (Cyan)
Hex: #00BCD4 Red pair: 00 → 0 × 16 + 0 = 0 Green pair: BC → B(11) × 16 + C(12) = 176 + 12 = 188 Blue pair: D4 → D(13) × 16 + 4 = 208 + 4 = 212 Result: rgb(0, 188, 212)
5. Converting hex to RGB in JavaScript
Here are several approaches, from simple to production-ready:
Basic function
function hexToRgb(hex) {
// Remove # if present
hex = hex.replace(/^#/, '');
// Handle 3-digit shorthand (#RGB → #RRGGBB)
if (hex.length === 3) {
hex = hex[0]+hex[0] + hex[1]+hex[1] + hex[2]+hex[2];
}
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return { r, g, b };
}
// Usage
hexToRgb('#FF6B6B'); // { r: 255, g: 107, b: 107 }
hexToRgb('#F6B'); // { r: 255, g: 102, b: 187 } (3-digit)
Using regex (compact)
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
// Returns null for invalid input — safe for production use
With validation and CSS string output
function hexToRgbString(hex, alpha = 1) {
hex = hex.replace(/^#/, '');
if (hex.length === 3) {
hex = hex.split('').map(c => c + c).join('');
}
if (!/^[0-9a-f]{6}$/i.test(hex)) {
throw new Error(`Invalid hex color: #${hex}`);
}
const r = parseInt(hex.slice(0, 2), 16);
const g = parseInt(hex.slice(2, 4), 16);
const b = parseInt(hex.slice(4, 6), 16);
return alpha < 1
? `rgba(${r}, ${g}, ${b}, ${alpha})`
: `rgb(${r}, ${g}, ${b})`;
}
hexToRgbString('#FF6B6B'); // "rgb(255, 107, 107)"
hexToRgbString('#FF6B6B', 0.5); // "rgba(255, 107, 107, 0.5)"
Using Canvas API (browser only)
// The browser's Canvas API can parse any CSS color string
function cssColorToRgb(colorString) {
const canvas = document.createElement('canvas');
canvas.width = canvas.height = 1;
const ctx = canvas.getContext('2d');
ctx.fillStyle = colorString;
ctx.fillRect(0, 0, 1, 1);
const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
return { r, g, b, a };
}
// Works with any valid CSS color
cssColorToRgb('#FF6B6B'); // { r: 255, g: 107, b: 107, a: 255 }
cssColorToRgb('coral'); // named colors work too
cssColorToRgb('hsl(0,80%,70%)'); // HSL input also works
6. Converting hex to RGB in Python
Python's standard library makes this even cleaner:
def hex_to_rgb(hex_color):
hex_color = hex_color.lstrip('#')
if len(hex_color) == 3:
hex_color = ''.join(c*2 for c in hex_color)
r = int(hex_color[0:2], 16)
g = int(hex_color[2:4], 16)
b = int(hex_color[4:6], 16)
return (r, g, b)
hex_to_rgb('#FF6B6B') # (255, 107, 107)
hex_to_rgb('1A237E') # (26, 35, 126)
def hex_to_rgb(h):
h = h.lstrip('#')
return tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
# (255, 107, 107)
from PIL import ImageColor
# ImageColor.getrgb handles all CSS color formats
ImageColor.getrgb('#FF6B6B') # (255, 107, 107)
ImageColor.getrgb('coral') # (255, 127, 80) — named colors too
ImageColor.getrgb('hsl(0,80%,70%)') # HSL input
7. Using both formats in CSS
Modern CSS supports both hex and RGB natively. Here's when each shines:
/* Hex — most common, most compact */
.button { background: #6366f1; }
/* RGB — useful when you need to add transparency */
.overlay { background: rgba(99, 102, 241, 0.5); }
/* Modern CSS rgb() — space-separated (no commas) */
.card { color: rgb(99 102 241); }
/* CSS custom properties — define once, use everywhere */
:root {
--brand: 99 102 241; /* Store as raw values */
}
.element {
background: rgb(var(--brand)); /* Solid */
border: 1px solid rgba(var(--brand), 0.3); /* Semi-transparent */
}
--color-indigo-500: 99 102 241 rather than --color-indigo-500: rgb(99 102 241).
8. When to use hex vs RGB
| Situation | Best format | Why |
|---|---|---|
| CSS solid colors | Hex | Shorter, more readable, universally supported |
| CSS with opacity / transparency | RGBA | Fourth alpha parameter not available in hex (without #RRGGBBAA) |
| Design tools (Figma, Sketch) | Hex | Standard input for color fields |
| Canvas API / WebGL | RGB (0–1 range) | WebGL expects 0.0–1.0 floats, not 0–255 integers |
| Image processing (Python PIL) | RGB tuples | Pixel operations work with integer channels |
| Generating color programmatically | HSL | Easier to manipulate hue, saturation, and lightness |
| Sharing colors with non-developers | Hex | Everyone recognizes #FF6B6B format |
| CSS custom properties system | RGB values (raw) | Enables opacity variants via rgb(var(--color)) |
9. The 3-digit hex shorthand
When each pair in a 6-digit hex consists of two identical characters, you can write it as a 3-digit shorthand. The browser expands it by doubling each digit:
#FFF = #FFFFFF → rgb(255, 255, 255) White #000 = #000000 → rgb(0, 0, 0) Black #F6B = #FF66BB → rgb(255, 102, 187) Pink #09C = #0099CC → rgb(0, 153, 204) Sky Blue #3A7 = #33AA77 → rgb(51, 170, 119) Teal Green
The rule: shorthand only works when both digits in each pair are the same. #FF6B6B cannot be shortened (6B is not a repeated digit). #FFAACC can be shortened to #FAC.
10. Common mistakes and how to avoid them
Mistake 1: Forgetting to strip the # prefix
The most common bug. If you pass #FF6B6B directly to parseInt(), it returns NaN. Always strip the leading # before parsing.
// WRONG — returns NaN
parseInt('#FF', 16); // NaN
// RIGHT — strip # first
parseInt('FF', 16); // 255
// Or use replace
parseInt('#FF6B6B'.replace('#', '').slice(0, 2), 16); // 255
Mistake 2: Not handling the 3-digit shorthand
A function that only handles 6-digit hex will silently produce wrong values (or NaN) for inputs like #F6B. Always expand 3-digit to 6-digit first.
Mistake 3: Case sensitivity
#ff6b6b and #FF6B6B are identical — hex is case-insensitive. Always use /i flag in regexes or call .toLowerCase() or .toUpperCase() before processing.
Mistake 4: Wrong substring indices
Off-by-one errors are common. Remember: Red = characters 0–1, Green = 2–3, Blue = 4–5 (zero-indexed, 2 chars each).
const hex = 'FF6B6B'; const r = parseInt(hex.slice(0, 2), 16); // 0,2 → 'FF' → 255 const g = parseInt(hex.slice(2, 4), 16); // 2,4 → '6B' → 107 const b = parseInt(hex.slice(4, 6), 16); // 4,6 → '6B' → 107
Mistake 5: Confusing RGBA hex (#RRGGBBAA)
CSS and some tools support 8-digit hex with an alpha channel: #FF6B6B80 (50% opacity). If your input could be 8 digits, handle the alpha pair separately (characters 6–7).
11. Beyond RGB: HSL and HSV
RGB and hex are great for computers and design tools, but they're not intuitive for humans. HSL (Hue, Saturation, Lightness) is often easier to reason about when you're generating or adjusting colors programmatically.
- Hue — the base color on the color wheel (0°=red, 120°=green, 240°=blue)
- Saturation — 0% is gray, 100% is full color
- Lightness — 0% is black, 50% is the pure color, 100% is white
For example, to create a lighter or darker shade of your brand color in CSS, HSL is far more intuitive than manipulating RGB channels:
/* Hard to understand what this will look like */ color: rgb(99, 102, 241); /* Much clearer — indigo, fully saturated, medium lightness */ color: hsl(239, 84%, 67%); /* Easy to create shades by changing only lightness */ --color-light: hsl(239, 84%, 90%); /* Light tint */ --color-dark: hsl(239, 84%, 40%); /* Dark shade */
Our hex to RGB converter outputs HSL and HSV values alongside RGB, so you can see all formats at once and choose the one that fits your workflow.
Ready to convert? Use the free tool →
Paste any hex code and instantly get RGB, RGBA, HSL, HSV and CSS values with one-click copy buttons.
Open Hex to RGB Converter12. Frequently Asked Questions
Is hex to RGB conversion lossy?
No. Both hex and RGB (8-bit) represent exactly the same 16,777,216 colors. Converting between them is perfectly lossless — every hex code maps to exactly one RGB value, and vice versa.
Can I convert hex to RGB without a tool?
Yes. Split the hex into three 2-character pairs and convert each from base-16 to base-10. For example, #1A2B3C → 1A=26, 2B=43, 3C=60 → rgb(26, 43, 60). With practice, you can do small values in your head.
Does the order matter in hex codes?
Yes — the order is always Red–Green–Blue. #FF0000 is red (full red, zero green, zero blue). Swap the pairs and you get a completely different color.
What is the difference between hex and RGB color spaces?
They are not different color spaces — they are different notations for the same sRGB color space. Hex is simply a base-16 encoding of the same three 8-bit channel values that RGB expresses in base-10.
Why do some hex codes have 8 digits?
An 8-digit hex code includes an alpha (transparency) channel as the last two digits. For example, #FF6B6B80 is the same coral red but at roughly 50% opacity. The CSS equivalent is rgba(255, 107, 107, 0.502).