HSL to HSV converter
Switch a color between the designer's HSL and the image editor's HSV: hsl(210, 80%, 45%) keeps hue 210 and becomes value 81%, with saturation recalculated for the new model. It works both ways. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Conversion direction
- hsl_to_hsv
- H
- 210
- S
- 80
- L
- 45
- S in
- 80
- S
- 88.8888888889
- Voltage (V)
- 81
HSL and HSV are two cylindrical color models that share the same hue angle on the wheel but treat the second and third axes differently: HSL uses saturation and lightness, while HSV uses saturation and value (brightness). Designers often pick colors in HSL because lightness moves toward black and white symmetrically, whereas game engines, image editors, and many video pipelines speak HSV because value maps more directly to maximum channel brightness. This converter takes a direction—HSL to HSV or HSV to HSL—plus hue in degrees from zero through three hundred sixty, saturation as a percentage, and either lightness or value as a percentage from zero through one hundred, then returns the converted triple with both model objects filled in.
How HSL and HSV relate on the same hue
Hue is shared: zero degrees is pure red, one hundred twenty is pure green, two hundred forty is pure blue, and three hundred sixty closes the circle back at red. The models diverge on how vividness and brightness are stored. In HSL, lightness runs from black at zero percent through a pure mid-tone near fifty percent up to white at one hundred percent, and HSL saturation stretches a gray of that lightness toward the fully chromatic color at the chosen hue.
In HSV, value is the maximum of the underlying RGB channels on a unit scale, so one hundred percent value is the brightest color of that hue and saturation, and zero percent value is always black regardless of saturation. Because the geometries differ, the numeric saturation in HSL is not the same number as the numeric saturation in HSV for most colors even when the perceived color matches after conversion.
The closed-form path used here works on the unit interval: for HSL to HSV, value equals lightness plus HSL saturation times the minimum of lightness and one minus lightness, and HSV saturation is zero when value is zero otherwise two times one minus lightness over value. For HSV to HSL, lightness equals value times one minus half the HSV saturation, and HSL saturation is zero at black or white otherwise the gap between value and lightness divided by the minimum of lightness and one minus lightness. Hue is copied unchanged.
Hue must lie in the closed interval from zero to three hundred sixty; saturation, lightness, and value must each lie between zero and one hundred percent inclusive.
Where HSL to HSV conversion shows up in real work
Design systems often author brand ramps in HSL so product teams can step lightness for accessible contrast while keeping hue and a perceptual saturation band stable, yet native mobile themes, Unity and Unreal material pickers, and many graphics libraries expect HSV or HSB for artist-facing brightness controls. Data visualization and generative art tools that expose a hue wheel with a value slider need a reliable inverse when exporting tokens stored as HSL custom properties.
Video and broadcast pipelines that document colors in HSV for camera grading still need HSL when feeding CSS and design documentation. Curriculum and bootcamp lessons teach cylindrical models side by side and need a single trusted oracle for homework keys that match textbook identities. Accessibility workflows that adjust perceived lightness in HSL and then hand off to an HSV-based editor still need exact channel mapping without browser-only APIs.
If you later need HSL to RGB, multi-format HEX LAB CMYK conversion, or WCAG contrast checks, treat those as separate search intents and landings rather than overloading this dedicated HSL to HSV converter page.
What you can do with it
Design tokens across HSL and HSV tools
Convert HSL brand ramps into HSV triples for mobile themes, game material pickers, and image editors that expose value instead of lightness.
Engine and shader parameter tables
Map artist HSV swatches back to HSL for CSS design systems and documentation tables that must stay bit-stable across pipelines.
FAQ
What ranges do hue, saturation, lightness, and value accept?
Hue h must be between 0 and 360 degrees inclusive. Saturation s, lightness l, and value v are percentages from 0 to 100.
Is HSL saturation the same number as HSV saturation?
No. The models define saturation differently. This converter applies the closed-form identities so the resulting color matches while the numeric S values generally differ.
Does hue change between HSL and HSV?
No. Hue is shared by both models and is copied unchanged. Only saturation and the lightness or value axis are recomputed.
What does it cost?
The browser tool is free and runs locally.
What does hsl(210, 80%, 45%) become in HSV?
Hue stays at 210 and value becomes 81%. Saturation rises above the original 80%, because HSV measures how vivid a color is in a different way from HSL.
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/hsl-hsv \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"direction":"hsl_to_hsv","h":210,"s":80}'const res = await fetch("https://api.kit.forhosting.com/color/hsl-hsv", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"direction": "hsl_to_hsv",
"h": 210,
"s": 80
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/hsl-hsv",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"direction": "hsl_to_hsv",
"h": 210,
"s": 80
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/hsl-hsv", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"direction":"hsl_to_hsv","h":210,"s":80}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"direction":"hsl_to_hsv","h":210,"s":80}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/hsl-hsv", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"direction": "hsl_to_hsv",
"h": 210,
"s": 80
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.hsl_hsv",
"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
Channels outside the legal ranges fail with a clear invalid_input error so bad tokens never silently wrap or clamp without notice.
How HSL and HSV relate on the same hue
The pipeline is pure floating-point arithmetic with no random seeds, no wall-clock timestamps, and no network calls, so identical inputs always produce identical JSON.
What you send and what you get back
Classic checks include pure mid red in HSL as hue zero, saturation one hundred, lightness fifty mapping to HSV value one hundred with full saturation; black as zero lightness or zero value collapsing to achromatic black; and grays with zero saturation mapping to zero saturation in the other model with value or lightness following the source brightness axis. Wire the free browser form for palette exploration and design reviews, then call the identical contract from scripts when you need bulk conversion of design tokens or engine materials. Send a direction string of either hsl_to_hsv or hsv_to_hsl, a finite hue h in degrees, and a finite saturation s as a percentage in the source model. When direction is hsl_to_hsv you must also send lightness l as a percentage from zero to one hundred; when direction is hsv_to_hsl you must send value v as a percentage in the same band. Missing fields, non-numeric strings, NaN, Infinity, and out-of-range channels fail with invalid_input and are not charged. On success for HSL to HSV the response echoes cleaned direction, h, source saturation as s_in, input lightness l, output HSV saturation s and value v, nested hsl and hsv objects, and a short formula note. On success for HSV to HSL the response echoes direction, h, s_in, input value v, output HSL saturation s and lightness l, nested hsv and hsl objects, and the inverse formula note. Pricing for successful API calls is the published base of $0.002 per item; validation failures do not consume prepaid balance.
Where HSL to HSV conversion shows up in real work
Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance.
Integration use cases
Bulk token and curriculum fixtures
Script bidirectional conversion for regression fixtures, homework keys, and palette exports with one deterministic API at $0.002 per item.
Technical questions
What does the direction field do?
Use hsl_to_hsv when the input is HSL (send h, s, and l). Use hsv_to_hsl when the input is HSV (send h, s, and v). Other direction strings are rejected.