Skip to content

EyeDropper API

Published

EyeDropper API — per Chrome for Developers, the EyeDropper API “enables authors to use a browser-supplied eyedropper in the construction of custom color pickers,” letting a page sample the color of an on-screen pixel instead of shipping its own color-sampling code.

  • Legend
  • Yes
  • Partial
  • Flag
  • No
  • Unknown
Browser / PlatformSupportVersionsConfidenceSourceNotes
Chrome (Desktop)Yes95highsource12
Chrome (Android)No—highsource3
Edge (Desktop)Yes95highsource456
Firefox (Desktop)No—highsource7
Firefox (Android)No—highsource89
Safari (macOS)No—highsource10
Safari (iOS)No—highsource1112
Samsung InternetNo—highsource1314
WebView (Android)No—highsource15
  1. Before Chrome 120, the EyeDropper API is not available on ChromeOS. See bug 40720753 (https://crbug.com/40720753).
  2. Available on Linux X11, but not available on Linux Wayland. See bug 40720753 (https://crbug.com/40720753).
  3. No Chrome Android support is recorded in browser-compat-data.
  4. Before Chrome 120, the EyeDropper API is not available on ChromeOS. See bug 40720753 (https://crbug.com/40720753).
  5. Available on Linux X11, but not available on Linux Wayland. See bug 40720753 (https://crbug.com/40720753).
  6. Derived by browser-compat-data mirroring from Chrome.
  7. No Firefox support is recorded in browser-compat-data.
  8. No Firefox for Android support is recorded in browser-compat-data.
  9. Derived by browser-compat-data mirroring from Firefox.
  10. No Safari support is recorded in browser-compat-data.
  11. No Safari on iOS support is recorded in browser-compat-data.
  12. Derived by browser-compat-data mirroring from Safari.
  13. No Samsung Internet support is recorded in browser-compat-data.
  14. Derived by browser-compat-data mirroring from Chrome Android.
  15. Implementation tracking: https://crbug.com/40791573.

Source data: /compatibility/eyedropper.json · Global usage: 37 % (StatCounter 2026-05)

Source: spec · MDN · Last verified 2026-10-03 · Confidence: high (computed from sources)

Per Chrome for Developers, open() “can only be called in response to a user action (like a button click),” so the call belongs inside the click handler itself. It resolves after the user selects a pixel, giving access to that pixel’s color in sRGBHex format:

// Minimal, self-contained: create the controls the handler needs, then wire it up.
const pickButton = document.createElement('button');
pickButton.type = 'button';
pickButton.textContent = 'Pick a color';
const colorInput = document.createElement('input');
colorInput.type = 'color';
document.body.append(pickButton, colorInput);
pickButton.addEventListener('click', async () => {
const eyeDropper = new EyeDropper();
try {
const result = await eyeDropper.open();
colorInput.value = result.sRGBHex; // e.g. "#3366ff"
} catch (err) {
// Per MDN, AbortError means the user pressed Escape or an AbortController
// aborted the selection.
if (err.name === 'AbortError') {
console.log('Eyedropper selection aborted.');
} else {
console.error('Eyedropper pick failed:', err.name, err);
}
}
});

'EyeDropper' in window is false in browsers that do not implement the API. The fallback branch below actually shows an <input type="color"> swatch instead of the pick button:

function initColorPicker(pickButton, colorInput) {
if (!('EyeDropper' in window)) {
// No native eyedropper here — hide the pick button and let the user choose a
// color with the always-present <input type="color"> swatch instead.
pickButton.hidden = true;
colorInput.hidden = false;
return;
}
pickButton.hidden = false;
pickButton.addEventListener('click', async () => {
const eyeDropper = new EyeDropper();
try {
const { sRGBHex } = await eyeDropper.open();
colorInput.value = sRGBHex;
} catch (err) {
// AbortError covers Escape and an AbortController aborting the selection.
if (err.name === 'AbortError') {
console.log('Eyedropper selection aborted.');
} else if (err.name === 'NotAllowedError') {
// open() was not called from a transient user activation.
console.error('Eyedropper needs a fresh user gesture.');
} else if (err.name === 'InvalidStateError') {
// Another eyedropper is already open.
console.error('An eyedropper is already open.');
} else {
// OperationError: the selection failed for other reasons.
console.error('Eyedropper pick failed:', err.name, err);
}
}
});
}
  • Per MDN, the EyeDropper API “is not Baseline because it does not work in some of the most widely-used browsers” — feature-detect before constructing one.
  • Only call open() from inside a user-gesture handler — per Chrome for Developers it “can only be called in response to a user action (like a button click).”
  • Handle the rejected promise from open() by name: per MDN, AbortError occurs when the user aborts the selection by pressing Escape or when an AbortController aborts it. NotAllowedError means the call lacked a transient user activation, InvalidStateError means another eyedropper is already open, and OperationError means the selection failed for other reasons.
  • open() accepts an AbortSignal, so an in-progress pick can also be cancelled programmatically when the picker’s host dialog is dismissed.
  • Per MDN’s browser-compat-data, Chrome for Android does not implement the API, so a mobile-first color picker cannot rely on it at all.
  • Desktop support is not uniform across platforms: per MDN’s browser-compat-data the API is “available on Linux X11, but not available on Linux Wayland,” and “before Chrome 120, the EyeDropper API is not available on ChromeOS.” Keep the <input type="color"> fallback reachable everywhere rather than assuming a desktop Chromium build can always pick.

For the full reference (constructor, open() options, cancellation), see EyeDropper API.

See also Async Clipboard API for another Chromium-first capability used by editor-style web apps.

← Back to the Compatibility explorer.