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.

GETPOSThttps://apibox.io.vn/v1/image-palette
Images & Codes▶ Try it online

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

NameInTypeRequiredDefault
filebodyfilenoImage (PNG, JPEG or SVG): multipart, raw body or file_base64.
urlquery|bodystringnoPublic URL of the image (up to 15 MB) instead of a file.
colorsquery|bodynumberno6Number of palette colours (1–16).
blurhash_xquery|bodynumberno4BlurHash horizontal components (1–9; 3 for portrait images).
blurhash_yquery|bodynumberno3BlurHash 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"

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

Start with 1,000 free requests every month. Get free API key →