# QR code contrast: the 40% minimum, measured

> A QR code needs a luminance difference of at least 40 percentage points between modules and background, with the modules darker. Luminance, not hue, is what decoders threshold on. Compute 0.2126R + 0.7152G + 0.0722B for each colour, subtract, and aim above 60 points for print and poor light.

Source: https://useqr.app/docs/design/qr-code-contrast-ratio-minimum · Last reviewed 2026-08-21 · UseQR is free forever, no signup.

---

## The number and where it comes from

Before a decoder reads anything, it converts the image to greyscale and picks a
threshold: everything darker is a module, everything lighter is background. For that
threshold to exist reliably, the two sides need a luminance difference of at least
**40 percentage points**, with the modules on the dark side. Below 40 the threshold
lands inside camera noise; above **60** the code survives dim light, glare and print.

Luminance weights the channels very unevenly:

```
L = 0.2126·R + 0.7152·G + 0.0722·B
```

Green dominates and blue barely counts, which is why a saturated blue reads as dark
and a saturated yellow reads as nearly white, whatever they look like to a designer.

## Pairs that pass and fail on white

Luminance below is computed with the formula above, expressed as a percentage of white.
The difference column is what a decoder has to work with.

| Module colour | Hex | Luminance | Difference vs white | Verdict |
|---|---|---|---|---|
| Near-black slate | `#0f172a` | 9% | 91 | pass |
| Navy | `#003366` | 17% | 83 | pass |
| Crimson | `#e60023` | 20% | 80 | pass |
| Forest green | `#228b22` | 43% | 57 | pass |
| Indigo | `#6366f1` | 44% | 56 | pass |
| Mid grey | `#808080` | 50% | 50 | pass, thin margin |
| Orange | `#ff9900` | 64% | 36 | fail |
| Bright green | `#25d366` | 65% | 35 | fail |
| Sky blue | `#87ceeb` | 76% | 24 | fail |
| Gold | `#ffd700` | 82% | 18 | fail |
| Yellow | `#ffff00` | 93% | 7 | fail |

Note how close the failures are to plausible brand palettes, the
[brand colour workflow](/docs/design/brand-color-qr-codes-that-still-scan) shows how to
darken a failing swatch without losing the hue.

## This is not the WCAG ratio

WCAG's 4.5:1 rule measures a contrast *ratio* on linearised luminance and exists for
reading text. QR decoding depends on a greyscale *difference* wide enough to threshold.
The two metrics do not interchange: check text with WCAG and codes with the 40-point
rule, and treat a pair that only passes one as failing.

## How to measure a real pair

1. Convert both colours with the formula, or desaturate the artwork in any image editor
   and read the two grey values.
2. Subtract. Under 40: change a colour. 40–60: acceptable on screen, risky in
   [print](/docs/print/qr-code-print-checklist) and dim rooms. Over 60: ship it.
3. Run the finished file through the [validator](/validate), which computes the actual
   contrast of the rendered pair and decodes it. If a code with adequate numbers still
   fails, the cause is usually elsewhere: see the
   [colour troubleshooting page](/docs/troubleshooting/qr-code-colors-not-scanning).

On-screen measurements are the best case. Ink spread, laminate glare, CMYK conversion
and an angled camera each consume margin, so the 40-point floor is a floor, not a
target. Remember polarity too: the difference must have the modules darker:
[an inverted pair fails differently](/docs/design/why-light-on-dark-qr-codes-fail) even
when the arithmetic passes.

## FAQ

### What is the minimum contrast for a QR code?

A luminance difference of at least 40 percentage points between modules and background,
with modules darker. That is the working floor; above 60 points the code stays reliable
in dim light, at an angle, and after printing.

### Does hue matter for QR code contrast?

No. Decoders convert to greyscale first, so only luminance survives. A red and a green
with the same luminance are identical to a scanner, which is also why QR codes are
inherently safe for colour-blind users when the luminance rule is followed.

### Is the WCAG 4.5:1 rule the same thing?

No. WCAG defines a contrast ratio for text legibility on linearised values, while QR
decoding needs an absolute greyscale difference. Passing one does not guarantee the
other, so codes should be checked against the 40-point rule directly.

### Why does my high-contrast code still fail sometimes?

Screen numbers are the best case. Printing shifts colours, glossy laminate adds glare,
and shadows compress the difference locally. Leave headroom by designing above 60
points, and decode a photograph of the final printed piece to confirm.

## Try it

- https://useqr.app/validate
- https://useqr.app/url
