Image palette & BlurHash API
Get the dominant colours of a PNG, JPEG or SVG with their share, the average colour, readable text colours, and BlurHash / ThumbHash placeholders.
Upload an image (PNG, JPEG or SVG, as multipart file, raw body or file_base64) or give a url. The image is reduced to a 128 px thumbnail, pixels that are more than half transparent are ignored, and the colours are grouped by median cut and refined with a few k-means rounds. You get up to 16 colours (colors, default 6) sorted by share, each with hex, RGB, HSL, the share of the image, the WCAG contrast ratio against white and black and the text colour that reads best on it; plus the average colour, the dominant colour and is_dark.
For lazy-loading placeholders the API also computes a BlurHash (blurhash, MIT; 4×3 components for landscape and 3×4 for portrait images, or blurhash_x / blurhash_y 1–9) and a ThumbHash (thumbhash, MIT; base64), each with a tiny PNG data URI you can put straight into src or a CSS background while the real image loads.
Images up to 25 megapixels; nothing is stored.
Parameters
| Name | In | Type | Required | Default | |
|---|---|---|---|---|---|
file | body | file | no | Image (PNG, JPEG or SVG): multipart, raw body or file_base64. | |
url | query|body | string | no | Public URL of the image (up to 15 MB) instead of a file. | |
colors | query|body | number | no | 6 | Number of palette colours (1–16). |
blurhash_x | query|body | number | no | 4 | BlurHash horizontal components (1–9; 3 for portrait images). |
blurhash_y | query|body | number | no | 3 | BlurHash vertical components (1–9; 4 for portrait images). |
Example
curl -X POST "https://apibox.io.vn/v1/image-palette?colors=5" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@./my-file"const form = new FormData();
form.append('file', fileInput.files[0]);
const res = await fetch('https://apibox.io.vn/v1/image-palette?colors=5', {
method: 'POST',
headers: { Authorization: 'Bearer YOUR_API_KEY' },
body: form,
});
console.log(await res.json());import requests
res = requests.post(
"https://apibox.io.vn/v1/image-palette?colors=5",
headers={"Authorization": "Bearer YOUR_API_KEY"},
files={"file": open("my-file", "rb")},
timeout=30,
)
print(res.json())<?php
$ch = curl_init('https://apibox.io.vn/v1/image-palette?colors=5');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY'],
CURLOPT_POSTFIELDS => ['file' => new CURLFile('my-file')],
]);
$response = curl_exec($ch);
print_r(json_decode($response, true));Response
{
"width": 320,
"height": 200,
"format": "jpeg",
"has_transparency": false,
"average": {
"hex": "#987b6e",
"rgb": [
152,
123,
110
],
"hsl": [
19,
17,
51
],
"text_color": "#000000",
"contrast_white": 3.89,
"contrast_black": 5.39
},
"dominant": {
"hex": "#13506d",
"rgb": [
19,
80,
109
],
"hsl": [
199,
70,
25
],
"share": 0.3336,
"text_color": "#ffffff",
"contrast_white": 8.76,
"contrast_black": 2.4
},
"palette": [
{
"hex": "#13506d",
"rgb": [
19,
80,
109
],
"hsl": [
199,
70,
25
],
"share": 0.3336,
"text_color": "#ffffff",
"contrast_white": 8.76,
"contrast_black": 2.4
},
{
"hex": "#ea825f",
"rgb": [
234,
130,
95
],
"hsl": [
15,
77,
65
],
"share": 0.3125,
"text_color": "#000000",
"contrast_white": 2.67,
"contrast_black": 7.86
},
{
"hex": "#cb977f",
"rgb": [
203,
151,
127
],
"hsl": [
19,
42,
65
],
"share": 0.2989,
"text_color": "#000000",
"contrast_white": 2.54,
"contrast_black": 8.27
},
{
"hex": "#fdd466",
"rgb": [
253,
212,
102
],
"hsl": [
44,
97,
70
],
"share": 0.0438,
"text_color": "#000000",
"contrast_white": 1.42,
"contrast_black": 14.79
},
{
"hex": "#556f7b",
"rgb": [
85,
111,
123
],
"hsl": [
199,
18,
41
],
"share": 0.0112,
"text_color": "#ffffff",
"contrast_white": 5.32,
"contrast_black": 3.95
}
],
"is_dark": false,
"blurhash": {
"hash": "L|LCI:a#WXs,}Tj@j@f7RQoJoJWE",
"components": [
4,
3
],
"placeholder": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAUCAIAAABj86gYAAAGfElEQVR4XlXNWXBT1xkH8PPQmb50Ojz1oTN56UMf0lKmaVqcBd…"
},
"thumbhash": {
"base64": "4DgOVJh3eIePeIiDeHd3j3b3eA==",
"placeholder": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAASCAYAAAA6yNxSAAAJcklEQVR4AQCBAH7/APp1Uf/5dFD/+HJO//dwTP/3b0r/+G9K//…",
"average": "#997d6f"
},
"method": "median cut seeds refined by k-means on a 128 px thumbnail (pixels with alpha < 50% ignored)"
}
Use cases
- Placeholder colours and BlurHash for product photos in an online shop
- Theme a page or card from the cover image
- Pick white or black captions over user images
- Index images by colour for search filters
FAQ
BlurHash or ThumbHash?
Both are tiny strings decoded by small client libraries. ThumbHash keeps the aspect ratio and transparency and has more detail; BlurHash has wider library support (iOS, Android, React Native).
Why does the palette not show a small detail colour?
Colours are weighted by area. Ask for more colors to see small regions; very small areas (under ~1%) may still merge with their neighbours.
How is the text colour chosen?
It is black or white, whichever has the higher WCAG 2 contrast ratio with that colour; both ratios are returned.
Related APIs
QR Code Generator
Generate QR codes as PNG or SVG with one GET request: URLs, text, WiFi logins, vCards, e-mail, SMS, phone and geo links. Custom colours, size and ECC.
|||Barcode Generator
Create Code 128 barcodes for labels, SKUs and shipping with a single request. SVG with human-readable text or PNG, custom height, width and colours.
▭Placeholder Image
Get placeholder images of any size for mockups and tests: /v1/placeholder/600x400.png. SVG with custom text and colours, or a solid-colour PNG.