How to Create a QR Code with Custom Colors That Still Scans

Your designer just handed you a QR code with brand colors: orange modules, pale peach corner squares and a soft gradient. It looks great. Will it scan?
Every QR code linkutm generates can carry brand colors, so I wanted real numbers before giving anyone advice. This guide shows how to create a QR code with custom colors, step by step, and where the safe limits are. I ran 40 simulated phone captures per setting on two open-source decoders, covering the three things nobody else on our site had measured: hue, corner eye colors and gradients.
Here’s the short version.
| What you color | My rule | What the test showed |
|---|---|---|
| Dark modules (the pattern) | Your darkest brand color, 4.5:1 or more against the background | Five hues all read 39-40/40 at 3:1 and above |
| Background | Light and solid | Black modules held 39-40/40 on a white-to-orange gradient |
| Corner eyes | Same color as the pattern, or darker | Pale eyes on a black pattern failed first: 20/40 at 2:1 |
| Gradient | Light end away from the three corners, lightest stop 3:1 or more | Placement mattered more than error correction level |
If you only remember one line: the corner eyes are the worst place for a light accent color.
What Decides Whether a Colored QR Code Scans?
A colored QR code scans when the scanner can still split it into dark and light. Hue doesn’t matter. Brightness does.
Look, the vocabulary helps here, so let’s define the four parts a scanner cares about:
- Modules are the small squares that make up the code. A QR code module is either dark or light, and that’s the only information it carries.
- Finder patterns (designers call them “eyes”) are the three big squares in the corners. A scanner looks for them first, using their fixed 1:1:3:1:1 dark-light-dark ratio. The finder pattern tells it where the code is and which way up.
- Luminance is how bright a color is, ignoring its hue. Most scanners convert the camera frame to a brightness image before doing anything else.
- Binarization is the step where the decoder turns that brightness image into pure black and white. Every module lands on one side of a threshold.
Here’s the relationship that matters. Your colors become brightness values. Brightness values become black or white at binarization. The finder patterns must survive that step, or the decoder never starts reading data.
Error correction sits after that. It can repair data modules that come out wrong. It can’t repair a finder pattern, because the eyes aren’t data.The standard yardstick for “different enough” is the contrast ratio from the W3C’s WCAG 2.2 accessibility guidelines. It runs from 1:1 (identical brightness) to 21:1 (black on white). I’ve already published contrast numbers for brand colors on white and for color on color, so I won’t repeat them here.
The limitation: contrast ratio was built for text read by people, not codes read by cameras. That gap shows up in the next test.

How to Create a QR Code with Custom Colors in 6 Steps
Okay, so here’s the process I use for every branded code. Most of the time goes into the last step.
- Pick the dark color first. Choose the darkest usable color in your brand palette for the modules. Check it against your background in any WCAG contrast checker and aim for 4.5:1 or more.
- Keep the background light and solid. White, off-white or a pale tint all work. If the design needs a dark page, put a light panel behind the code instead of flipping it to light-on-dark. Include the quiet zone, the blank margin of 4 modules, inside that panel.
- Color the corner eyes the same as the modules, or darker. Never use a lighter accent color for the eyes than for the pattern. My eye-color test below shows why.
- If you want a gradient, place it carefully. Keep the lightest stop at 3:1 or more, and run the light end away from the three finder corners. In my test, a diagonal gradient and a radial gradient with a light center both read 40 out of 40 on both decoders, even with a very pale end.
- Export the right file. Use SVG or PDF for print and a PNG at final size for screens. My guide to high-quality PNG QR codes covers pixel sizes and why transparent PNGs break on dark pages.
- Test at final size on several phones. Scan from the real distance, in the real light. A code that reads on one decoder can fail on another, as the hue test shows.
The fastest way to do steps 1 to 5 is linkutm’s free custom color QR code generator. Set the pattern and background colors, watch the live preview, and download PNG, SVG or PDF with no account.
Real talk: no generator can do step 6 for you. A preview on a backlit screen is the best-case version of your code.

Does Hue Matter If the Contrast Ratio Is the Same?
Above 3:1, no. Below 2:1, a lot.
I tuned five hues (red, orange, green, blue and purple) to the same WCAG contrast ratio against white, then put each through 40 simulated phone captures. The decoders were zxing-cpp 3.1.1 and OpenCV 5.0.0. Both read the plain black-on-white baseline 40 out of 40.
| Contrast vs white | Red | Orange | Green | Blue | Purple |
|---|---|---|---|---|---|
| 4.5:1 | 40 / 40 | 40 / 40 | 40 / 39 | 40 / 40 | 40 / 40 |
| 3:1 | 40 / 40 | 40 / 40 | 40 / 40 | 40 / 39 | 40 / 39 |
| 2:1 | 40 / 40 | 40 / 40 | 40 / 40 | 40 / 40 | 39 / 40 |
| 1.6:1 | 18 / 37 | 26 / 39 | 40 / 40 | 31 / 40 | 10 / 39 |
Scans out of 40: zxing-cpp / OpenCV. Version 3 code, error correction M.
At 1.6:1, the same ratio produced anything from 10 to 40 reads. Why? WCAG and a camera weigh red, green and blue differently. The test camera used the common BT.601 brightness formula, and under it the pale green (#00ED00) was 45% darker than white, while the pale purple (#E9BCFF) was only 18% darker. Same ratio on paper, very different contrast to the decoder.
So the WCAG ratio works as a floor, not as a precise prediction. At 3:1 and above, every hue passed. I’d still pick 4.5:1 for anything printed, because paper, ink and dim light all eat contrast.
The honest limitation: real phones use their own camera pipelines and brightness formulas, so the low-contrast ranking might shuffle on your phone. Don’t design at 1.6:1 and hope you got a lucky hue.

Can the Corner Eyes of a QR Code Be a Different Color?
Yes, if the eye color is at least as dark as the pattern. A lighter QR code eye color is the riskiest custom color choice I’ve tested.
This surprised me. I expected a pale accent on just three squares to be safer than a pale color everywhere. It’s the opposite. I kept the data modules black and recolored only the finder patterns, then compared that with coloring the data only and coloring everything.
| Color (vs white) | Eyes colored, data black | Data colored, eyes black | Whole code colored |
|---|---|---|---|
| #7F3F00 (8:1) | 40 / 40 | 40 / 40 | 40 / 40 |
| #BA5D00 (4.5:1) | 40 / 40 | 40 / 40 | 40 / 40 |
| #E97500 (3:1) | 40 / 40 | 40 / 40 | 40 / 39 |
| #FFA244 (2:1) | 20 / 24 | 37 / 40 | 40 / 40 |
| #FFC080 (1.6:1) | 0 / 3 | 7 / 23 | 26 / 39 |
Scans out of 40: zxing-cpp / OpenCV. Same Version 3 code at error correction M.
At 2:1, the whole code in pale orange read 40 out of 40. The same pale orange on only the eyes dropped to 20 and 24. At 1.6:1, eyes-only failed almost completely.
Here’s the thing. Binarization sets its threshold from the surrounding brightness. Next to black modules, the threshold sits roughly halfway between black and white, so a pale orange eye lands on the white side and vanishes. When the whole code is pale, the threshold moves down with it. Mixed contrast inside one code is worse than uniform low contrast.
That’s my reading of the mechanism. The numbers are what matter: at 3:1 and above, colored eyes passed every time.
This also fills a gap in our finder pattern entry, which noted that colored eyes were untested. If you want eye shapes too, my dot QR code tests cover rounded and circle eyes. Shape and color risks stack, so keep both conservative.

Do Gradient QR Codes Scan?
Usually, yes. A gradient is more forgiving than a solid fill in its lightest color, as long as the light end doesn’t cover the corner eyes.
I ran a navy-to-light-blue gradient across the modules in four layouts: left to right, diagonal (top-left to bottom-right), radial with a dark center, and radial with a light center. Then I made the light end paler and paler.
| Lightest stop (vs white) | Solid in that color | Left to right | Diagonal | Radial, dark center | Radial, light center |
|---|---|---|---|---|---|
| #B9CDF5 (1.6:1) | 28 / 38 | 40 / 40 | 40 / 40 | 40 / 40 | 40 / 40 |
| #D6E2F9 (1.3:1) | 0 / 9 | 31 / 40 | 40 / 40 | 39 / 39 | 40 / 40 |
Scans out of 40: zxing-cpp / OpenCV. Every layout read 39-40/40 with the lightest stop at 2:1 or darker.
The pale end alone fails as a solid, 0 out of 40 on zxing-cpp. As the end of a gradient it mostly passed, because only part of the code is pale. The two weakest layouts were the ones where the pale end covered finder corners: left to right (the top-right eye) and radial with a dark center (all three eyes).
I also reran the gradients at error correction level H, the highest level. It didn’t help. Left to right read 29 out of 40 instead of 31. That fits the mechanism: level H adds spare data, and the problem was the eyes, not the data.
Gradient backgrounds behaved well too. Black modules on a white-to-orange background read 39 to 40 out of 40 even when the darkest end of the background was only 3.5:1 against black.
My limitation for this section: these are clean digital images. Print adds ink spread and paper tone, and a gradient on glossy stock adds glare on top. That’s why my rule keeps the lightest stop at 3:1, well above the point where things broke.

How to Set Custom QR Code Colors in Code
If you generate codes in bulk or need to change QR code color inside your own app, two open-source libraries cover every color slot.
Python with segno. Segno lets you color each part of the code separately. The segno color documentation lists every region. This is the setup I’d use for a navy brand code with slightly darker eyes:import segno
qr = segno.make("https://go.example.com/sp26", error="m")
qr.save(
"brand-qr.svg",
scale=10,
dark="#0D2B6B", # all dark modules
light="#FFFFFF", # background and light modules
finder_dark="#081A40", # corner eyes, darker than the pattern
)
I ran this with segno 1.6.6, and the SVG it writes uses one color per region, so a designer can still edit it. Segno doesn’t do gradients.
JavaScript with qr-code-styling. qr-code-styling (version 1.9.2 at the time of writing) takes a solid color or a linear or radial gradient for the dots, the corner squares, the corner dots and the background separately. That separation is exactly what my test says to use: gradient on the dots, solid dark eyes.const qr = new QRCodeStyling({
width: 600,
height: 600,
data: "https://go.example.com/sp26",
dotsOptions: {
gradient: {
type: "linear",
rotation: Math.PI / 4,
colorStops: [
{ offset: 0, color: "#0D2B6B" },
{ offset: 1, color: "#6994EA" }
]
}
},
cornersSquareOptions: { color: "#0D2B6B" },
cornersDotOptions: { color: "#0D2B6B" },
backgroundOptions: { color: "#FFFFFF" }
});
The rotation value is in radians and sets the gradient angle. Check the preview to see where the light end lands. With solid corner options, the eyes stay dark whatever the gradient does.
The trade-off: code gives you control, and it also gives you every way to break the code. Run each new color setup through a decoder before you ship it in bulk.
Custom Colors in Print and on Screens
Color choices that pass on screen can still fail in the real world. Three pointers, each covered in depth elsewhere:
- Print. Your RGB brand color becomes CMYK ink, and bright screen colors usually print duller. For black, I use 100% K, never rich black. The QR code printing guide explains the press-side settings.
- Dark pages and dark mode. A light-on-dark code is an inverted code, and only some scanners read it. My QR code not scanning guide has the inverted-code results.
- Transparent backgrounds. A transparent PNG borrows the page color behind it, so a dark page turns your code into a low-contrast one. Flatten it onto white.
One thing color can’t fix later: the destination. Colors are baked into the printed code. If you want to change where it points after printing, use a dynamic code. Our static vs dynamic QR codes explainer covers the difference.
What My Custom Color Test Can’t Tell You
I want to be clear about the edges of this data.
- These are simulations. Each setting got 40 captures with random tilt, scale, blur and sensor noise. That’s not a phone in a dim restaurant.
- Two decoders, not every app. zxing-cpp and OpenCV disagreed in several rows. Your phone’s camera app uses neither.
- One code size. Every code was a short link at Version 3 or 4. Longer URLs make denser codes with smaller modules, which leaves less margin for weak colors.
- No logos or shapes. I tested color alone. Logos, dots and colors stack their risks.
The settings, for anyone repeating this: segno 1.6.6, zxing-cpp 3.1.1, OpenCV 5.0.0, 8 pixels per module, BT.601 brightness, 40 captures per setting, run on October 31, 2026.
Frequently Asked Questions
Can I change the colors of a QR code after printing it?
No. The colors are part of the printed image, so changing them means reprinting. What you can change after printing is the destination, if the code is dynamic. The code then points to a short link, and you update where that link goes.What colors should you avoid in a QR code?
Avoid any color that is close in brightness to its background. Pale yellow, pastels and light gray on white are the usual failures, as are mid-tones on mid-tones. In my test, five different hues all failed at around 1.6:1 against white, so the risk is the lightness, not the color name.Does adding color reduce a QR code’s error correction?
No. Color doesn’t use any of the code’s error correction capacity. Low contrast does cause misread modules, and error correction then spends its capacity repairing them. My gradient test also showed level H didn’t rescue a code whose corner eyes went pale.Can the corner squares of a QR code be a different color?
Yes, as long as the corner squares are the same brightness as the pattern or darker. In my test, colored eyes at 3:1 or more scanned 40 out of 40. Pale eyes on a black pattern were the first combination to fail, at 2:1.Do colored QR codes work on all phones?
A colored code with strong contrast works on any phone that reads QR codes. Borderline colors are where phones disagree, because each uses its own decoder. In my test, the same pale purple code read 10 out of 40 on one decoder and 39 out of 40 on the other.What contrast ratio does a gradient QR code need?
Keep the lightest point of the gradient at 3:1 or more against the background. That leaves a margin above the 2:1 point where all four of my gradient layouts still passed. Then check that the light end avoids the three corner eyes.Your Next Custom Color QR Code
Creating a QR code with custom colors comes down to a few rules:
- Use your darkest brand color for the pattern, at 4.5:1 or more.
- Keep the background light and solid.
- Make the corner eyes the same color as the pattern, or darker. Never lighter.
- Run gradients so the light end avoids the corners, and keep it at 3:1 or more.
- Test the final file on several phones at real size.
Start with the free colored QR code generator for a static code in your brand colors. If you need to edit the destination later or count scans, linkutm’s QR code features add color customization, logo overlay and scan analytics to a dynamic code. Create your first one, then scan it on three phones before it goes anywhere near a printer.