# QR code pixelated when enlarged

> Enlarging a raster QR code cannot add detail. Bicubic and bilinear resampling blur module edges into gradients; nearest-neighbour keeps edges sharp but distorts module widths at non-integer scales. The only correct fix is regenerating the code at the size you need, or exporting SVG, which scales to any size with perfect edges.

Source: https://useqr.app/docs/troubleshooting/qr-code-pixelated-when-enlarged · Last reviewed 2026-08-21 · UseQR is free forever, MIT licensed, no signup.

---

## Why enlargement cannot work

A raster image contains a fixed amount of information. Scaling it up does not add detail — it invents pixels by guessing from the neighbours. For photographs the guesses look fine. For a QR code, whose entire meaning lives in the exact position of hard dark-light edges, the guesses are the damage.

## The counterintuitive part: "smooth" scaling is the worst

Bicubic and bilinear resampling — the defaults in nearly every image editor — are designed to make photos look natural by blending across edges. That blending is precisely what a QR code cannot afford. Each module boundary becomes a gradient, and when a decoder later thresholds the image to pure dark and light, gradient pixels sit at the threshold where noise, lighting and printing decide which way they flip. A "smoothly" enlarged code often looks better to the eye and scans worse than a blocky one.

## Nearest-neighbour is only safe at integer multiples

Nearest-neighbour resampling keeps edges hard, so it seems like the right tool. It is — but only at exact **integer multiples** (2×, 3×, 4×), where every source pixel becomes a clean block. At a non-integer factor such as 2.4×, rounding forces some modules to come out 2 pixels wide and others 3 — a **50% width difference between modules that should be identical**. That distortion lands directly on the [timing pattern](/glossary/timing-pattern) and module grid the decoder uses to map the symbol.

## The right fixes

1. **Regenerate at the size you need.** A QR code is computed from its payload, so a fresh render at 2,048 px costs nothing and is pixel-perfect. With our API it is one parameter: `https://useqr.app/api/v1/qr?data=hello&size=2048`.
2. **Export SVG once and never think about size again.** Vector output renders exactly at any dimension — the case is laid out in [vector vs raster QR codes](/docs/spec/vector-vs-raster-qr-codes), and [making a high-resolution QR code](/docs/how-to/how-to-make-a-high-resolution-qr-code) walks through both routes.
3. **Lost the original data?** Decode the small image with our [scanner](/scan) to recover the exact payload, then regenerate clean. Never ship an upscaled rescue.

## If it must stay on screen

For web embeds, an SVG sized with CSS is the clean answer. If you are stuck with a small PNG, `image-rendering: pixelated` at an exact integer device-pixel multiple avoids browser smoothing — but this is a patch, not a fix, and it breaks the moment a user zooms.

Whatever route you take, run the final artwork through the [validator](/validate) — it decodes the rendered result, which is the only test that matters.

## FAQ

### How do I enlarge a QR code without losing quality?
You do not enlarge it — you regenerate it. A QR code is computed from its data, so rendering a fresh copy at the target size, or exporting SVG, produces perfect edges at any dimension in seconds.

### Why does my enlarged QR code look sharp but not scan?
Nearest-neighbour enlargement at a non-integer factor keeps edges hard but makes identical modules different widths. The decoder's grid mapping depends on consistent module size, so the code looks crisp and still fails.

### Is SVG always better than PNG for QR codes?
For anything that will be resized or printed, yes — vector edges are exact at every size. PNG is fine when generated at the exact display or print size and never scaled afterwards.

### Can AI upscalers fix a low-resolution QR code?
They make it look nicer, not decode better — and a hallucinated module is a changed module. Decode the original to recover the payload, then regenerate. If the original no longer decodes, no upscaler will recover data that is not there.

## Try it

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