Skip to content

How to Convert RGB to Color Name in Python

Learn how to convert RGB values to human-readable color names like 'Navy Blue' in Python using exact matching or closest-color algorithms with the webcolors library.

Human-readable color names like "Navy Blue" are more intuitive than RGB tuples (0, 0, 128). Converting between them requires either exact matching against known colors or finding the mathematically closest named color.

This guide covers both approaches with practical implementations.

Exact Match with webcolors

For standard CSS3 colors, use direct lookup:

pip install webcolors
import webcolors

def rgb_to_name_exact(rgb_tuple):
    """Get exact color name or None if no match."""
    try:
        return webcolors.rgb_to_name(rgb_tuple)
    except ValueError:
        return None

print(rgb_to_name_exact((255, 0, 0)))    # red
print(rgb_to_name_exact((0, 0, 128)))    # navy
print(rgb_to_name_exact((250, 5, 5)))    # None (no exact match)

Closest Match with Euclidean Distance

Find the nearest named color mathematically:

import webcolors
import math


def closest_color(rgb):
    """Find the closest CSS3 named color."""
    min_distance = float('inf')
    closest_name = None

    for name in webcolors.names("css3"):
        r, g, b = webcolors.name_to_rgb(name)

        distance = math.sqrt(
            (r - rgb[0]) ** 2 +
            (g - rgb[1]) ** 2 +
            (b - rgb[2]) ** 2
        )

        if distance < min_distance:
            min_distance = distance
            closest_name = name

    return closest_name


print(closest_color((250, 0, 0)))    # red
print(closest_color((250, 10, 10)))  # red
print(closest_color((100, 50, 75)))  # dimgray (or similar)

Combined Approach

Try exact match first, then fall back to closest:

import webcolors
import math

def rgb_to_name(rgb):
    """Get color name: exact if available, otherwise closest."""
    try:
        return webcolors.rgb_to_name(rgb)
    except ValueError:
        pass
    
    min_distance = float('inf')
    closest_name = None
    
    for name in webcolors.names("css3"):
        r, g, b = webcolors.name_to_rgb(name)
        distance = sum((a - b) ** 2 for a, b in zip(rgb, (r, g, b)))
        
        if distance < min_distance:
            min_distance = distance
            closest_name = name
    
    return closest_name

print(rgb_to_name((255, 0, 0)))      # red (exact)
print(rgb_to_name((255, 10, 10)))    # red (closest)

Hex Code to Color Name

Common in web development:

import webcolors
import math

def rgb_to_name_with_confidence(rgb):
    """Get color name with distance score."""
    try:
        return {
            'name': webcolors.rgb_to_name(rgb),
            'distance': 0,
            'exact_match': True
        }
    except ValueError:
        pass
    
    min_distance = float('inf')
    closest_name = None
    
    for name in webcolors.names("css3"):
        r, g, b = webcolors.name_to_rgb(name)
        distance = math.sqrt(sum((a - b) ** 2 for a, b in zip(rgb, (r, g, b))))
        
        if distance < min_distance:
            min_distance = distance
            closest_name = name
    
    confidence = 1 - (min_distance / 441.67)
    
    return {
        'name': closest_name,
        'distance': round(min_distance, 2),
        'confidence': round(confidence, 2),
        'exact_match': False
    }

print(rgb_to_name_with_confidence((255, 0, 0)))

print(rgb_to_name_with_confidence((200, 50, 50)))

With Color Distance and Confidence

Return both name and match quality:

import webcolors
import math

def rgb_to_name_with_confidence(rgb):
    """Get color name with distance score."""
    try:
        return {
            'name': webcolors.rgb_to_name(rgb),
            'distance': 0,
            'exact_match': True
        }
    except ValueError:
        pass
    
    min_distance = float('inf')
    closest_name = None
    
    for name in webcolors.names("css3"):
        r, g, b = webcolors.name_to_rgb(name)
        distance = math.sqrt(sum((a - b) ** 2 for a, b in zip(rgb, (r, g, b))))
        
        if distance < min_distance:
            min_distance = distance
            closest_name = name
    
    confidence = 1 - (min_distance / 441.67)
    
    return {
        'name': closest_name,
        'distance': round(min_distance, 2),
        'confidence': round(confidence, 2),
        'exact_match': False
    }

print(rgb_to_name_with_confidence((255, 0, 0)))

print(rgb_to_name_with_confidence((200, 50, 50)))

Color Categories (Simple Grouping)

For basic color classification:

def get_basic_color(rgb):
    """Classify RGB into basic color category."""
    r, g, b = rgb
    
    if abs(r - g) < 20 and abs(g - b) < 20 and abs(r - b) < 20:
        if max(r, g, b) < 50:
            return "black"
        elif min(r, g, b) > 200:
            return "white"
        return "gray"
    
    max_val = max(r, g, b)
    
    if r == max_val:
        if g > b:
            return "orange" if g > 100 else "red"
        return "red" if b < 100 else "pink"
    elif g == max_val:
        if b > r:
            return "cyan" if b > 100 else "green"
        return "green" if r < 100 else "yellow"
    else:  # b == max_val
        if r > g:
            return "purple" if r > 100 else "blue"
        return "blue"

print(get_basic_color((255, 0, 0)))    # red
print(get_basic_color((50, 50, 50)))   # gray
print(get_basic_color((255, 165, 0)))  # orange

Using scipy for Efficient Distance Calculation

For processing many colors:

import webcolors
import numpy as np
from scipy.spatial import KDTree

def build_color_tree():
    colors = []
    names = []
    
    for name in webcolors.names("css3"):
        colors.append(webcolors.name_to_rgb(name))
        names.append(name)
    
    return KDTree(colors), names

COLOR_TREE, COLOR_NAMES = build_color_tree()

def rgb_to_name_fast(rgb):
    """Fast color name lookup using KDTree."""
    distance, index = COLOR_TREE.query(rgb)
    return COLOR_NAMES[index]

print(rgb_to_name_fast((200, 50, 50)))  # firebrick

Batch Processing

Convert multiple colors efficiently:

import webcolors
import math

def rgb_to_name(rgb):
    """Get color name: exact if available, otherwise closest."""
    try:
        return webcolors.rgb_to_name(rgb)
    except ValueError:
        pass
    
    min_distance = float('inf')
    closest_name = None
    
    for name in webcolors.names("css3"):
        r, g, b = webcolors.name_to_rgb(name)
        distance = sum((a - b) ** 2 for a, b in zip(rgb, (r, g, b)))
        
        if distance < min_distance:
            min_distance = distance
            closest_name = name
    
    return closest_name

def batch_rgb_to_names(rgb_list):
    """Convert list of RGB tuples to names."""
    return [rgb_to_name(rgb) for rgb in rgb_list]

colors = [
    (255, 0, 0),
    (0, 255, 0),
    (0, 0, 255),
    (255, 165, 0),
    (128, 0, 128)
]

names = batch_rgb_to_names(colors)
print(dict(zip(colors, names)))

Practical Example: Image Color Analysis

from PIL import Image
from collections import Counter

def get_dominant_colors(image_path, n_colors=5):
    """Get most common color names in an image."""
    img = Image.open(image_path)
    img = img.convert('RGB')
    img = img.resize((100, 100))  # Reduce for speed
    
    pixels = list(img.getdata())
    
    color_names = [rgb_to_name(pixel) for pixel in pixels]
    
    return Counter(color_names).most_common(n_colors)

Summary

Input Method Use Case
Exact RGB webcolors.rgb_to_name() Standard CSS colors
Any RGB Euclidean distance Real-world colors
Hex code hex_to_rgb() + distance Web development
Bulk processing KDTree + scipy Image analysis
Navigation