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.

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:

PairHex digitsRepresentsRange
First pairFFRed channel00–FF (0–255)
Second pair6BGreen channel00–FF (0–255)
Third pair6BBlue channel00–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.

💡 Why hexadecimal?
Computers store colors as 24-bit values (8 bits per channel). One byte (8 bits) holds values 0–255, which conveniently maps to exactly two hex digits (00–FF). This makes hex a compact, direct representation of how color is stored in memory — with no conversion overhead.

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:

ColorRGBHex
Pure Redrgb(255, 0, 0)#FF0000
Pure Greenrgb(0, 255, 0)#00FF00
Pure Bluergb(0, 0, 255)#0000FF
Whitergb(255, 255, 255)#FFFFFF
Blackrgb(0, 0, 0)#000000
Mid Grayrgb(128, 128, 128)#808080
Coral Redrgb(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:

Formula
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:

Manual calculation
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.
⚡ Quick mental shortcut
For hex values A–F: A=10, B=11, C=12, D=13, E=14, F=15. For any pair XY: value = X×16 + Y. Example: "FF" = 15×16 + 15 = 255. "80" = 8×16 + 0 = 128.

4. Step-by-step examples

Example 1: #FF6B6B (Coral Red)

Step-by-step
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)

Step-by-step
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)

Step-by-step
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

JavaScript
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)

JavaScript — regex approach
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

JavaScript — production-ready with CSS 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)

JavaScript — Canvas API method
// 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:

Python — basic
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)
Python — one-liner using tuple unpacking
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)
Python — using PIL/Pillow for image processing
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:

CSS — both formats in action
/* 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 */
}
⚠ CSS variable transparency trick
When using CSS custom properties for colors that need opacity variants, store the raw RGB values (not the full rgb() expression) so you can use them inside rgba(). This is why design systems like Tailwind store colors as --color-indigo-500: 99 102 241 rather than --color-indigo-500: rgb(99 102 241).

8. When to use hex vs RGB

SituationBest formatWhy
CSS solid colorsHexShorter, more readable, universally supported
CSS with opacity / transparencyRGBAFourth alpha parameter not available in hex (without #RRGGBBAA)
Design tools (Figma, Sketch)HexStandard input for color fields
Canvas API / WebGLRGB (0–1 range)WebGL expects 0.0–1.0 floats, not 0–255 integers
Image processing (Python PIL)RGB tuplesPixel operations work with integer channels
Generating color programmaticallyHSLEasier to manipulate hue, saturation, and lightness
Sharing colors with non-developersHexEveryone recognizes #FF6B6B format
CSS custom properties systemRGB 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:

3-digit shorthand examples
#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.

JavaScript — wrong vs right
// 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).

JavaScript — correct indices
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.

For example, to create a lighter or darker shade of your brand color in CSS, HSL is far more intuitive than manipulating RGB channels:

CSS — HSL for programmatic color manipulation
/* 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 Converter

12. 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).