DEV Community

Jonas Hämmerle
Jonas Hämmerle

Posted on

SVG output for QR codes: why vector beats raster once anyone screenshots or resizes it

Raster QR codes (PNG/JPEG) look fine at the size they were generated for and fall apart the moment someone resizes, screenshots, or prints them larger — the module edges blur, and blurred module edges are exactly what breaks a decoder's ability to read the grid.

SVG sidesteps this completely because a QR code is fundamentally vector data already — it's a grid of black/white squares, not a photograph. Rendering it as <rect> elements instead of a pixel bitmap means it stays crisp at any zoom level, print size, or screen density:

<img src="qr.svg" alt="Scan to open" width="600" />
Enter fullscreen mode Exit fullscreen mode

That's a 600px display of a code that could've been generated at any size — no upscaling artifacts, because there was never a fixed pixel grid to begin with.

A couple of practical notes if you're embedding these in a product:

  • Inline the SVG (rather than referencing it as an <img src>) if you need to style fill colors with CSS at render time instead of baking colors in server-side.
  • Strict hex validation on any color params matters more than it looks — if a QR generation endpoint lets you pass custom foreground/background colors and embeds them directly into SVG attributes, that's an injection surface if the values aren't validated as actual hex colors first.
  • Raw matrix output is still useful — for canvas rendering, terminal output, or anything that isn't "embed an image," getting the boolean module grid directly beats parsing an SVG back into pixels.

QR API returns image/svg+xml by default from GET /v1/qr, with a /v1/qr/matrix variant returning the raw grid for exactly that second use case. Sibling APIs on the same account: Validate and Currency API.

Top comments (0)