Quantile color scale buckets
The quantile color scale buckets tool assigns a numeric value to one of a fixed number of equal-width intervals and returns the corresponding color between two hexadecimal endpoints.
Run — free
Give it a value, an inclusive minimum and maximum, a bucket count, and the colors at both ends. It validates every input, handles the upper boundary explicitly, and always produces the same result. Use it for dashboards, maps, score bands, legends, reports, and any workflow that needs repeatable classification instead of a continuously changing gradient.
Turn a continuous range into dependable categories
A continuous gradient can imply more precision than the underlying measurement deserves. Buckets make the decision visible: every value in the same interval receives exactly the same color. Enter the numeric value, the inclusive lower and upper endpoints, and the number of buckets you want. The tool divides the range into equal-width intervals, numbers them from one, and reports both the zero-based bucket index and its numeric boundaries. All intervals include their lower boundary and exclude their upper boundary, except the final interval, which includes the declared maximum. That explicit rule prevents adjacent systems from disagreeing about values that fall exactly on a boundary. The returned range flag also tells a consumer whether the reported upper boundary is inclusive. This capability is useful when a chart renderer, spreadsheet export, backend service, and browser view must classify values identically. It does not inspect a dataset or calculate statistical quantiles; the supplied minimum and maximum define the scale, so results never depend on hidden observations or their ordering.
Build the color scale by deterministic RGB interpolation
The first bucket uses the start color and the last bucket uses the end color. Colors between them are calculated by interpolating the red, green, and blue channels independently, then rounding each channel to the nearest integer. Position is based on the bucket index rather than the raw value, which guarantees that two values assigned to the same bucket receive the same hexadecimal color. Six-digit hexadecimal endpoints may include or omit the leading hash, and output is normalized to lowercase with a hash. RGB interpolation is intentionally straightforward and reproducible across the API and browser implementation. It is not a perceptual color-space model, so users designing accessibility-sensitive palettes should choose endpoints whose intermediate colors remain distinguishable and maintain suitable contrast. The result includes the selected color, bucket index, human-oriented bucket number, total bucket count, and the numeric bounds of the chosen interval. With these fields, you can color a mark while also generating a matching tooltip, legend label, validation record, or audit entry without recreating the boundary calculation elsewhere.
Validate ranges before they reach a visualization
Silent clamping is convenient until an upstream defect paints an impossible value as if it were valid. This tool instead rejects non-finite numbers, reversed or zero-width ranges, values outside the inclusive range, malformed endpoint colors, and bucket counts that are not integers from two through 256. That makes failures actionable and keeps a dashboard from concealing bad measurements. Decide the scale limits in the system that owns the metric, then reuse those exact limits for every value in the series. If your data distribution is highly skewed and you truly need equal-population quantiles, calculate those quantile breakpoints first; this capability creates equal-width buckets between explicit endpoints. For a stable legend, call the same mapping rules when generating labels and when coloring observations. The maximum receives special handling so floating-point division cannot place it beyond the final index. Other exact boundaries naturally enter the following bucket, matching the documented lower-inclusive convention. The browser implementation and paid API share the same pure algorithm, allowing an interactive preview before the same mapping is embedded in an automated pipeline for $0.002 per request.
What you can do with it
Color a performance dashboard
Assign consistent colors to latency, revenue, utilization, or quality values across cards and charts.
Create a choropleth classification
Map regional measurements into fixed numeric intervals and keep map fills aligned with the legend.
Standardize risk bands
Apply a shared range, bucket count, and endpoint palette to repeatable scores in reports and exports.
FAQ
Does this calculate statistical quantiles from a dataset?
No. It creates equal-width buckets between the explicit minimum and maximum. It does not receive or analyze a dataset.
What happens when the value equals the maximum?
The maximum is valid and is assigned to the final bucket, whose upper boundary is inclusive.
Which color formats are accepted?
Use a six-digit hexadecimal RGB color with or without a leading hash. The returned color is lowercase and includes the hash.
How are intermediate colors calculated?
Red, green, and blue channels are interpolated independently according to bucket position and rounded to integer channel values.
Can values outside the range be clamped?
No. An out-of-range value is rejected so invalid measurements are not silently presented as valid endpoint colors.
What does it cost?
The API costs $0.002 per request. The same deterministic calculation can run free in the browser.
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/scale-buckets \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"value":72,"min":0,"max":100,"buckets":5,"start_color":"#ffffcc","end_color":"#800026"}'const res = await fetch("https://api.kit.forhosting.com/color/scale-buckets", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"value": 72,
"min": 0,
"max": 100,
"buckets": 5,
"start_color": "#ffffcc",
"end_color": "#800026"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/color/scale-buckets",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"value": 72,
"min": 0,
"max": 100,
"buckets": 5,
"start_color": "#ffffcc",
"end_color": "#800026"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/color/scale-buckets", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"value":72,"min":0,"max":100,"buckets":5,"start_color":"#ffffcc","end_color":"#800026"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"value":72,"min":0,"max":100,"buckets":5,"start_color":"#ffffcc","end_color":"#800026"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/color/scale-buckets", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"value": 72,
"min": 0,
"max": 100,
"buckets": 5,
"start_color": "#ffffcc",
"end_color": "#800026"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "color.scale_buckets",
"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. |