scalpel@labs: ~/glossary/eyedropper-tool.mdx8 sections

The EyeDropper API: Native Color Picking in the Browser

The EyeDropper API is a built-in browser feature that opens an OS-level magnifier and returns the sRGB hex of any pixel you click, anywhere on screen, including over images, video, canvas, or other applications. No screenshots, no extra permissions.

extension: Scalpel Colorupdated: 2026-08-14read_time: 3 min
less eyedropper-tool.mdx

Why it matters

Older colour pickers screenshot the tab and sample the image, which fails on video, cross-origin images and anything outside the browser. The native EyeDropper sidesteps all of that: the operating system does the sampling, so it works over any pixel and is pixel-accurate. The catches are honest ones: it needs a user gesture to open, it is Chromium and Firefox only (no Safari yet), and it returns a colour string only, never the surrounding image.

How it works

The EyeDropper API is a built-in browser feature, no extension permission needed beyond the normal browser sandbox. When you click a "Pick colour" button (or call the API in JavaScript), the browser opens an OS-level picker overlay. You move the magnifier to the pixel you want, click it, and the browser returns the sRGB hex value of that exact pixel.

Because the operating system does the sampling, not the browser, it can see any pixel on screen: a video playing in the browser, a colour in another application, a screenshot, anything the desktop is showing. That is why it works where a screenshot-based picker would fail.

The call

JavaScript developers use it like this:

button.addEventListener('click', async () => {
  try {
    const result = await new EyeDropper().open();
    console.log(result.sRGBHex);  // e.g., "#38bdf8"
  } catch (e) {
    if (e.name === 'AbortError') {
      console.log('User pressed Escape');
    }
  }
});

The open() method returns a promise. If the user picks a colour, it resolves to an object with sRGBHex (a hex string). If the user presses Escape or closes the picker, it rejects with an AbortError.

What does not matter

The EyeDropper cannot grab the full image or any metadata about what it sampled, only the colour of that one pixel. It also cannot open without a user gesture: you cannot call new EyeDropper().open() in a background task or timer. The user must click a button or press a key first. That is a security boundary the browser enforces.

Safari does not support EyeDropper yet. If your site needs to pick colours, you need a fallback: either a file upload for users to sample an image, or a screenshot-based picker that works inside the browser (slower, but works everywhere).

Browser support

  • Chrome and Edge: version 95+.
  • Firefox: 2024+.
  • Safari: not yet.

For a production site, check 'EyeDropper' in window or wrap the call in a try-catch:

if ('EyeDropper' in window) {
  // Safe to use the API
}

Why it beats getImageData sampling

Older colour pickers screenshot the page with canvas.toDataURL(), then use getImageData() to sample pixels. This works for content inside the browser, but fails on:

  • Video: the <video> element paints to a protected surface; sampling gets only a black frame.
  • Cross-origin images: marked with crossOrigin="anonymous", they still fail getImageData() due to taint rules.
  • Hardware-accelerated content: WebGL, requestAnimationFrame overlays, and system-level chrome (browser toolbar, OS windows).

The native EyeDropper avoids all of this because the operating system does the sampling at a lower level, below the browser sandbox.

Code example

A full colour picker integration:

const pickButton = document.getElementById('pick-colour');
const output = document.getElementById('colour-output');

pickButton.addEventListener('click', async () => {
  if (!('EyeDropper' in window)) {
    alert('Your browser does not support EyeDropper');
    return;
  }

  try {
    const eyeDropper = new EyeDropper();
    const result = await eyeDropper.open();
    output.style.backgroundColor = result.sRGBHex;
    output.textContent = result.sRGBHex;
  } catch (e) {
    if (e.name !== 'AbortError') {
      console.error('Error:', e);
    }
    // Silently ignore if user pressed Escape
  }
});

A fallback for unsupported browsers:

async function pickColour() {
  if ('EyeDropper' in window) {
    const result = await new EyeDropper().open();
    return result.sRGBHex;
  } else {
    // Fallback: prompt user to upload an image
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'image/*';
    input.click();
    // ... handle file upload
  }
}

How Scalpel Color shows it

Click the "Pick from screen" button in the Picker. The browser's native EyeDropper overlay opens. Move the magnifier over any pixel on screen (in the browser or in another app) and click it. The extension captures the sRGB hex and adds it to the Picker. The colour is also saved to your History for later reuse.

Sources