# Generate a QR code in Swift

> Apple platforms have a QR encoder built in: CIFilter.qrCodeGenerator() from CoreImage, available since iOS 7. Set message and correctionLevel, scale the tiny output with CGAffineTransform (never interpolated resizing), and wrap the CGImage for SwiftUI. No package needed; use the keyless API only for styled codes.

Source: https://useqr.app/docs/developers/generate-a-qr-code-in-swift · Last reviewed 2026-08-21 · UseQR is free forever, MIT licensed, no signup.

---

## The generator is already on the device

The headline fact: you do not need a library. Every iPhone since iOS 7 and every Mac since
OS X 10.9 ships `CIQRCodeGenerator` inside CoreImage:

```swift
import CoreImage.CIFilterBuiltins

func qrImage(for text: String, scale: CGFloat = 12) -> CGImage? {
    let filter = CIFilter.qrCodeGenerator()
    filter.message = Data(text.utf8)
    filter.correctionLevel = "M"          // "L", "M", "Q" or "H"
    guard let output = filter.outputImage else { return nil }
    let scaled = output.transformed(by: CGAffineTransform(scaleX: scale, y: scale))
    return CIContext().createCGImage(scaled, from: scaled.extent)
}
```

`correctionLevel` accepts the four standard
[error-correction levels](/docs/spec/error-correction-levels-explained) as strings.
On-device generation is also the right call for privacy: a WiFi password or contact card
never needs to reach a server to become an image
([client-side vs server-side](/docs/security/client-side-vs-server-side-qr-generation)).

## Scale without blur

The filter's raw output is one pixel per [module](/glossary/module) — a few dozen pixels
across. Resize that with normal image scaling and you get a grey, smeared code that
scanners hate. Two rules:

- Scale with `CGAffineTransform` **before** rasterising, as above — modules stay square
  and hard-edged at any size.
- In SwiftUI, add `.interpolation(.none)` so the framework never smooths it either.

```swift
struct QrView: View {
    let value: String
    var body: some View {
        if let cg = qrImage(for: value) {
            Image(decorative: cg, scale: 1)
                .interpolation(.none)
                .resizable()
                .scaledToFit()
                .frame(width: 220, height: 220)
                .padding(12)
                .background(.white)   // keep the code light-on-white in dark mode
        }
        // always offer the underlying link as a tappable fallback
    }
}
```

The white background matters: a code inheriting a dark-mode backdrop reads as inverted,
which many scanners [refuse](/docs/design/why-light-on-dark-qr-codes-fail).

## Styled codes: the keyless API

`CIQRCodeGenerator` draws black-on-white squares, full stop. For brand colours, module
shapes or typed payloads with validation, fetch the
[keyless API](/docs/developers/free-qr-code-api-no-key):

```swift
var comps = URLComponents(string: "https://useqr.app/api/v1/qr")!
comps.queryItems = [
    .init(name: "data", value: "https://example.com/sale?src=poster"),
    .init(name: "size", value: "1024"),
    .init(name: "color", value: "6366f1"),
]
let (data, _) = try await URLSession.shared.data(from: comps.url!)
let image = UIImage(data: data)
```

`URLComponents` handles the percent-encoding — building the query by string concatenation
is how payloads containing `&` get silently truncated. In SwiftUI,
`AsyncImage(url: comps.url)` displays it with no manual fetch at all.

## Verify styled output

Any code you recolour should be decoded back before it ships. On-device you can round-trip
with Vision's barcode detection; simpler is one call to `GET /api/v1/verify`, which
renders, rasterises and decodes server-side and returns `scannable` plus issues — the
[decode-verify loop](/docs/developers/why-verify-that-your-qr-code-decodes) as a request.
The Android equivalent of this whole page is
[generate a QR code in Kotlin](/docs/developers/generate-a-qr-code-in-kotlin).

## FAQ

### Does iOS have a built-in QR code generator?
Yes — CIQRCodeGenerator in CoreImage, present since iOS 7 and OS X 10.9. CIFilter.qrCodeGenerator() gives typed access; no third-party package is required.

### Why is my Swift QR code blurry?
The filter outputs one pixel per module and it is being resized with interpolation. Scale the CIImage with CGAffineTransform first and set .interpolation(.none) in SwiftUI.

### How do I set error correction with CIQRCodeGenerator?
Set correctionLevel to "L", "M", "Q" or "H". Use "H" when the code will carry a logo or face rough conditions; "M" is a sensible default.

### Can CIQRCodeGenerator make coloured QR codes?
No, it emits black on white. Recolour with CoreImage filters carefully, or request styled output from the keyless API and verify that it still decodes.

## Try it

- https://useqr.app/url
- https://useqr.app/json
- https://useqr.app/validate
