ScreenshotNeo

BlogHow-to

How to Extract HTML Color Codes from an Image

Learn how to pick exact HEX, RGB, HSL, and alpha colors from an image using browser tools, DevTools, EyeDropper, canvas, and ScreenshotNeo.

By the ScreenshotNeo team1 October 20268 min read

Fast answer: open the image in a color-picker, move the eyedropper to the pixel you need, click, and copy the resulting #RRGGBB value. For code, draw the image into a canvas and read one pixel with getImageData(). Use #RRGGBBAA or rgba() when transparency matters.

This guide covers image files, screenshots, whole-screen sampling, browser APIs, color spaces, transparent pixels, JPEG artifacts, averaging regions, and a repeatable JavaScript implementation.

What an HTML color code represents

HTML and CSS use the <hex-color> type to represent sRGB color components in hexadecimal notation. In the six-digit form, the first pair is red, the second is green, and the third is blue; each channel ranges from 00 to FF. CSS also supports short forms and alpha transparency: #RGB, #RGBA, #RRGGBB, and #RRGGBBAA.MDN: <hex-color>

Notation Meaning Example
#RGB Three 4-bit channels expanded to six digits #3AF
#RRGGBB Opaque red, green, and blue channels #33AAFF
#RGBA Short RGB form plus alpha #3AFC
#RRGGBBAA RGB plus an 8-bit alpha channel #33AAFFCC

A sampled value describes the encoded pixel you selected. It is not automatically the “name” of a visual area, a palette average, or the color your monitor emits after calibration.

Fastest no-code method: use an image color picker

  1. Open a browser-based image color-picker that accepts your file type, such as PNG, JPEG, WebP, or GIF.
  2. Upload or drop the image.
  3. Move the eyedropper over the image and watch the preview value.
  4. Click the exact pixel or a representative point in the region.
  5. Copy HEX for CSS, or copy RGB/HSL if your destination expects those formats.

Prefer a tool that processes the image locally when the file is private. For a flat UI color, click the center of a solid region rather than an edge, shadow, or text anti-aliasing fringe.

Sample a color anywhere on your screen with Chrome DevTools

Chrome DevTools includes a Color Picker with an Eyedropper that can sample from the page or anywhere on the screen. It samples in the sRGB color space; press Escape to leave eyedropper mode.Chrome DevTools color picker

  1. Open DevTools with F12 or Ctrl/Cmd + Shift + I.
  2. Inspect an element that has a color declaration, or open the Styles pane.
  3. Click a color swatch next to a CSS value.
  4. Choose the eyedropper, move over the target pixel, and click.
  5. Copy the displayed HEX value.

This workflow is useful when the color is visible on another application or browser tab and you do not want to upload the source image.

Use the browser EyeDropper API

The EyeDropper API lets a supported Chromium-based browser ask the user to select a pixel from the screen. Chrome documentation identifies support from version 95. The open() promise resolves with an sRGBHex value such as #1a2b3c.Chrome EyeDropper API MDN EyeDropper API

<button id="pick">Pick a screen color</button>
<output id="result"></output>

<script>
const button = document.querySelector('#pick');
const result = document.querySelector('#result');

button.addEventListener('click', async () => {
  if (!('EyeDropper' in window)) {
    result.textContent = 'EyeDropper is not supported in this browser.';
    return;
  }

  const controller = new AbortController();
  try {
    const picker = new EyeDropper();
    const { sRGBHex } = await picker.open({ signal: controller.signal });
    result.textContent = sRGBHex;
    await navigator.clipboard?.writeText(sRGBHex);
  } catch (error) {
    // Escape or AbortController cancellation rejects the promise.
    result.textContent = 'Color selection cancelled.';
  }
});
</script>

Feature-detect window.EyeDropper. Treat rejection as normal user cancellation, not necessarily as an application error. Use an AbortController if your UI needs a Cancel button.

Extract a pixel with JavaScript and canvas

For an image file or an image already available to your page, canvas is the standard programmable approach. Draw the image at the resolution you intend to sample, convert displayed pointer coordinates to canvas coordinates, then call getImageData(). The returned ImageData contains 8-bit RGBA channel values by default.MDN: getImageData()

<input id="file" type="file" accept="image/*" />
<canvas id="canvas"></canvas>
<output id="hex"></output>

<script>
const fileInput = document.querySelector('#file');
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
const output = document.querySelector('#hex');

function rgbaToHex([r, g, b, a]) {
  const channel = value => value.toString(16).padStart(2, '0');
  return a === 255
    ? `#${channel(r)}${channel(g)}${channel(b)}`
    : `#${channel(r)}${channel(g)}${channel(b)}${channel(a)}`;
}

fileInput.addEventListener('change', () => {
  const file = fileInput.files[0];
  if (!file) return;

  const image = new Image();
  image.onload = () => {
    canvas.width = image.naturalWidth;
    canvas.height = image.naturalHeight;
    ctx.drawImage(image, 0, 0);

    canvas.addEventListener('click', event => {
      const rect = canvas.getBoundingClientRect();
      const x = Math.floor((event.clientX - rect.left) * canvas.width / rect.width);
      const y = Math.floor((event.clientY - rect.top) * canvas.height / rect.height);
      const pixel = ctx.getImageData(x, y, 1, 1).data;
      output.textContent = rgbaToHex(pixel);
    }, { once: false });
  };
  image.src = URL.createObjectURL(file);
});
</script>

The coordinate conversion matters when CSS scales the canvas. Sampling event.offsetX directly can return the wrong source pixel if the displayed canvas is smaller or larger than its backing resolution.

Sample a remote image safely

Remote images must satisfy canvas origin rules. Set crossOrigin = 'anonymous' before assigning src, and ensure the image server sends an appropriate CORS header. Otherwise the canvas becomes origin-unclean and getImageData() throws a security error.

const image = new Image();
image.crossOrigin = 'anonymous';
image.onload = () => {
  ctx.drawImage(image, 0, 0);
  const pixel = ctx.getImageData(10, 10, 1, 1).data;
};
image.src = 'https://example.com/image.png';

Request a specific color space

When wide-gamut or HDR content matters, the Canvas API documents optional srgb and display-p3 color-space requests and rgba-float16 data for higher-range work. Use the default 8-bit sRGB path for ordinary web CSS; choose an explicit color space when your design pipeline requires it.

const pixels = ctx.getImageData(0, 0, 1, 1, {
  colorSpace: 'display-p3'
});

Convert the sampled value to CSS formats

Canvas returns numeric channels. Convert each 0–255 channel to two hexadecimal digits:

const pixel = ctx.getImageData(x, y, 1, 1).data;
const hex = '#' + [pixel[0], pixel[1], pixel[2]]
  .map(v => v.toString(16).padStart(2, '0'))
  .join('');

For an opaque pixel, the result is #RRGGBB. If alpha is less than 255, preserve it as #RRGGBBAA or use CSS rgba():

const [r, g, b, a] = pixel;
const css = `rgba(${r}, ${g}, ${b}, ${(a / 255).toFixed(3)})`;

One pixel versus an average color

A one-pixel sample reports that exact encoded pixel. It does not average a textured area. For a representative color, deliberately select a rectangle and average its pixels.

function averageRgb(ctx, x, y, width, height) {
  const { data } = ctx.getImageData(x, y, width, height);
  let r = 0, g = 0, b = 0, count = 0;

  for (let i = 0; i < data.length; i += 4) {
    const alpha = data[i + 3] / 255;
    r += data[i] * alpha;
    g += data[i + 1] * alpha;
    b += data[i + 2] * alpha;
    count += alpha;
  }

  if (!count) return '#00000000';
  return '#' + [r / count, g / count, b / count]
    .map(v => Math.round(v).toString(16).padStart(2, '0'))
    .join('');
}

For gradients, photographs, shadows, and anti-aliased text, state whether you need the exact source pixel, a simple arithmetic mean, or a perceptual palette color. Those are different outputs.

Accuracy checklist

  • Use the original file: screenshots, resized previews, and recompressed JPEGs can contain different channel values.
  • Avoid edges: anti-aliasing blends foreground and background colors across several pixels.
  • Check alpha: transparent pixels still have RGB channels, but their visible result depends on the background.
  • Keep color space explicit: Chrome’s screen eyedropper reports sRGB; canvas can request sRGB or display-P3, and conversion changes numbers.
  • Sample at final size: browser scaling can interpolate pixels, so inspect the source resolution when exact values matter.
  • Record the location: save the image filename, pixel coordinates, and color-space assumption for repeatable work.

Or skip the browser setup

If the image is on a web page, ScreenshotNeo can create a clean screenshot before you sample it. The API is a single GET request; see the ScreenshotNeo documentation for all capture options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are never billed; response headers identify the page verdict and whether the shot was billed. An MCP server lets AI agents such as Claude and Cursor take screenshots. The Free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Troubleshooting

Symptom Cause Fix
Canvas throws a security error The remote image lacks permitted CORS headers or crossOrigin was set too late. Use a same-origin copy, configure the image server for CORS, and set crossOrigin before src.
The color is slightly different from what you see JPEG compression, scaling, anti-aliasing, transparency, or color-space conversion. Use the original asset, sample a flat interior pixel, inspect alpha, and keep the color space consistent.
EyeDropper is undefined The browser does not implement the API. Feature-detect it and provide a file-upload/canvas fallback.
EyeDropper promise rejects The user pressed Escape or an abort signal cancelled selection. Handle rejection as cancellation and restore the picker UI.
Canvas coordinates are wrong The displayed canvas size differs from its backing resolution. Scale pointer coordinates by canvas.width / rect.width and canvas.height / rect.height.
Transparent pixels look black RGB channels are being read without considering alpha or the compositing background. Return #RRGGBBAA or composite against the intended background before sampling.

Performance, reliability, and cost

  • For occasional picks, a local browser tool is fastest and avoids upload time.
  • For repeated sampling, keep one canvas context, size the canvas deliberately, and request only the small rectangle you need from getImageData().
  • willReadFrequently: true can help workloads that read many pixels, but do not use it as a substitute for limiting the sampled area.
  • Large images consume memory when decoded and drawn. Downsample only when an approximate color is acceptable.
  • Remote images add network and CORS failure modes. A same-origin upload or server-side fetch is more predictable.
  • When capturing pages through ScreenshotNeo, caching, wait conditions, blocking rules, and bulk capture can reduce repeated browser work; only clean successful shots are billed.

FAQ

Is HEX the same as an HTML color name?

No. HEX is a numeric CSS representation. A named color such as tomato is a separate CSS keyword and may not describe the exact sampled pixel.

Should I use HEX, RGB, or HSL?

Use the format required by the destination. HEX is compact and common in CSS tokens; RGB is convenient for channel arithmetic; HSL can be useful when adjusting hue, saturation, or lightness.

Why do two pickers report different values?

They may sample different pixels, use different scaling, composite transparency differently, or convert between sRGB and a wide-gamut color space.

Can I extract a color from a PDF?

Yes, render the relevant page to an image first, then apply the same pixel or region-sampling workflow. Preserve the rendered resolution and color-space assumptions.

What is the most repeatable workflow for a design system?

Keep the original asset, document coordinates and color space, sample a defined region, and store the resulting value with the asset version. Use a script when the process must be rerun.