How to 3D Print a QR Code That Scans — featured illustration
Design

How to 3D Print a QR Code That Scans

6 min read
Create a QR code

The plate comes off the bed and the code looks perfect. Raised modules, crisp walls, a satisfying object. It scans on the workbench in half a second, under a lamp off to one side. Then it goes on the shelf it was made for, lit from directly above by an LED panel, and no phone in the building can read it.

Nothing changed about the geometry. The shadows went away, and on a single-colour print the shadows were the code.

Decide where the contrast comes from

A printed QR code has no ink. Nothing in the process produces a dark area and a light area, so contrast has to be manufactured, and there are only two ways.

A filament colour change. Dark plastic where the dark modules go, light plastic underneath and around. A real difference in reflectance, so it works in any light, at any angle, torch on or off. It behaves like a printed code because it is one.

Relief. Raised or recessed modules in one colour. The dark areas are shadows, so the code is only as good as the light in the room it lives in.

If the printer can manage two colours, use two colours. Everything below about relief is for the case where it cannot, and it is harder. The handmade QR codes page covers the wider craft family.

Colour change: three layers, not one

The usual approach is a shallow recess in the top surface: print in light filament up to the recess floor, swap, then the code layers in dark.

One layer of dark is not enough. Most filaments are slightly translucent at 0.2 millimetres, so a single dark layer over a light body comes out grey, worst in bright light where the colour underneath shows through most. Give the code two or three layers, more if the light filament is the one on top, since light colours are the more translucent direction.

Then the swap. On a manual change the first centimetres of extrusion still carry the old colour, so purge before the code layer rather than printing a module perimeter in the previous filament. On a multi-material setup the purge is automatic, but ooze across the code area leaves pale streaks through dark modules, so put the code late in the layer.

A third way sidesteps all of it: print the code as a separate thin plate and glue it into a recess. Two prints, no swap risk, clean edges.

Relief is the only QR code that scans worse with the torch on

If it has to be one colour, recess the modules rather than raising them, for a reason worth understanding.

A recessed module self-shadows. Light at most angles is blocked by the walls, so the dark area sits inside the module's own footprint, exactly where the decoder samples.

A raised module casts its shadow beside itself. The dark area is displaced by an offset that grows as the light angle drops, so one module shadows its neighbour and the whole pattern of darkness shifts sideways against the grid. That is not damage error correction can repair. It is the wrong picture.

So engrave, do not emboss. Half the module width of depth is enough for the walls to shade at moderate angles, and deeper than a full module width buys nothing while printing worse. Keep the walls vertical, no chamfer or fillet, because a rounded lip softens the shadow edge the way ink spread softens a printed one.

Now the limitation. Light arriving down the camera axis, which is what a phone torch gives you, reaches the flat floor of the recess and reflects off it exactly as the top surface does. The contrast collapses. A relief code is the only kind that reads better with the flash off, which makes it a poor choice for anything a stranger scans in a dim room.

The way out is paint. Flood the engraved modules with dark acrylic and wipe the top surface clean before it sets. Now it is a mechanically masked ink code: real contrast, no swap, a surface that survives handling.

Module size is set by the nozzle, not the layer height

Layer height is a Z dimension and the module grid lives in X and Y, so what constrains the pattern is extrusion width. On a 0.4 millimetre nozzle that is roughly 0.42, and features get built from whole extrusions.

A module two extrusions wide prints as a clean square. One extrusion wide comes out rounded and oversized, since a single bead of plastic has no straight sides. Below that the slicer drops the feature or smears it in as a thin wall, and a dropped module is a flipped bit.

So treat three extrusions as the floor: 1.2 millimetres per module on a 0.4 nozzle. A short redirect URL lands near a 29 module symbol, add four modules of quiet zone each side for 37 across, and at 1.2 millimetres that is a plate about 45 millimetres square. A 0.2 nozzle buys you smaller, slowly.

Anything that shortens the payload widens the modules, since a lower version means fewer across the same plate. Error correction is the other half: the levels recover roughly 7, 15, 25 and 30 percent of a symbol's codewords at L, M, Q and H, and the generator here renders every code at H with no way to lower it, as the level comparison explains. Useful for a relief code where lighting takes out patches. Useless against a module the slicer never printed.

Matte filament, and turn ironing off

The top surface of a print is a set of parallel lines, and parallel lines reflect directionally: rotate the part ninety degrees under the same lamp and the highlight moves. On glossy filament those lines throw a streak across the code, the same failure as gloss lamination on paper, and silk PLA is the worst offender because gloss is the entire point of it.

Matte PLA or PETG scatter instead, and they are the right choice for anything scanned. Two slicer settings follow. Turn ironing off over the code, because a smoother top surface is a shinier one. And set the top fill direction at an angle to the module grid, so the line pattern does not align with module edges.

Facing the code down onto the bed gives a flatter surface than any top infill, and the bed texture comes with it: smooth PEI or glass prints a near-mirror finish, textured PEI matte.

First layer squish, and the flat rule

The bed brings a second consequence with it, and this one is squish. An over-pressed first layer spreads each extrusion sideways, so dark features widen and a one-module light gap between two dark modules can close. Once it does, the two read as one and the grid is wrong. Set elephant-foot compensation properly, or move the code to the top surface.

One rule is not negotiable: print it flat. A code wrapped around a cylinder has a module grid no decoder can map, and that is geometry rather than damage, so error correction never touches it. Print a flat plate and mount it on the curve, for the reasons in codes on curved surfaces.

Print a test tile first

  1. Model one plate carrying the same code at 1.0, 1.2 and 1.6 millimetre modules, in the filament and finish you intend to use.
  2. Scan each in the room the part will live in, at the height and angle it will sit.
  3. Scan with the torch on and off. A relief code that passes only with the torch off has told you something.
  4. Use two phones from different makers.
  5. Take the smallest size that reads first try every time, then go one step up.

Export the pattern as SVG and bring the vector into CAD rather than tracing a PNG, and set the quiet zone before downloading: the slider here runs from zero to eight modules and defaults to two, while the standard asks for four, for the reasons in the quiet zone. Building and styling are free with no login, downloading needs a free account, and every code here is dynamic, so editing the destination and reading scan counts are the paid plan. For a printed object that is the useful half of the deal: the plastic is permanent and the link does not have to be.

Share this article