LAB to hex converter
Lightness 53.2408 with a at 80.0925 and b at 67.2032 gives #FF0000, pure red, and the result tells you it was clipped to fit the screen range. Turn lab readings into usable screen colors. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- L
- 53.2408
- A
- 80.0925
- B
- 67.2032
- X
- 41.245661
- Y
- 21.267295
- Z
- 1.933391
- Resistance (Ω)
- 255
This LAB to hex converter turns CIE L*a*b* coordinates into a six-digit sRGB color string by following a transparent D65 conversion path. It validates L*, a*, and b*, reconstructs CIE XYZ, transforms XYZ into linear sRGB, applies the standard sRGB transfer curve, and rounds the resulting channels to bytes. Colors outside the displayable sRGB gamut are clamped safely and identified in the response instead of being allowed to produce malformed channels.
What the converter accepts and returns
Enter three numeric coordinates: l for CIE L* lightness, a for the green-to-red axis, and b for the blue-to-yellow axis. Lightness must be between zero and one hundred, while each chromatic coordinate must be between minus two hundred and two hundred. These bounds cover practical Lab values while catching misplaced fields, infinities, missing values, and obviously corrupt records before conversion.
The response repeats the validated coordinates and provides intermediate X, Y, and Z values scaled to the familiar zero-to-one-hundred convention. A false flag means the unbounded conversion landed inside sRGB. A true flag means at least one linear sRGB component fell below zero or above one and was clamped to the nearest displayable boundary.
The hex result is always valid, even in that case.
How Lab becomes XYZ and then a hex color
The calculation uses the standard D65 reference white associated with sRGB. First, L*, a*, and b* are rearranged into the three pivot terms commonly called f-x, f-y, and f-z. Each term passes through the inverse CIE Lab pivot: values above six twenty-ninths are cubed, while smaller values use the matching linear branch.
Multiplying those results by the D65 reference white reconstructs CIE XYZ. A fixed three-by-three matrix then converts XYZ into linear sRGB. At this stage, a component can legitimately be negative or greater than one because Lab describes colors beyond the sRGB display gamut.
The converter records that condition before altering the values. Each linear component then receives the official piecewise sRGB companding curve. The resulting encoded values are clamped to zero through one, multiplied by two hundred fifty-five, and rounded to the nearest integer.
Finally, every byte is formatted as exactly two uppercase hexadecimal digits and concatenated after a number sign.
Using gamut information and deterministic results
Lab covers a much larger set of theoretical colors than a typical sRGB screen can reproduce, so a converter needs an explicit policy for impossible results. This capability uses channel clipping, a straightforward and reproducible policy: negative linear components become zero and components above one become one. Keep the generated hex when you need a concrete CSS-compatible fallback, but retain the original Lab coordinates when color fidelity matters or when a future wide-gamut workflow may handle the source better.
For quality-control systems, treat a true flag as a reason to review or remap the color with a dedicated gamut-mapping strategy. Determinism is equally deliberate. The implementation performs only fixed arithmetic and formatting; it never reads the time, uses randomness, calls a remote service, consults a color profile installed on the host, or depends on browser rendering.
What you can do with it
Publish design tokens
Turn measured or authored Lab brand colors into stable six-digit hex values for CSS variables, documentation, and application theme files.
Check sRGB gamut limits
Identify Lab samples that require channel clipping before they can be represented on standard sRGB displays.
FAQ
Which white point is used?
The conversion uses the D65 reference white Xn 0.95047, Yn 1.00000, and Zn 1.08883, matching the standard sRGB conversion path.
Is the returned hex always six digits?
Yes. Each clamped RGB byte is rendered as two uppercase hexadecimal digits, including leading zeroes, after a number sign.
Does this converter preserve transparency?
No. CIE Lab input has no alpha coordinate, so the output is an opaque six-digit hex color rather than an eight-digit value.
What happens when a LAB color cannot be shown on screen?
Each channel that falls outside the displayable range is pushed to the nearest edge, so you still get a valid hex color. The result is marked as out of range, and extreme colors may shift in hue or intensity.
Which hex color is lightness 53.2408 with a at 80.0925 and b at 67.2032?
It is #FF0000, pure red, with red at 255 and green and blue at 0. The exact value lies just outside the screen range, so it is marked as clipped.
Related tools
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/lab-hex \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"l":53.2408,"a":80.0925,"b":67.2032}'const res = await fetch("https://api.kit.forhosting.com/color/lab-hex", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"l": 53.2408,
"a": 80.0925,
"b": 67.2032
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/lab-hex",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"l": 53.2408,
"a": 80.0925,
"b": 67.2032
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/lab-hex", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"l":53.2408,"a":80.0925,"b":67.2032}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"l":53.2408,"a":80.0925,"b":67.2032}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/lab-hex", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"l": 53.2408,
"a": 80.0925,
"b": 67.2032
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.lab_hex",
"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. |
Technical notes
The same deterministic calculation runs in the browser and through the API for $0.002 per successful request, with no network lookup, random input, or clock dependency.
What the converter accepts and returns
It also returns integer red, green, and blue channels, an uppercase six-digit hex string beginning with a number sign, and an out_of_gamut boolean.
Using gamut information and deterministic results
Clipping can change hue or chroma for extreme colors, so the out_of_gamut flag is important context rather than a warning to ignore. Identical JSON input therefore produces identical output. That makes the converter useful for snapshot tests, build pipelines, database normalization, and shared design-system tooling. Interactive conversion is free in the browser, while automated API conversion costs $0.002 per successful request and follows exactly the same mathematical path.
Integration use cases
Create deterministic test fixtures
Generate repeatable XYZ, RGB, and hex expectations for color libraries, importers, and data-validation pipelines.
Technical questions
How much does LAB to hex conversion cost?
It runs free in your browser. Through the API, each successful request costs $0.002; invalid input is rejected before a result is produced.
Why does the result say out_of_gamut?
Lab can describe colors outside sRGB. The flag is true when an unbounded linear RGB channel needed clipping below zero or above one.