Generate an analogous color palette from any hex color
Create a predictable analogous color palette from one hexadecimal color and the exact number of swatches you need.
Run — free
The generator converts the base color to HSL, distributes the requested colors evenly across a sixty-degree hue window centered on the original hue, and converts every result back to normalized hexadecimal notation. A one-color request returns the base hue itself, while larger palettes include both thirty-degree boundaries. The same deterministic calculation works in the browser and API, making the result suitable for design tokens, charts, illustrations, and repeatable build pipelines without random choices or network dependencies.
Choose the base color and palette size
Begin with a CSS hexadecimal color written with three or six digits, optionally preceded by a hash. Short notation is expanded before any conversion, so #36c and #3366cc describe the same starting color and produce the same normalized output. Then choose count, which controls the exact number of swatches returned. Count must be an integer of at least one; zero and negative values are rejected because they cannot describe a palette. When count is one, the generator returns the base hue without shifting it. When count is two, it returns the two boundary hues at minus thirty and plus thirty degrees. With three colors, the base sits between those boundaries. Larger counts add equal intervals throughout the same window rather than widening the harmony. This distinction is useful when a component library needs five tokens while a small illustration needs only three: both sets preserve the same analogous range and visual intent. Saturation and lightness remain equal to those of the base color, which isolates hue as the only changing dimension. The output echoes the normalized base color and requested count, then provides every swatch with its zero-based index, signed hue offset, wrapped hue angle, and lowercase six-digit hex value. Use the index for stable token names and the offset when documenting how each generated color relates to the original source color.
Understand even spacing around the hue wheel
Analogous colors occupy neighboring positions on a circular hue wheel. This capability uses a fixed window from thirty degrees below the base hue to thirty degrees above it, giving a total span of sixty degrees. For any count greater than one, spacing is calculated by dividing that span by count minus one. Five requested colors therefore use offsets of minus thirty, minus fifteen, zero, plus fifteen, and plus thirty degrees. Four colors use minus thirty, minus ten, plus ten, and plus thirty degrees. Because hue is circular, an offset that crosses zero wraps around toward three hundred sixty instead of becoming an invalid negative angle. A red base can therefore produce neighbors on both the magenta and orange sides while remaining a compact family. The algorithm first parses RGB channels from the supplied hex value, converts those channels to HSL, applies each offset, and converts the shifted HSL value back to integer RGB and hex. Channel rounding is deterministic, and displayed angles are rounded to stable precision, so identical input produces byte-for-byte identical JSON across repeated calls. Neutral colors are a special but valid case: gray has zero saturation, so changing its mathematical hue cannot alter the visible RGB result. The response may consequently contain repeated gray hex values at different hue offsets. That is accurate color mathematics, not an error, because a hue becomes visually meaningful only when saturation is above zero.
Apply the palette in production workflows
Use the generated array wherever a repeatable family of related colors is more important than dramatic contrast. A design-system build can map indices to custom properties such as accent-1 through accent-5 and regenerate them whenever the primary brand color changes. A chart builder can request the number of series present in a report, then assign swatches in array order so closely related categories appear cohesive. Illustration tooling can turn one art-directed seed into a controlled set for highlights, fills, and shadows, although lightness adjustments should be performed separately when tonal depth is required. The result is also convenient for snapshot tests because it contains no random seed, timestamp, network response, or model-generated variation. Store the base color and count as the source of truth instead of copying disconnected swatches into several repositories. Before using any generated color for text, icons, or controls, run a contrast check against its actual background; analogous harmony does not guarantee WCAG contrast, and preserving the base lightness can make neighboring swatches equally unsuitable for small text. The API price for a successful item is $0.002, while the browser version can support quick visual exploration. Validate count in user interfaces before submitting it, and surface the returned validation message when it is below one or not an integer. This keeps configuration mistakes distinct from downstream rendering problems and makes automated theme pipelines easier to diagnose.
What you can do with it
Create design-system accent tokens
Turn one approved brand color into an exact number of stable neighboring hue tokens for components and themes.
Color related chart series
Match the palette count to the number of related series and assign evenly spaced colors in deterministic array order.
Build illustration color families
Derive cohesive fill and detail colors from an art-directed seed without random palette selection or manual hue calculations.
FAQ
What happens when count is one?
The single returned color uses the base hue with an offset of zero degrees.
Are the endpoints included?
Yes. For counts above one, the first color is at minus 30 degrees and the last is at plus 30 degrees.
Which color formats are accepted?
Three-digit and six-digit hexadecimal CSS colors are accepted, with or without a leading hash.
Why can gray produce duplicate hex values?
Gray has zero saturation, so hue changes are mathematically present but do not change its visible RGB channels.
How much does an API request cost?
A successful API item costs $0.002. The browser tool is available for interactive use.
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/analogous-palette \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"color":"#3366cc","count":5}'const res = await fetch("https://api.kit.forhosting.com/color/analogous-palette", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"color": "#3366cc",
"count": 5
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/analogous-palette",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"color": "#3366cc",
"count": 5
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/analogous-palette", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"color":"#3366cc","count":5}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"color":"#3366cc","count":5}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/analogous-palette", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"color": "#3366cc",
"count": 5
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.analogous_palette",
"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. |