Library / SDK
Shane32/QRCoder avatar
Shane32/QRCoder

QRCoder builds QR and Micro QR symbols in C# and stops at the rendered image

A pure C# Open Source QR Code implementation

5,178 stars1,172 forksC#MIT

At a glance

What is it?
QRCoder is a MIT licensed C# library that turns strings into PNG, SVG, PDF, ASCII, Bitmap and PostScript QR symbols. It ships 23 or more payload generators, needs no third party assemblies, and targets everything from .NET Framework 3.5 to .NET 5.
Who is it for?
QRCoder fits teams that already ship .NET and want QR output as bytes or markup without pulling in another package. It does not fit anyone looking for decoding, scanning or hosted short links.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 12 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • Shane32/QRCoder5,178 ★ · +16
Star history
Repository2026-09-232026-11-14
Shane32/QRCoder5.2k5.2k

16 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Install-Package QRCoder is the only install line the README gives

QRCoder ships as a NuGet package, and the README gives exactly one installation line. There is no command line install shown, no PackageReference snippet and no build step in the tree listing, so the package manager console is the whole story.

bash
PM> Install-Package QRCoder

First use comes in two shapes. The static helper hands back bytes in a single call. The renderer path separates building the symbol from drawing it, and wraps both in using blocks because those objects are disposable.

csharp
using QRCoder;

// Generate a simple black and white PNG QR code
byte[] qrCodeImage = PngByteQRCodeHelper.GetQRCode("Hello World", QRCodeGenerator.ECCLevel.Q, 20);

// Generate a scalable black and white SVG QR code
using var qrCodeData = QRCodeGenerator.GenerateQrCode("Hello World", QRCodeGenerator.ECCLevel.Q);
using var svgRenderer = new SvgQRCode(qrCodeData);
string svg = svgRenderer.GetGraphic();

Pick the second shape whenever the output is not a bitmap. SvgQRCode.GetGraphic() is called with no size argument in the example, and the README calls the SVG output scalable, while the PNG path needs a module pixel size passed in.

Payload generators format a string, then a renderer draws it

The two halves of the library meet in the middle. A payload generator returns a formatted string, that string goes into QRCodeGenerator.GenerateQrCode, and the resulting QRCodeData object is handed to a format specific renderer.

csharp
using QRCoder;

// Create a bookmark payload
var bookmarkPayload = new PayloadGenerator.Bookmark("https://github.com/Shane32/QRCoder", "QRCoder Repository");

// Generate the QR code data from the payload
using var qrCodeData = QRCodeGenerator.GenerateQrCode(bookmarkPayload);

// Or override the ECC level
using var qrCodeData2 = QRCodeGenerator.GenerateQrCode(bookmarkPayload, QRCodeGenerator.ECCLevel.H);

// Render the QR code
using var pngRenderer = new PngByteQRCode(qrCodeData);
byte[] qrCodeImage = pngRenderer.GetGraphic(20);

Two things are worth copying from that example. The ECC level is chosen at generation time, not at render time, so two symbols built from the same bookmark string can differ if you switch from ECCLevel.Q to ECCLevel.H. And the renderer name matches the return type: PngByteQRCode produces compressed bytes, SvgQRCode produces markup.

The number 20 is a module pixel size, not a quality setting

One integer in the quick start does more work than it looks. GetQRCode("Hello World", QRCodeGenerator.ECCLevel.Q, 20) passes 20 as the pixel size for each module of the finished bitmap, so the output image grows with that value while the number of modules stays fixed. GetGraphic(20) on the PNG renderer takes the same kind of argument.

Error correction is exposed separately, as an enumeration on the generator. The feature list names error correction levels, custom colors, logos and styling as the configuration surface, and the two quick start snippets pick different members: ECCLevel.Q in the simple call, ECCLevel.H in the payload example.

Because the level is baked in when QRCodeData is created, a cache that stores rendered images has to record which level produced them. The SVG route sidesteps the pixel argument entirely, which is the practical reason to reach for it when the consumer scales the image itself.

The payload table runs from WiFi credentials to ISO 20022 bills

The feature list claims 23 or more payload generators, and the landing page shows the first stretch of them as a table with one constructor call and one line of description per row.

| Payload Type | Usage Example | Description | |--------------|---------------|-------------| | WiFi | `new PayloadGenerator.WiFi(ssid, password, auth)` | WiFi network credentials | | URL | `new PayloadGenerator.Url("https://example.com")` | Website URL | | Bookmark | `new PayloadGenerator.Bookmark(url, title)` | Browser bookmark | | Mail | `new PayloadGenerator.Mail(email, subject, body)` | Email with pre-filled fields | | SMS | `new PayloadGenerator.SMS(number, message)` | SMS message | | MMS | `new PayloadGenerator.MMS(number, subject)` | MMS message | | Geolocation | `new PayloadGenerator.Geolocation(lat, lng)` | GPS coordinates | | PhoneNumber | `new PayloadGenerator.PhoneNumber(number)` | Phone number for calling | | SkypeCall | `new PayloadGenerator.SkypeCall(username)` | Skype call | | WhatsAppMessage | `new PayloadGenerator.WhatsAppMessage(number, msg)` | WhatsApp message | | ContactData | `new PayloadGenerator.ContactData(...)` | vCard/MeCard contact | | CalendarEvent | `new PayloadGenerator.CalendarEvent(...)` | iCal/vEvent | | OneTimePassword | `new PayloadGenerator.OneTimePassword(...)` | TOTP/HOTP for 2FA | | BitcoinAddress | `new PayloadGenerator.BitcoinAddress(address)` | Bitcoin payment | | BitcoinCashAddress | `new PayloadGenerator.BitcoinCashAddress(address)` | Bitcoin Cash payment | | LitecoinAddress | `new PayloadGenerator.LitecoinAddress(address)` | Litecoin payment | | MoneroTransaction | `new PayloadGenerator.MoneroTransaction(...)` | Monero payment | | SwissQrCode | `new PayloadGenerator.SwissQrCode(...)` | Swiss QR bill (ISO-20022) | | Girocode | `new PayloadGenerator.Girocode(...)` | SEPA payment (EPC QR) | | BezahlCode | `new PayloadGenerator.BezahlCode(...)` | German payment code | | RussiaPaymentOrder | `new PayloadGenerator.RussiaPaymentOrder(...)` | Russian payment (ГОСТ Р 56042-2014) |

The table continues with SlovenianUpnQr and further rows, each linking to the wiki page on advanced payload generator usage. None of the rows says which scanner reads which format, so that choice stays with the caller.

One package spans .NET Framework 3.5 through .NET 5

The cross platform bullet names four target families in a single line: .NET 5+, .NET Framework 3.5+, .NET Core 1.0+ and .NET Standard 1.3+. That spread is why the same package can sit inside a legacy .NET Framework service and a current .NET 5 application without a second dependency.

The root of the repository is organised the same way. QRCoder.slnx holds the library next to QRCoder.Xaml for the WPF renderer, QRCoderConsole, QRCoderDemo, QRCoderDemoUWP and QRCoderSamples as hosts, plus QRCoderTests, QRCoderApiTests, QRCoderBenchmarks and QRCoderTrimAnalysis. Directory.Build.props, Directory.Build.targets and a global.json sit at the top next to the license file.

Micro QR codes get their own bullet in the feature list, described as smaller symbols for space constrained applications and listed separately from the standard QR support. The quick start does not show how to request one.

Benchmarks and a trimming analysis ship in the tree, without figures

QRCoderBenchmarks and QRCoderTrimAnalysis are real projects in the repository, which tells you the authors care about throughput and about how much of the library survives trimming. The feature list, however, gives no benchmark table, no throughput number and no memory measurement. The feature list says the generation is optimized with a low memory footprint and leaves it there.

The zero dependencies claim is checkable in a different way: the package lists framework dependencies only, so the code you audit is the code that runs. That also means no third party imaging stack arrives with it, which is why SVG, PostScript, ASCII and PDF output have to be produced by the library itself rather than delegated to an encoder elsewhere.

For a reader comparing .NET QR options, the consequence is direct. Payload coverage, target frameworks and output formats are stated precisely enough to act on; performance is a claim you would have to measure in your own application before betting on it.

Every entry point ends at bytes or markup, with no reader included

Walk the documented API from either direction and it stops at the same place. PngByteQRCodeHelper returns a byte array, SvgQRCode returns SVG text, and the format list adds PDF, ASCII, Bitmap and PostScript. Nothing in the package decodes a photographed code, resolves a shortened link, or reports whether a scanner will accept the symbol you drew.

The test projects confirm the boundary. QRCoderTests and QRCoderApiTests sit next to the library as guard rails around generation, and there is no scanner project among the top level entries.

This matters for the payload side too. SwissQrCode, Girocode, BezahlCode and RussiaPaymentOrder all format payment strings, and each row gives a constructor and a description with no reader compatibility notes. A team shipping a bank payment QR has to settle scanner support outside this library, and a team that expected a scanner picked the wrong package.

The documentation is silent on encoding failures, DPI and page setup

Custom colors, logos and styling are promised as configuration, with the wiki linked for advanced usage, but the quick start does not cover what happens when a payload cannot be encoded, or output settings such as DPI for PDF, page size for PostScript, or where the ASCII renderer writes.

Version numbers are easier to trace. The newest tags are v1.8.1 from 2026-10-13, v1.8.0 from 2026-04-04 and v1.7.0 from 2025-10-09, and the master branch received its last push on 2026-11-02. The repository is not archived, so branch activity continues between releases, which is exactly why the changelog matters more than the tag list when you pick a version.

Editorial conclusion

QRCoder fits teams that already ship .NET and want QR output as bytes or markup without pulling in another package. It does not fit anyone looking for decoding, scanning or hosted short links. Before you commit, check your longest payload against the error correction level you pick, and read the changelog for the version you pin: the last push to master landed on 2026-11-02 while the newest tag is v1.8.1 from 2026-10-13.

Frequently asked questions

How does QRCoder generate a QR code?

It encodes, it does not decode. A string goes into QRCodeGenerator.GenerateQrCode or into the static PngByteQRCodeHelper, and what comes back is QRCodeData or a byte array that a renderer draws as PNG, SVG, PDF, ASCII, Bitmap or PostScript. Reading a photographed code is outside the package.

Is a QR code generator trustworthy?

For QRCoder the symbol is built inside your own process from a string you supply, so no image leaves the machine. The package is MIT licensed and declares no external dependencies beyond framework ones, so the generator you read is the generator that draws.

Does QRCoder include a malicious QR code checker?

No checker ships here. QRCoder is a generator whose documented entry points end at a rendered image, and the tests in the tree, QRCoderTests and QRCoderApiTests, cover generation. If you need something that inspects a code and tells you whether to open it, this package is not that tool.

qrcoder vs zxing, how do the two compare?

The README feature list does not compare QRCoder with ZXing. What it states about QRCoder itself: pure C#, no external dependencies, targets .NET 5+, .NET Framework 3.5+, .NET Core 1.0+ and .NET Standard 1.3+, and emits PNG, SVG, PDF, ASCII, Bitmap and PostScript.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. Shane32/QRCoder on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/shane32-qrcoder.svg)](https://hysenlabs.com/projects/shane32-qrcoder)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/shane32-qrcoder.svg)](https://hysenlabs.com/projects/shane32-qrcoder)

Was this useful?