# Generate a QR code in C#

> QRCoder is the .NET standard: CreateQrCode(text, ECCLevel.Q) then PngByteQRCode.GetGraphic(20) returns PNG bytes with no System.Drawing dependency, so it runs on Linux containers. Expose it as an ASP.NET minimal API endpoint, or fetch the keyless API with HttpClient and Uri.EscapeDataString.

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

---

## QRCoder

`dotnet add package QRCoder` and the whole flow is generator → data → renderer:

```csharp
using QRCoder;

using var generator = new QRCodeGenerator();
var qrData = generator.CreateQrCode("https://example.com", QRCodeGenerator.ECCLevel.Q);
byte[] png = new PngByteQRCode(qrData).GetGraphic(20);
File.WriteAllBytes("qr.png", png);
```

Two details that save real debugging time:

- **Use `PngByteQRCode`, not the legacy `QRCode` class.** The legacy renderer draws
  through System.Drawing, which is Windows-only on modern .NET — it throws at runtime on
  Linux containers. `PngByteQRCode` writes the PNG itself and runs everywhere.
- `GetGraphic(20)` is **pixels per module**, not total size. A version 2 code (25
  [modules](/glossary/module) plus the quiet zone) at 20 px/module lands around 660 px.

`ECCLevel.L/M/Q/H` are the standard
[error-correction levels](/docs/spec/error-correction-levels-explained). For print, use
`SvgQRCode` from the same package — it returns an SVG string, and
[vector is what print needs](/docs/print/qr-code-size-for-print).

## An ASP.NET endpoint

Minimal API version — generation is fast enough to do per-request, and the cache header
makes repeats free:

```csharp
app.MapGet("/qr", (string data) =>
{
    using var generator = new QRCodeGenerator();
    var qrData = generator.CreateQrCode(data, QRCodeGenerator.ECCLevel.M);
    return Results.Bytes(new PngByteQRCode(qrData).GetGraphic(16), "image/png");
});
```

Add `Cache-Control: public, max-age=31536000, immutable` if the mapping from input to
image never changes — which for a QR code it does not.

## The zero-dependency route: HttpClient

For styled codes (colours, module and eye shapes) or typed, validated payloads
(`/api/v1/wifi`, `/api/v1/upi`, `/api/v1/vcard`), skip the package and call the
[keyless API](/docs/developers/free-qr-code-api-no-key):

```csharp
using var http = new HttpClient();
var target = "https://example.com/sale?src=poster";
var url = $"https://useqr.app/api/v1/qr?data={Uri.EscapeDataString(target)}&size=1024";
await File.WriteAllBytesAsync("qr.png", await http.GetByteArrayAsync(url));
```

`Uri.EscapeDataString` is the load-bearing call — an unescaped `&` in the payload starts a
new query parameter and truncates the data silently. Keep credentials (WiFi passwords,
personal data) out of any remote call; generate those locally with QRCoder.

## Verify styled output

Decode what you encode before it ships:

```csharp
using System.Net.Http.Json;

var report = await http.GetFromJsonAsync<VerifyReport>(
    $"https://useqr.app/api/v1/verify?data={Uri.EscapeDataString(target)}&color=6366f1");
if (report is not { Scannable: true })
    throw new InvalidOperationException(string.Join("; ", report!.Issues));

record VerifyReport(bool Scannable, string[] Issues);
```

The endpoint renders, rasterises and reads the code back with a real decoder — the
[decode-verify loop](/docs/developers/why-verify-that-your-qr-code-decodes) in one GET.
How QRCoder sits next to ZXing and friends is covered in
[QR code libraries compared](/docs/developers/qr-code-libraries-compared); the JVM
equivalent of this page is [Java](/docs/developers/generate-a-qr-code-in-java).

## FAQ

### What is the best C# library for QR codes?
QRCoder. Use its PngByteQRCode renderer, which has no System.Drawing dependency and therefore works on Linux and in containers.

### Why does my QRCoder code crash on Linux?
You are using the legacy QRCode renderer, which needs System.Drawing — Windows-only on modern .NET. Switch to PngByteQRCode or SvgQRCode.

### What does GetGraphic(20) mean?
Pixels per module, not total image size. Multiply by the module count of your code's version, plus the quiet zone, to predict output dimensions.

### How do I return a QR code from ASP.NET?
Results.Bytes with the PngByteQRCode output and an image/png content type in a minimal API route. Add an immutable cache header since output is deterministic.

## Try it

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