Toolmingo
Guides6 min read

How to Convert Hex to RGB (and Back): Complete Color Code Guide

Learn how to convert hex color codes to RGB values and vice versa. Includes the formula, step-by-step examples, code in JavaScript, Python, Go, and PHP, plus HSL conversion tips.

How to Convert Hex to RGB (and Back): Complete Color Code Guide

Web colors live in two worlds: the six-character hex codes that designers paste into CSS (#3a86ff) and the RGB triplets that programmers use in canvas drawing, image processing, and color math (rgb(58, 134, 255)). Converting between them is a 30-second job once you know the formula — and a five-minute job if you don't.

This guide covers both directions (hex → RGB and RGB → hex), explains why the formats exist, gives ready-to-run code in four languages, and answers the questions that trip people up most often.


What Is a Hex Color Code?

A hex color is three bytes — one each for red, green, and blue — written in base-16 (hexadecimal):

#RRGGBB

Each pair of hex digits goes from 00 (decimal 0) to FF (decimal 255). So #ff0000 is pure red (R=255, G=0, B=0) and #000000 is black.

Format Example Range
Hex #3a86ff 00FF per channel
RGB rgb(58, 134, 255) 0–255 per channel
RGB % rgb(22.7%, 52.5%, 100%) 0%–100%

Browsers understand both formats in CSS. JavaScript Canvas, most image libraries, and color-math functions typically want RGB integers — so conversion is necessary.


The Hex → RGB Formula

Split the six-character code into three two-character chunks and convert each from base 16 to base 10:

R = parseInt("RR", 16)
G = parseInt("GG", 16)
B = parseInt("BB", 16)

Example — #3a86ff:

Chunk Hex Decimal
RR 3a 58
GG 86 134
BB ff 255

Result: rgb(58, 134, 255)


The RGB → Hex Formula

Convert each channel to a two-digit hex string, zero-pad if needed, and concatenate:

hex = "#" + toHex(R) + toHex(G) + toHex(B)

toHex(n) = n.toString(16).padStart(2, "0")

Example — rgb(58, 134, 255):

Channel Decimal Hex Padded
R 58 3a 3a
G 134 86 86
B 255 ff ff

Result: #3a86ff


Code Examples

JavaScript

// Hex → RGB
function hexToRgb(hex) {
  const clean = hex.replace(/^#/, "");
  const r = parseInt(clean.slice(0, 2), 16);
  const g = parseInt(clean.slice(2, 4), 16);
  const b = parseInt(clean.slice(4, 6), 16);
  return { r, g, b };
}

// RGB → Hex
function rgbToHex(r, g, b) {
  return (
    "#" +
    [r, g, b]
      .map((v) => v.toString(16).padStart(2, "0"))
      .join("")
  );
}

console.log(hexToRgb("#3a86ff"));   // { r: 58, g: 134, b: 255 }
console.log(rgbToHex(58, 134, 255)); // "#3a86ff"

Python

def hex_to_rgb(hex_color: str) -> tuple[int, int, int]:
    h = hex_color.lstrip("#")
    return tuple(int(h[i:i+2], 16) for i in (0, 2, 4))

def rgb_to_hex(r: int, g: int, b: int) -> str:
    return f"#{r:02x}{g:02x}{b:02x}"

print(hex_to_rgb("#3a86ff"))    # (58, 134, 255)
print(rgb_to_hex(58, 134, 255)) # "#3a86ff"

Go

package main

import (
    "fmt"
    "strconv"
)

func hexToRGB(hex string) (r, g, b uint8) {
    if len(hex) > 0 && hex[0] == '#' {
        hex = hex[1:]
    }
    val, _ := strconv.ParseUint(hex, 16, 32)
    r = uint8(val >> 16)
    g = uint8((val >> 8) & 0xFF)
    b = uint8(val & 0xFF)
    return
}

func rgbToHex(r, g, b uint8) string {
    return fmt.Sprintf("#%02x%02x%02x", r, g, b)
}

func main() {
    r, g, b := hexToRGB("#3a86ff")
    fmt.Println(r, g, b)           // 58 134 255
    fmt.Println(rgbToHex(58, 134, 255)) // #3a86ff
}

PHP

function hexToRgb(string $hex): array {
    $hex = ltrim($hex, '#');
    return [
        'r' => hexdec(substr($hex, 0, 2)),
        'g' => hexdec(substr($hex, 2, 2)),
        'b' => hexdec(substr($hex, 4, 2)),
    ];
}

function rgbToHex(int $r, int $g, int $b): string {
    return sprintf('#%02x%02x%02x', $r, $g, $b);
}

print_r(hexToRgb('#3a86ff'));   // r=58, g=134, b=255
echo rgbToHex(58, 134, 255);    // #3a86ff

Handling the Short (3-digit) Hex Format

CSS allows a 3-digit shorthand: #rgb is equivalent to #rrggbb — each digit is repeated.

#3af  →  #33aaff
#f00  →  #ff0000

Expand before parsing:

function expandHex(hex) {
  const clean = hex.replace(/^#/, "");
  if (clean.length === 3) {
    return "#" + clean.split("").map((c) => c + c).join("");
  }
  return "#" + clean;
}

Hex with Alpha (8-digit / RGBA)

CSS also supports #RRGGBBAA — an 8-digit hex with an alpha channel:

#3a86ffcc  →  rgba(58, 134, 255, 0.8)

The alpha byte cc (204 in decimal) divided by 255 gives the CSS alpha: 204 / 255 ≈ 0.8.

function hexToRgba(hex) {
  const clean = hex.replace(/^#/, "");
  const r = parseInt(clean.slice(0, 2), 16);
  const g = parseInt(clean.slice(2, 4), 16);
  const b = parseInt(clean.slice(4, 6), 16);
  const a = clean.length === 8
    ? Math.round((parseInt(clean.slice(6, 8), 16) / 255) * 100) / 100
    : 1;
  return { r, g, b, a };
}

Bonus: Converting to HSL

RGB is not great for color math (lightening, darkening, rotating hue). HSL (Hue / Saturation / Lightness) is more intuitive:

function rgbToHsl(r, g, b) {
  r /= 255; g /= 255; b /= 255;
  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  const l = (max + min) / 2;
  if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) };

  const d = max - min;
  const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  let h;
  switch (max) {
    case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
    case g: h = ((b - r) / d + 2) / 6; break;
    case b: h = ((r - g) / d + 4) / 6; break;
  }
  return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) };
}

console.log(rgbToHsl(58, 134, 255)); // { h: 217, s: 100, l: 61 }

To lighten #3a86ff by 10%, convert to HSL, add 10 to L, convert back to hex.


Quick Reference Table

Hex R G B Color
#ff0000 255 0 0 Red
#00ff00 0 255 0 Green
#0000ff 0 0 255 Blue
#ffff00 255 255 0 Yellow
#ff00ff 255 0 255 Magenta
#00ffff 0 255 255 Cyan
#ffffff 255 255 255 White
#000000 0 0 0 Black
#808080 128 128 128 Gray

FAQ

Why do hex colors use base 16? Because two hex digits can represent exactly 256 values (0–255) — the range of one color channel. Base 10 would need three digits for the same range and would be harder to compact to short codes.

Are hex colors case-sensitive? No. #3A86FF and #3a86ff are identical. CSS accepts both; convention is lowercase.

What does parseInt("ff", 16) return? 255. The second argument 16 tells parseInt to interpret the string as base 16.

My color looks wrong after converting — why? Check for the 3-digit short form (#3af) — expand it before parsing. Also check for an extra # or a missing leading zero (e.g., #030201 not #32 1).

Can I convert hex to HSL directly? Not directly — go hex → RGB → HSL. The intermediate RGB step is necessary.

What's the difference between rgba() and the 8-digit hex? They represent the same thing. rgba(58, 134, 255, 0.8) and #3a86ffcc are equivalent. Browser support for 8-digit hex is solid from 2018 onwards (Chrome 62, Firefox 49, Safari 10).

How do I pick the right color format for CSS? Use hex for static colors in stylesheets (compact, designer-friendly). Use rgb() / rgba() when you need to manipulate channels dynamically in JavaScript. Use hsl() when you need to generate color palettes or calculate lighter/darker shades programmatically.

Related tools

Keep reading

All Toolmingotools are free & run in your browser

No sign-up, no upload, no watermark. Your files never leave your device.

Browse all tools