Convert RGB to HSL
Convert an RGB color into its HSL equivalent with a small, predictable result that is easy to use in design tools, stylesheets, and application code.
Run — free
Supply red, green, and blue channel values between 0 and 255. The converter returns hue on a 0–360 degree circle and saturation and lightness as percentages from 0 to 100. It rejects missing, nonnumeric, infinite, or out-of-range channels instead of silently clipping them, so mistakes remain visible and downstream color data stays trustworthy.
Enter the RGB channels correctly
Provide three numeric fields named red, green, and blue in their compact forms: r, g, and b. Every channel must be between 0 and 255, including both endpoints. Zero means that the channel contributes no intensity, while 255 means full intensity. Intermediate values may be integers or decimals, which is useful when another calculation produces interpolated colors. The converter deliberately does not clamp values. If a channel is negative, greater than 255, missing, not a number, or infinite, the request returns an input error. This strict behavior makes automated workflows safer because an invalid source value cannot quietly turn into a plausible but incorrect color. For a familiar first test, use r 255, g 0, and b 0; the result is red at zero degrees of hue, full saturation, and fifty percent lightness. When copying values from CSS, submit only the channel numbers rather than the rgb() wrapper, commas, or percentage symbols. Keeping input numeric also avoids ambiguity between the 0–255 RGB scale and percentage-based RGB notation used by some design systems.
Understand how the HSL result is calculated
The conversion first normalizes each RGB channel by dividing it by 255. It then finds the largest and smallest normalized channels. Their average becomes lightness, and their difference, called chroma, determines whether the color has saturation and a meaningful hue. When chroma is zero, the color is a shade of gray: saturation is zero and hue is reported as zero by convention because no position on the color wheel is visually distinguishable. For colorful values, saturation is chroma adjusted for the current lightness, while hue depends on which RGB channel is largest. Red, green, and blue occupy different sectors of the hue circle, and the relative channel differences select a position within that sector. The returned hue is expressed in degrees from zero up to, but not including, 360. Saturation and lightness are multiplied by 100 and expressed as percentages. Results are rounded to four decimal places to provide useful precision while keeping responses stable and readable. This is the standard RGB-to-HSL transformation; it reorganizes the same color information and does not apply color management, gamma correction, or profile conversion.
Use HSL in design and application workflows
HSL is often easier than RGB when people need to reason about variations. Hue identifies the broad color family, saturation controls how vivid or gray the color appears, and lightness moves it toward black or white. After converting a brand color, a developer can keep its hue steady while adjusting lightness for hover, pressed, or disabled states. A data pipeline can normalize mixed color records into a common HSL representation before sorting or grouping them. A quality check can also compare returned values with design tokens and reject malformed RGB channels early. Remember that equal numeric changes do not guarantee equal perceived visual changes; HSL is convenient for controls but is not a perceptually uniform color space. Also preserve the original RGB values if exact round trips matter, because rounded output can introduce a small difference when converted back. The operation is deterministic and local to the supplied numbers: it makes no network request, uses no random value, and depends on no clock or external color database. That makes identical inputs produce identical outputs across repeated calls, which is suitable for tests, build scripts, API integrations, and reproducible design-system tooling.
What you can do with it
Build color controls
Convert stored RGB channels before presenting hue, saturation, and lightness sliders in an editor.
Create interface variants
Find a base color's HSL values, then adjust lightness or saturation for interactive UI states.
Normalize color records
Turn RGB fields into a consistent HSL structure for application data, testing, or reporting.
FAQ
What RGB values are accepted?
Each of r, g, and b must be a finite number between 0 and 255 inclusive.
What ranges does the result use?
Hue uses degrees from 0 to 360, while saturation and lightness use percentages from 0 to 100.
What hue is returned for gray colors?
Gray has no visually meaningful hue, so the converter returns zero degrees and zero percent saturation by convention.
Are out-of-range channels clipped?
No. Any value below 0 or above 255 produces an invalid input error so source-data mistakes remain visible.
How much does an API conversion cost?
Each API request costs $0.002. The browser experience can run the same deterministic conversion locally.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/color/rgb-to-hsl \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"r":255,"g":128,"b":64}'const res = await fetch("https://api.kit.forhosting.com/color/rgb-to-hsl", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"r": 255,
"g": 128,
"b": 64
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/rgb-to-hsl",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"r": 255,
"g": 128,
"b": 64
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/rgb-to-hsl", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"r":255,"g":128,"b":64}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"r":255,"g":128,"b":64}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/rgb-to-hsl", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"r": 255,
"g": 128,
"b": 64
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.rgb_to_hsl",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |