Color Thief
Library to extract color palettes from photos
Color Thief is an open-source JavaScript library that extracts the dominant color and a representative color palette from an image. It is self-hostable and used in photo galleries and apps to generate color-aware layouts.
Key features
- Dominant color extraction
- Color palette generation
- Browser and Node support
- Tiny library
Pros & cons
Strengths
- Simple and reliable
- Widely used
Trade-offs
- Library, not an app
- Single-purpose
Is Color Thief secure?
OSV.dev has no published security advisories for Color Thief's repository. No known vulnerabilities is not proof of security: it means none have been publicly catalogued.
Source: OSV.dev, checked 2026-10-14. How this is measured.
Color Thief replaces
Health badge
Maintain Color Thief? Add its health score to your README. The badge links back to this page.
Last reviewed Aug 26, 2026 · 826 words
Color Thief is two functions. getColor(image) returns the dominant colour of an image as an [r, g, b] array, and getPalette(image, count) returns a list of representative colours. There is no server, no database, no port, and nothing to deploy; it is a JavaScript library with an MIT licence, 13,614 GitHub stars, and a history that goes back to 2011. It appears in this directory because self-hosted galleries and dashboards use it, and because people arrive here looking for "self-hosted colour extraction" and are surprised to find that the answer is 3 KB of code rather than a container.
Where it sits in a self-hosted stack
Three places, in order of how often I have seen it used. First, in the browser of a gallery front-end, to tint a card background or a lightbox frame with the photo's own colours. Second, in a Node script during import, so a static gallery or a small photos app stores a palette per image alongside width, height, and EXIF data. Third, in dashboard and media-server themes that pull an accent colour from album art or a poster. The big self-hosted photo apps do their own colour work internally; Immich and PhotoPrism do not depend on Color Thief, but Lychee themes and countless home-grown galleries do exactly this job with it.
The Node version is the one you will actually run
Install it, point it at a file, get colours back:
npm install colorthief
const ColorThief = require('colorthief');
const palette = await ColorThief.getPalette('./photos/2026-08-beach.jpg', 5);
// [[212, 184, 141], [64, 108, 152], [246, 244, 239], [31, 47, 66], [140, 158, 174]]
Run this once at import time and store the result. Do not call it per request: it decodes the whole image into memory, and a 24-megapixel JPEG is about 72 MB of raw pixels. Downscale to a 200-pixel thumbnail first with sharp, then extract; the palette is almost identical and the run takes milliseconds instead of a second. The 64 MB RAM figure in the catalogue is realistic for a single small image; batch processing a whole library wants either thumbnails or a queue.
The browser version needs CORS you control
In the browser Color Thief draws the image onto a canvas and reads pixels back. Browsers block that read if the image came from a different origin without CORS headers, and the failure is a silent tainted-canvas error. Two fixes: serve the images from the same origin as the page, which self-hosters can usually arrange, or set crossorigin="anonymous" on the <img> tag and add an Access-Control-Allow-Origin header on the object store or CDN that serves them. If your photos live in a MinIO bucket, that means a bucket CORS rule; without it nothing works and the console tells you why only if you look.
<img id="cover" src="https://media.example.com/cover.jpg" crossorigin="anonymous">
<script type="module">
import ColorThief from 'colorthief';
const img = document.getElementById('cover');
img.addEventListener('load', () => {
const [r, g, b] = new ColorThief().getColor(img);
document.body.style.setProperty('--accent', `rgb(${r} ${g} ${b})`);
});
</script>
What "dominant" means, and what it does not
Color Thief uses median-cut quantisation over the RGB values it samples. The third argument to getPalette is a quality setting: 10 (the default) inspects every tenth pixel, 1 inspects all of them and is proportionally slower. The result is the colour that covers the most area, which for a photo of a person against a grey wall is the grey wall. It does not know about faces, subjects, or what a designer would call "the interesting colour". If you want a pleasing accent rather than the statistically dominant one, take the palette of 5 and pick the entry with the highest saturation yourself; that is a 6-line function and it is how most galleries that look good with Color Thief are doing it.
It is also not a placeholder generator. The blurred preview trick that Immich and others use while a full image loads is a different technique (BlurHash or ThumbHash), and it is not a colour-search index; PhotoPrism's "find photos that are mostly blue" feature is built from its own classification, not from a palette library.
What I'd do
Extract at import in a Node script, on a 200-pixel thumbnail, store 5 colours as JSON next to the image record, and use the most saturated one for card backgrounds with the dominant one as a fallback. Never in the request path, never on the full-size original, and never across origins without a CORS rule you have tested in the browser console. Used that way it is one of the more dependable small libraries in the self-hosting toolbox: single purpose, unchanged API for years, and no operational weight at all.
Similar photo management apps
Immich
Photo ManagementHigh-performance self-hosted photo and video backup
Replaces Google Photos, iCloud Photos
PhotoPrism
Photo ManagementAI-powered photo app for the decentralized web
Replaces Google Photos
Ente Photos
Photo ManagementEnd-to-end encrypted photo storage and backup
Replaces Google Photos, iCloud Photos
DeepFace
Photo ManagementFace recognition and facial attribute analysis framework
Replaces AWS Rekognition, Azure Face API
gallery-dl
Photo ManagementCommand-line tool to download image galleries from websites
Replaces Manual downloads
darktable
Photo ManagementOpen-source photography workflow and RAW developer
Replaces Adobe Lightroom