# Scan latency — why some codes scan instantly

> Decoding itself takes tens of milliseconds: find the three finder patterns, correct perspective, sample the grid, run Reed–Solomon. Codes that feel slow are losing time upstream — too small in frame, long exposures in dim light, a dense version, a busy background full of false finder candidates, or damage forcing error-correction retries.

Source: https://useqr.app/docs/scanning/scan-latency-why-some-codes-scan-instantly · Last reviewed 2026-08-21 · UseQR is free forever, MIT licensed, no signup.

---

## The pipeline, and its budget

Once a clean frame reaches the decoder, the work is quick. The stages:

1. **Detect.** Scan the image for the three [finder patterns](/glossary/finder-pattern)
   — the corner squares whose dark-light-dark-light-dark run has the fixed
   **1:1:3:1:1** width ratio in any direction. That ratio is the entire trick: it is
   detectable in a single row of pixels at any rotation or scale, which is why
   detection is cheap.
2. **Align.** Use the three corners (plus [alignment patterns](/glossary/alignment-pattern)
   in larger codes) to compute the perspective transform back to a square grid.
3. **Sample.** Read each module's luminance against a threshold, un-mask, and recover
   the raw bits.
4. **Correct and decode.** Run [Reed–Solomon](/glossary/reed-solomon) error correction
   and parse the payload.

On a modern phone the whole pipeline costs **tens of milliseconds** — and the camera
delivers a fresh frame every ~33 ms at 30 fps. A healthy code therefore decodes within
one to three frames of entering the viewfinder, which humans perceive as *instant*. A
code that takes three seconds is not decoding slowly; it is **failing repeatedly**,
frame after frame, until conditions improve. Latency is really a reliability problem
wearing a stopwatch.

## What makes a code slow, ranked

| Rank | Cause | Mechanism | Fix |
|---|---|---|---|
| 1 | **Too small in frame** | Modules fall under ~3 px; every frame fails until the user moves closer while autofocus hunts | Size for distance — the [10:1 rule](/docs/scanning/scanning-distance-limits) via the [size calculator](/size-calculator) |
| 2 | **Low light** | Long exposures blur module edges; frames fail until the hand steadies | Light the placement; the physics is in [low-light scanning](/docs/scanning/qr-scanning-in-low-light) |
| 3 | **Dense version** | More, smaller modules for the same print width — cause 1 by another route | Shorten the payload; see [why longer URLs make denser codes](/docs/spec/why-longer-urls-make-denser-codes) |
| 4 | **Busy background** | Patterns near the code mimic the 1:1:3:1:1 ratio, flooding detection with false finder candidates to test and reject | Generous [quiet zone](/glossary/quiet-zone) and a plain surround — the failure mode of codes on textures |
| 5 | **Damage and logo overreach** | Errors burn the Reed–Solomon budget; marginal frames decode only when sampling lands luckily | Keep logos under ~20% coverage with EC level H; test worn samples |

The ranking is diagnostic: causes 1–2 depend on the *scan*, so the same code is fast
in hand and slow across a room; causes 3–5 are baked into the *artwork*, so the code
is uniformly sluggish everywhere. Ask which pattern you are seeing before changing
anything — and for a code that fails outright rather than slowly, work through the
[not-scanning checklist](/docs/troubleshooting/qr-code-not-scanning-checklist).

## Why short payloads feel snappy

The codes that scan from across a room before you have consciously aimed — payment
codes on counters, WiFi cards — share one property: **tiny payloads**. A short
[URL](/url-qr-code) or ID yields a version 2–4 code with large modules, which survives
distance, blur and damage with margin to spare, so nearly every camera frame decodes
on the first attempt. The relationship between density and working distance is
quantified in [density and scan distance](/docs/spec/qr-code-density-and-scan-distance).
Nothing you do to the artwork buys as much speed as deleting characters from the
payload.

## Measure, do not guess

Perceived speed is a poor instrument. Two checks replace it: the
[validator](/validate) confirms the artwork decodes cleanly and reports its contrast
and density margins, and a bench test — the code at its real distance, a mid-range
phone, normal lighting — tells you the frame-level truth. If the banner does not
appear within about a second, one of the five causes above is eating your frames; the
table says which fix to reach for. For decoding screenshots and photos during testing,
[/scan](/scan) shows the raw payload without opening it.

## FAQ

### Why do some QR codes scan instantly and others take seconds?
Decoding takes tens of milliseconds, so instant codes are decoding on the first camera frame. Slow codes are failing frame after frame — too small, too dark, too dense, on a busy background, or damaged — until a lucky frame succeeds.

### Does the amount of data in a QR code affect scan speed?
Yes, strongly. Longer payloads create denser codes with smaller modules, which need more camera pixels and fail more frames at any given size and distance. Short payloads produce low-version codes that decode almost instantly from generous distances.

### What is the fastest way to make a code scan quicker?
Shorten the payload, then enlarge the print. Both grow the modules, which is what the camera actually needs. After that: better light, a plain background with a full quiet zone, and keeping any logo well inside the error-correction budget.

### Why does a busy background slow scanning?
Finder detection looks for a 1:1:3:1:1 dark-light ratio in pixel runs, and visual clutter near the code produces false candidates the decoder must test and reject each frame. A clean quiet zone and plain surround keep detection on the real corners.

## Try it

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