Upload an image or pick an Unsplash photo, then copy its colors as HEX, RGB, or HSL.
Upload an image or choose an Unsplash photo, and the picker lists up to ten of its main colors, starting with the one that covers the largest area. The extraction runs in your browser with the open-source extract-colors library, so an uploaded file is read on your device and never sent to a server. Each swatch copies as HEX, RGB, or HSL, and the whole set can be exported or opened in the other color tools.
On the Upload image tab, select Choose an image, or drop a file onto the upload area. One image is read at a time, and choosing a new one replaces the previous result. The input accepts any file the browser reports as an image; PNG, JPG, WebP, and GIF are the common cases. A file that is not an image shows a message instead, and an image the browser cannot decode shows "Colors could not be read from this image". The tool does not set a file size limit, but a very large photo still has to be decoded in full before it is sampled, so it takes longer.
The Unsplash photos tab searches Unsplash as you type and offers quick searches (Abstract, Geometric, Sand dune, Dark matte, Neon gradient). Results load twelve at a time, up to thirty per search. Selecting a photo extracts its colors the same way; the photo itself is loaded from Unsplash.
Knowing what the extraction does explains most surprising results. The image is scaled down to about 64,000 pixels for the calculation, nearly transparent pixels are skipped, and pixels with similar hue, saturation, and lightness are merged into one color. The merged colors are sorted by how much of the image they cover and the ten largest are shown.
The HEX, RGB, and HSL buttons above the swatches set the copy format; selecting a swatch copies its value in that format, and the value is printed under each swatch. HEX is copied in capitals with the #, RGB as rgb(5, 94, 104), and HSL with whole numbers, such as hsl(186, 91%, 21%). Because HSL is rounded, converting it back does not always give the same color: hsl(186, 91%, 21%) comes back as #055D66, not the original #055E68. Copy HEX or RGB when the exact value matters, for example to match an existing design token.
Export palette opens the same export dialog as the palette generator: CSS custom properties, gradient CSS and Tailwind classes, a mesh gradient, and PNG or SVG files. Colors stay in the extracted order, so --color-1 is always the color with the largest area, which is often a good candidate for a background or surface. The arrow next to Export palette has Visualize, Open in the generator, Explore similar, View variations (tints and shades of every color), and View fullscreen.
Below the workspace, Similar palettes compares the five largest colors with the 400 palettes in the site's collection, using a weighted RGB distance, and shows up to 24 of the closest. This is useful when the photo's own colors are close to what you want but too muddy or too similar to each other to build a UI with.
The largest colors in a photo are usually muted, such as sky, wall, or shadow tones. They work as backgrounds and surfaces, but rarely as button colors or text. Pick the most saturated extracted color for actions, then check it: WCAG level AA asks for 4.5:1 contrast for normal text and 3:1 for large text and UI parts. If the color is close but fails, open View variations and take a darker row of the same column instead of a new color, so it still matches the image.
To run the same extraction in your own code, for example to tint a card from its cover image, install extract-colors and repeat what this page does. Remote images need CORS headers that allow your origin, otherwise the browser will not let a script read the pixels.
import { extractColors } from "extract-colors";
async function mainColors(src) {
const colors = await extractColors(src, { crossOrigin: "anonymous" });
return colors
.sort((a, b) => b.area - a.area) // largest area first
.slice(0, 10)
.map((color) => color.hex);
}
const [dominant] = await mainColors("/covers/album.jpg");
document.querySelector(".card").style.backgroundColor = dominant;Updated