Just File Tools

Color Palette Extractor

Extract the dominant colors from an image as a HEX palette

Drop an image here or click to browse — PNG, JPG, GIF, WebP

Max file size: 50MB

Files are processed in your browser. Nothing is uploaded.

How to Color Palette Extractor Online

Extract the dominant colors from an image as a HEX palette using k-means clustering.

  1. Drag an image into the drop zone, or click to pick one from your computer. PNG, JPG, GIF, and WebP all work.
  2. Set the palette size — 6 is the default and works well for most images. Smaller values give bolder, fewer colors; larger values give finer variation.
  3. Wait briefly for the extractor to sample pixels and run clustering. Most images complete in well under a second.
  4. Each palette entry shows the HEX value and the percentage of pixels assigned to it — useful for telling 'main brand color' from 'background tint.'
  5. Click any swatch to copy its HEX value. Click 'Copy all' to put the entire palette on your clipboard as a comma-separated list.
  6. Drag in a different image at any time to re-extract — previous results are replaced.

About Color Palette Extractor

Extracting a palette from an image is one of those tasks that sounds trivial and turns out to need real thought. The naive approach — count every unique RGB value, take the top N — fails badly because real photographs have millions of slightly-different RGB values, none of which appear more than a few times. The right approach is **clustering**: group similar pixels into N buckets, then return the average color of each bucket. This is what every palette extractor in production (Pinterest's color search, Spotify's album-cover palettes, Material You's wallpaper theming) does under the hood. The algorithm is **k-means**, and a competent implementation runs in a couple of hundred lines of code with no dependencies.

The implementation here samples pixels off a downscaled canvas (max 200px on the longest side) and runs k-means with **k-means++ initialization** — a heuristic that picks initial cluster centers far from each other, which produces better-than-random convergence. The number of iterations is capped at 30; on real images the algorithm usually converges in 5–10. The downscale step is the key speed optimization: clustering 40,000 sampled pixels takes ~50 milliseconds, while clustering the full 8 million pixels of a 4K photo takes ~5 seconds for results that are indistinguishable. Dominant colors are by definition the most common, so they survive any reasonable downsample.

A subtle but important detail: **alpha-near-zero pixels are skipped**. PNGs with transparent backgrounds (logos, icons, sprites with cutouts) have huge areas of fully-transparent pixels. Browsers report those pixels as having undefined RGB (effectively black or whatever fill color the canvas defaults to). Including them in the cluster pool produces a palette dominated by "transparent = black" which is wrong. The extractor skips pixels with alpha below 16/255 (about 6% opacity) — well below visible threshold but above the rounding noise some PNG encoders produce. The result is a palette that reflects only what the eye actually sees.

The output for each cluster includes its **pixel-count percentage**. This is more useful than it sounds. The largest cluster by pixel count is the image's background or dominant fill — usually less interesting visually than the smaller clusters that contain the subject. The 30%-of-pixels cluster from a photo of a red car on grass is the grass; the 8% cluster is the car. Knowing the cluster size lets you tell "background tint" from "accent color" at a glance, which matters when you're picking colors for a design that should feature, not just match, the image.

**Palette size (k)** is the single tuning knob. The right value depends on what you'll use the palette for:

- **k=2 or 3** is "what's the brand color of this logo?" — finds the most-saturated dominant colors and an off-color (usually white/black background). - **k=4-6** is the design-system sweet spot — enough variety to build a theme, not so many that adjacent entries look identical. - **k=8-12** is for reference work — building a moodboard, matching a photograph's color story. - **k=16+** approaches indexed-color GIF territory; the clusters get small and noisy, with several near-duplicate entries.

The result is **non-deterministic between runs** because k-means++ uses randomness for initialization. For typical images the difference between runs is a few RGB values, well within visible threshold. For images with sharp color discontinuities (logos with pure brand colors, posters), the result is stable. If you need deterministic output across runs, the right tool is a fixed-seed clustering library at the command line, not a browser-based extractor.

**Use cases worth highlighting:**

- **Branding from a logo**: drop in a competitor's logo, get their brand color in 1 click. - **Theme generation from a photograph**: drop in a mood-board image, get a 6-color palette for the rest of the design. - **Image-to-CSS-variables**: copy the extracted HEX values straight into your design tokens. - **Quick "what color is this?"**: drop in a screenshot, pick the swatch you want.

Everything runs in your browser. The k-means implementation is a small pure function (under 200 lines, with vitest coverage including the k-means++ initialization, cluster-ordering, and empty-input edge cases). The image is decoded by the browser's native image pipeline and never transmitted. EXIF GPS data, undecoded color profiles, embedded metadata — all stay on your machine. You can verify in DevTools: zero outgoing image bytes during extraction.

Frequently Asked Questions

How does the extractor decide which colors are 'dominant'?

It runs **k-means clustering** on the image's pixels. Pixels are grouped into N color clusters by minimizing the squared distance between each pixel and its assigned cluster center; the cluster centers are the output colors. This is the same algorithm used by Adobe Photoshop's 'Indexed Color' mode and most palette-extraction libraries. The result is the N RGB values that, taken together, best represent the image's color distribution.

Why is the result slightly different each time I extract?

Because k-means starts from randomly chosen initial cluster centers (using the k-means++ heuristic for better convergence). Different starting points can converge to slightly different local optima. For typical photographic images the differences are small — a few RGB values off, usually imperceptible. For images with sharp color discontinuities (logos, posters, graphics), the result is more stable.

Why does my image get downscaled before clustering?

Speed. A 4K photograph has ~8 million pixels; clustering all of them takes seconds and produces results indistinguishable from clustering 40,000 pixels (since the dominant colors are by definition the most common ones, which downsampling preserves). The tool downscales any image larger than 200 pixels on its longest side, samples those pixels, and clusters. Quality of the palette is unaffected; latency drops from seconds to ~100 milliseconds.

Why don't transparent pixels show up in the palette?

The tool skips pixels with alpha less than 16/255. Fully transparent pixels would otherwise count as 'pure white' or whatever browser-default fills them, which would skew the palette toward white for any image with a transparent background (logos, icons, PNGs with cutouts). Skipping them produces a palette that reflects the visible content only.

What palette size should I pick?

**4–6** for a typical design palette — enough variety to use as theme accents without too many similar colors. **2–3** for the most-dominant-only result (e.g., 'what is the brand color of this logo?'). **8–12** for design references where you want subtle variations. The maximum is 16 — past that, the clusters get small and noisy, and adjacent palette entries start to look near-identical.

Can I use the extracted palette in Tailwind?

Yes. Copy any HEX value and add it as a custom color in your `tailwind.config.js` (`theme.extend.colors`), or use Tailwind's arbitrary-value syntax (`bg-[#ff7700]`). For a quick way to find the closest Tailwind default for any extracted color, paste the HEX into the Color Converter tool to see RGB/HSL, then visually scan the Tailwind Color Picker for a match. Most extracted colors fall within a few units of a default Tailwind swatch.

Is my image uploaded to a server?

No. The image is decoded by your browser, drawn onto an in-memory canvas, and the pixel array is fed to the k-means function — all client-side. The browser's network tab will show zero outgoing image data. Your image, including any embedded EXIF / GPS metadata, never leaves the page.