Count unique colors in an image and find the top five
The unique image color counter turns sampled RGB pixels into a clear inventory of the colors that actually occur.
Run — free
It reports the exact number of distinct RGB triples, the total represented pixel count, and the five colors that appear most often. Repeated records are combined automatically, while an optional count lets one sample stand for many identical pixels. The calculation is deterministic and uses exact channel values rather than clustering nearby shades, making it useful when precise equality matters in exported graphics, indexed artwork, screenshots, and test fixtures.
Prepare pixel samples for an exact count
Provide pixels as RGB records with red, green, and blue channels from 0 through 255. Each record represents one pixel unless you add a positive count, which is useful when an image decoder or histogram has already combined repeated values. The tool treats a color as unique only when its complete RGB triple differs. For example, RGB 20, 40, 60 and RGB 20, 40, 61 are two distinct colors even though they may look almost identical. Alpha is intentionally outside this contract, so samples should already reflect whatever transparency or compositing policy your workflow requires. You may submit the same RGB value more than once; all occurrences and supplied counts are added together before ranking. This design supports both raw pixel streams and compact histograms without changing the meaning of the answer. An empty list cannot describe an image sample and therefore returns an input error instead of a misleading zero. Invalid channels, invalid counts, unsupported fields, and oversized sample lists are also rejected so accidental data-shape problems remain visible rather than silently changing the result.
Understand distinct colors and the top-five ranking
The distinct color total is the size of the exact RGB frequency map after duplicate records have been merged. The total pixel figure is the sum of every record's count, using one when count is omitted. The top colors list contains no more than five entries and may contain fewer when fewer than five unique colors occur. Entries are sorted from the largest count to the smallest. If two colors have equal counts, lower red, then lower green, then lower blue values come first, which makes tied results stable across calls and machines. Every ranked entry includes uppercase hexadecimal notation, the original RGB channels, its absolute count, and a frequency measured against the total represented pixels. Frequency is rounded to six decimal places for compact, repeatable JSON. This is not a perceptual palette extractor: neighboring shades remain separate rather than being blended into a cluster center. That distinction is important for checking indexed assets, detecting unintended anti-aliasing colors, or confirming exact output from an image transformation. Use a palette-clustering tool instead when visual similarity matters more than exact pixel identity.
Use the result in audits, optimization, and tests
A color count is a compact diagnostic for graphics pipelines. Before shipping an icon, compare its distinct color total with the intended palette size; an unexpected increase can reveal anti-aliasing, an incorrect export mode, or a background that was flattened with slightly different values. For compression work, the five leading frequencies show whether a small set of colors dominates the image and may guide a later choice of indexed encoding or palette reduction. In automated tests, store the distinct total and leading colors as assertions after rendering, resizing, or format conversion, while remembering that any operation that interpolates pixels can legitimately create new RGB values. The optional count field also makes the capability convenient for server-side decoders that already produce histograms, because they can send one record per observed color rather than every pixel. No image file is fetched or decoded by this capability: your application supplies the samples. Processing is local and deterministic, with no network request, randomness, or retained state. Browser execution is available for interactive checks, while an API request costs $0.002 when you integrate the same calculation into a repeatable workflow.
What you can do with it
Audit an indexed graphic
Confirm that an exported icon or sprite contains no more exact RGB colors than its intended palette.
Detect unexpected rendering shades
Spot extra colors introduced by anti-aliasing, interpolation, compositing, or a changed export setting.
Summarize a decoder histogram
Turn weighted RGB histogram records into an exact distinct count and a stable top-five frequency list.
FAQ
What counts as a distinct color?
A distinct color is a unique combination of red, green, and blue integer channels. Even a one-channel difference creates another color.
Does the tool cluster similar colors?
No. It compares RGB values exactly and never merges nearby shades. Use a dominant-palette tool for perceptual clustering.
What does the count field do?
It lets one RGB record represent multiple identical pixels. When omitted, the record represents one pixel.
What happens when fewer than five colors occur?
The top_colors list returns every observed color, so it contains fewer than five entries.
What does an API request cost?
Each API request costs $0.002. The same deterministic calculation can also run 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/image/color-count \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"pixels":[{"r":255,"g":0,"b":0,"count":4},{"r":0,"g":0,"b":255,"count":2},{"r":255,"g":0,"b":0}]}'const res = await fetch("https://api.kit.forhosting.com/image/color-count", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"pixels": [
{
"r": 255,
"g": 0,
"b": 0,
"count": 4
},
{
"r": 0,
"g": 0,
"b": 255,
"count": 2
},
{
"r": 255,
"g": 0,
"b": 0
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/image/color-count",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"pixels": [
{
"r": 255,
"g": 0,
"b": 0,
"count": 4
},
{
"r": 0,
"g": 0,
"b": 255,
"count": 2
},
{
"r": 255,
"g": 0,
"b": 0
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/image/color-count", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"pixels":[{"r":255,"g":0,"b":0,"count":4},{"r":0,"g":0,"b":255,"count":2},{"r":255,"g":0,"b":0}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"pixels":[{"r":255,"g":0,"b":0,"count":4},{"r":0,"g":0,"b":255,"count":2},{"r":255,"g":0,"b":0}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/image/color-count", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"pixels": [
{
"r": 255,
"g": 0,
"b": 0,
"count": 4
},
{
"r": 0,
"g": 0,
"b": 255,
"count": 2
},
{
"r": 255,
"g": 0,
"b": 0
}
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "image.color_count",
"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.
Limits
max_mb | 15 |
max_megapixels | 12 |
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. |