IRONSOFTWAREHOME

Using IronQR with AI Coding Assistants

Curtis Chau
Curtis Chau
Updated: October 9, 2026

IronQR is Iron Software's QR code library for .NET. It writes standard QR, Micro QR, and rMQR symbols, styles them with logos and colors, and reads them back with a machine learning detector. Its guides and samples are public, so coding assistants may have met the API in training.

Training does not pin the release in your project. Assistants referencing current documentation generate code that follows its runtime rules, while those relying on memory may produce code that compiles but fails at runtime.

This guide covers two types of tools.

  • Assistants work in the editor, completing lines or rewriting methods, like GitHub Copilot's inline suggestions.
  • Agents take whole tasks, editing files, running builds and programs, and returning results for review, as Claude Code, Cursor, ChatGPT Codex, and Google Antigravity do.

Both need the same setup. Install the package, load the license key from the environment, provide IronQR's machine-readable documentation, and decode each saved QR image with IronQR's reader, whether you are generating a code with a logo, selecting an error correction level, reading the QR type, or choosing a scan mode.

Claude Code logoChatGPT Codex logoGitHub Copilot logoCursor editor logoGoogle Antigravity logo

Can't My AI Assistant Handle QR Codes on Its Own?

IronQR publishes documentation built for tools to read, which shows the options each symbol type accepts and what the reader returns in each scan mode.

The library matters too. Almost any QR package prints a black square that scans on a screen. The gaps appear with branded codes, photographed tickets, and small symbols.

  • A changed background color is not checked: a code on a dark background saves without an error and then fails to decode.
  • Phone photos are harder than generated images: a section below measures which scan mode reads each kind of damage.
  • Rebuilding detection costs tokens: an assistant that writes its own thresholding to rescue scans spends a paid attempt on every try, and repeats the work for each new kind of failing photo.
  • Small symbols are built in: Micro QR and rMQR come from the same write call as standard QR, so seat numbers and narrow labels do not need a second library.
  • The package and the namespace differ: the NuGet package is IronQR and the namespace is IronQr. A guessed package name can also resolve to a lookalike that attackers publish on purpose, a practice called slopsquatting. Spell out both names in the prompt.
  • The license terms are known in advance: IronQR licenses are perpetual, and the licensing page shows how many developers, locations, and projects each tier covers.

Step 1: Install IronQR

With the package referenced, the assistant sees IronQR's real types as it writes code.

Add IronQR from NuGet to this project, run a restore, and report the
version number that NuGet resolved.
Text

To pin a release from the terminal instead, name it.

dotnet add package IronQR --version 2026.10.1
SHELL

Plain IronQR brings the Windows native reader and the detection model, a 44 MB IronQrDetection.dll that pulls in Microsoft.ML.OnnxRuntime 1.20.1, so container images and serverless bundles should budget for it. Linux and Docker use IronQR.Linux, Macs use IronQR.MacOs or IronQR.MacOs.ARM, and mobile apps use IronQR.iOS or IronQR.Android. All six were published at 2026.10.1, and the NuGet packages guide explains the choice. IronQR.Slim leaves the model out. It still reads in Auto and OnlyBasicScan but throws IronQrException in OnlyDetectionModel. On Windows it also needs IronSoftware.ReaderInternals.Windows.


Step 2: Apply Your License Key

IronQR does not produce watermarked trial output. Without a license key, every write and read call fails with IronSoftware.Exceptions.LicensingException and the text "Production License Required". A mistyped key fails at the same calls with "License Key Not Recognized". A free trial key is available below.

Start using IronQR in your project today with a free trial.

First Step:
arrow pointer

Set the key once at startup through IronQr.License.LicenseKey, before any IronQR call, and read it from an environment variable to keep it out of the repository.

IronQr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONQR_LICENSE_KEY");
C#

IronQr.License.IsLicensed reports true after a valid key is set, and the same class has a method that tests a key without applying it. The exception type is not public, so a catch clause that names it fails to compile with CS0122. Catch Exception and inspect the message instead.

Please note: IronQR License Keys covers Web.config, appsettings.json, and the other places a key can be kept.

Step 3: Point Your Assistant at IronQR's LLM Documentation

When a task depends on one guide's detail, have the assistant open that page.

Combine the index with a direct instruction.

Open https://ironsoftware.com/qr/csharp/llms.txt before you write IronQR code
and keep to the members it documents. Creating a code goes through
QrWriter.Write with an optional QrOptions, and reading goes through
new QrReader().Read on a QrImageInput, so do not look for one class that does
both. When a member is not in the index, check
https://ironsoftware.com/qr/csharp/object-reference/api/, and tell me it is
missing rather than inventing it.
Text

Step 4: Add IronQR Context to Your Project

A chat forgets its instructions when it ends, and a project file is read at the start of every session. Put the IronQR rules in the file your team uses. Claude Code reads CLAUDE.md, ChatGPT Codex reads AGENTS.md, and GitHub Copilot reads .github/copilot-instructions.md. Cursor reads .cursor/rules/*.mdc or AGENTS.md, and Google Antigravity reads AGENTS.md or GEMINI.md. The wording can be the same in each, although a Cursor rule file also needs MDC frontmatter.

## QR codes with IronQR

All QR work in this project uses IronQR. NuGet package `IronQR` (`IronQR.Linux` on Linux and Docker), namespace `IronQr`, enums in `IronQr.Enum`.

- Docs index: https://ironsoftware.com/qr/csharp/llms.txt
- Skill file: https://ironsoftware.com/qr/csharp/skill.md
- Write with `QrWriter.Write(value, new QrOptions(...))`, style with `QrStyleOptions`, read with `new QrReader().Read(new QrImageInput(bitmap))`.
- Set `IronQr.License.LicenseKey` from IRONQR_LICENSE_KEY at startup. Never put the key in a file.
- Pass an explicit `QrErrorCorrectionLevel` that the symbol type accepts. Micro QR rejects `Highest`, rMQR rejects `Low` and `High`.
- Release a `QrImageInput` with `input.Dispose()`, not a `using` statement.
- Decode every saved image with `QrReader` and compare it with the written value before calling a change done.
- Do not add a second QR library. If IronQR cannot do something, say so.
Text

Four things in the current skill file need correcting. Its single-file example pins 2026.8.1 while NuGet serves 2026.10.1. Its frame-reading recipe wraps the image input in a using declaration, and its first recipe and its styling advice pass a file path to Verify, two of the mistakes Step 7 describes. And it lists Highest as invalid for rMQR, which the error correction table below contradicts.


Step 5: One-Shot Setup Prompt

Steps 1 through 4 fit in one message at the start of a session.

Set this project up for QR code work with IronQR, then save the rules below
where your future sessions will read them.

- Add the IronQR NuGet package (IronQR.Linux for a Linux or Docker host).
  The namespace is IronQr, spelled with a lowercase r.
- Assign IronQr.License.LicenseKey from the IRONQR_LICENSE_KEY environment
  variable before the first QrWriter or QrReader call. Keep the key out of
  every file you create or commit.
- Fetch https://ironsoftware.com/qr/csharp/llms.txt first and write against
  the members it documents. Look up anything else in the API reference at
  https://ironsoftware.com/qr/csharp/object-reference/api/ before using it.
- If your tool loads skill files, add
  https://ironsoftware.com/qr/csharp/skill.md, but trust a compiler error
  over the skill when the two disagree.
- After any change that writes a QR image, decode the saved file with
  QrReader and compare the value with the one you wrote.
Text
Tips: Open the Step 4 project file afterward to confirm the rules landed.

Step 6: Prompt Patterns That Produce Working Code

Name the symbol type, the error correction level, and the style.

Vague Generate a QR code for the ticket with our logo.

Better Write the ticket ID with QrWriter.Write at the Highest error correction level, save it at 300 pixels with the logo at 28 percent of that width, and catch IronQrException if IronQR refuses the style.

Give the release and the framework, because defaults and validation rules change between versions.

Better Target .NET 9 and IronQR 2026.10.1.

Ask for complete files. A fragment drops the IronQr.Enum directive that the encoding and scan mode enums need, and it hides where the key is assigned.

Better Return all of Program.cs with its using directives and the license line, ready to build as it is.


Step 7: Verify What You Get Back

  • Disposing the image input with using: QrImageInput implements IDisposable with a method that throws NotImplementedException, so a using block or declaration fails after the read succeeds. Call its public Dispose method directly instead.
  • Reading with the detection model alone: OnlyDetectionModel returns where codes are, with an empty value and a QR type of None. The scan modes guide explains when to use Auto or OnlyBasicScan for values.
  • Treating Verify as a file check: it compares the code in memory with the string you pass, so a file path returns false. Decode the saved PNG with QrReader to prove the file scans.
  • Empty write options: QrOptions built with no arguments has its encoding set to None, and QrWriter.Write rejects it with None is not a valid encoding. Pass the level, and the encoding when it is not standard QR.

Let the Agent Verify Its Own Work

Hand the checks back to the assistant and ask for the evidence.

Rebuild in Release and run it. List each IronQR type and member the code uses
next to the documentation page that shows it, print IronQr.License.IsLicensed,
then reopen every PNG the program saved with QrReader and give me a table of
file, value written, value decoded, QrType, and whether they agree.
Text

Which Error Correction Level Does Each Symbol Type Accept?

The four QrErrorCorrectionLevel members do not follow the letters of the QR standard. High is level Q, and Highest is level H, which IronQR's XML documentation describes as leaving room for a logo. Micro QR and rMQR accept only some of them, and the write call throws IronQrEncodingException for the rest, with a message such as Highest is not valid for Micro QR.

MemberQR standardMicro QRrMQR
LowL, about 7% recoverableacceptedthrows
MediumM, about 15%acceptedaccepted
HighQ, about 25%acceptedthrows
HighestH, about 30%throwsaccepted

QrWriter.Write with no options writes standard QR at Highest, and the options constructors also default to Highest, which is why Micro QR options fail until you pass a lower level. The supported formats page compares the three symbol types.

The level also caps the logo. On a 400 pixel ticket ID code in our tests, Low refused a logo at 20% of the width, Medium and High took 28% and refused 30%, and Highest took 30%. A refused logo makes Save throw IronQrException with The logo size which you manually specified for your QR code is too large. A QrLogo width and height of 0 lets IronQR size the logo itself, and on that code it picked 60 pixels at Low and 112 at Highest.

Foreground color is checked the same way. With a navy foreground at Highest, the same ticket ID code saved at 300 and 500 pixels but threw IronQrException at 400 with Color: #FF1A237E makes the QR unreadable for our reading engine. Styling code should catch that exception, change the size or color, and retry, since a style that saved at one size can fail at another.


Which Default Values Does IronQR Use?

These starting values were measured in IronQR 2026.10.1 under .NET 9.

  • Empty style options leave Dimensions and the margins at 0, so a ticket ID saves at one pixel per module, 25 x 25 pixels.
  • An initializer that sets Dimensions still leaves the margins at 0, since it skips the constructor that sets 10.
  • The QrStyleOptions constructor that takes a size sets margins of 10, so a size of 400 saves a 420 pixel PNG.
  • Save with no style writes a ticket ID at 250 x 250 pixels.
  • Color and BackgroundColor start as black on white.
  • A new image input scans in Auto, the detection model and then a basic scan.
  • CharacterEncoding is ISO-8859-1, so set it for characters outside Latin-1.

The logo guide sets a Dimensions of 500 in an initializer, so its output has no quiet zone around the symbol. Set Margins when the code will be printed next to other artwork.


How Does IronQR Read Photographed Codes?

We calibrated the acceptance test below on eight seeded sets. IronQR 2026.10.1 wrote the styled logo codes at 300 pixels and the other ticket codes at 400, Pillow distorted them, and IronQR read them back. The Auto counts vary with how the values are assigned to the images, so they are ranges over 10 draws.

ImageSets read in AutoSets read in OnlyBasicScanFix
Scaled to 60%, rotated 30 degrees, blurred 1.5 pixels, on gray8 of 88 of 8None needed
Grain, standard deviation 20 gray levels0 of 80 of 8Blur first
Two upright codes 30 pixels apart5 to 7 of 88 of 8Add OnlyBasicScan
Navy logo code after a 1.5 pixel blur0 to 4 of 88 of 8Add OnlyBasicScan

The blur that rescues the grainy code is the one that costs Auto the navy logo code. Two setups read all 12 codes on all eight sets. One applies a 1.5 pixel blur and then OnlyBasicScan. The other applies a blur of 1 to 2 pixels, runs Auto and OnlyBasicScan, and merges the results by value. Pick the setup from the images that fail, then run it unchanged for every upload.

Grain also interacts with code size. With the same grain, codes of 350 to 425 pixels failed in both modes on all 24 files, codes of 300, 500, and 600 pixels read in both, and codes of 450 and 475 pixels read only in Auto. Adding 100 pixels of white around a failing code let OnlyBasicScan read all 12 files we tried.


A Result You Can Reproduce

The acceptance test is one realistic task in one prompt with no hand-written code. Paste it into a new session in an empty directory and judge the result against the pass list.

Please note: Running it takes the .NET 9 SDK on a Windows machine with internet access, an assistant allowed to use the terminal, and an IronQR trial or production key in IRONQR_LICENSE_KEY.

The prompt

Build a .NET 9 minimal API for event check-in that issues ticket QR codes and
reads them back from uploaded photos. Begin in an empty directory, and if you
find existing code or a project file there, report that and do nothing else.
Nobody will answer questions, so carry the job through writing, building,
running, and fixing by yourself, and settle anything left open with a
reasonable choice that you note. Keep all deliverables inside the project
directory, in the folders this prompt names.

1. Install the IronQR NuGet package pinned to version 2026.10.1.
2. Work from https://ironsoftware.com/qr/csharp/llms.txt and the guides it
   points to, and call no IronQR member those pages do not document. Every
   code must come from QrWriter.Write; any .NET imaging library may compose
   and distort the test images afterward.
3. Take the key from IRONQR_LICENSE_KEY when the app starts and keep it out of
   source and out of every file the run writes. If IronQr.License.IsLicensed
   comes back false, stop with a report saying so.
4. GET /ticket/{ticketId} returns a PNG of a QR code written at
   QrErrorCorrectionLevel.Highest and saved through QrStyleOptions at a
   Dimensions of 400 with 10-pixel margins, with a logo in the center: a
   solid square of one bright accent color, drawn by your code, whose QrLogo
   width and height are each 28 to 30 percent of Dimensions. POST /checkin
   accepts one uploaded image and returns JSON listing every QR code found in
   it, each with its value and QR type.
5. Seed the random generator with 2026 and write 10 PNG files to testset/,
   no two holding the same value: standard-01 to standard-03, each carrying a
   ticket ID made of TKT- and eight random digits; pair-01, one image holding
   two more ticket codes side by side and upright, with 30 pixels of
   background between their dark modules; styled-01 to styled-03, ticket
   codes at Highest with the step 4 logo and three different dark, saturated
   foreground colors on white; micro-01 and micro-02, Micro QR codes carrying
   seat numbers such as C07; and rmqr-01, an rMQR code carrying an event URL.
   Save every testset code the same way at a Dimensions of 400, except 300
   for the styled and Micro QR codes and 600 for rmqr-01, and resize no code
   afterward unless standard-02 calls for it.
   Keep standard-01 clean. Make standard-02 look photographed: scale it to 60
   percent, rotate it 30 degrees, blur it with a Gaussian radius of 1.5
   pixels, and center it on a 600 x 600 light gray canvas. Give standard-03
   sensor grain: Gaussian noise with a standard deviation of 20 gray levels,
   one value per pixel added to all three channels, over the whole image.
   Record in manifest.csv each file, every value it holds, its QR type, the
   error correction level used, and its distortion (none, photographed,
   grain, pair, or styled).
6. Measure each saved image before /checkin is ever called, and repair the
   generator whenever a measurement falls outside its range: the pixel size
   step 5 implies;
   on the styled codes and the /ticket output, the logo's share of the symbol
   area, 7 to 10 percent; on the styled codes, the foreground's WCAG contrast
   ratio against the background, 7 to 15; on the Micro QR codes, a square
   symbol 11 to 17 modules wide; on the rMQR code, a symbol at least twice as
   wide as it is tall; on standard-03, the mean absolute difference from the
   clean code, 7 to 9 gray levels; on pair-01, the gap between the two codes'
   dark modules, 28 to 32 pixels. Once /checkin has been called the first
   time, the testset files are frozen: do not rewrite or edit them.
7. /checkin runs one fixed configuration for every upload: the same scan mode
   or modes and the same image preparation, in the same order. It must never
   open the manifest, hold a ticket ID, seat number, or URL as a literal, or
   pick between results by comparing them with expected values. You choose
   and change the configuration between runs; the program never does.
8. Build in Release and start the API. Request /ticket for a ticket ID drawn
   from the seed that is not in the testset and save the PNG it returns as
   ticket.png. POST ticket.png and every testset image to /checkin over HTTP
   and save each raw response as checkin/<file name without .png>.json.
9. Write roundtrip.md with every step 6 measurement as a number for each
   image (a bare pass or fail is not enough), the /checkin configuration,
   and a results table with the columns file, distortion, expected value,
   value read (the decoded string as the saved response holds it, even when
   it is wrong), expected QR type, QR type read, and match, holding one row
   per expected code, 12 rows in all. A row counts as a match only if the
   decoded value equals the expected value exactly, the QR type agrees, and
   the value appears in that file's saved response. An extra or repeated
   code in a response fails every row of that file.
10. Until all 12 rows match, study the saved responses of the failing files,
    adjust the /checkin configuration, rebuild, and repeat. Stop after the
    eighth run that still has failures, and report the failing rows, each
    configuration you tried, and your reading of the cause.
11. End with a brief summary covering the Release build outcome, how many
    rows matched, the /checkin configuration, the measured step 6 values,
    and every assumption you made.
Text

Output

Grainy test QR code that IronQR read correctly through the check-in API in the acceptance run

This is standard-03.png, the grain image, 8.0 gray levels from the clean code on average. The first check-in setup, plain Auto, read the other 11 codes and missed this one. A Gaussian blur with a sigma of 1 read it but lost styled-03.png and ticket.png, and a median filter, alone or with a wider quiet zone, still missed it. The fifth setup read all 12 codes by applying a 3 by 3 median filter and a threshold at half brightness to every upload, then reading in Auto.

The unedited round-trip table lists every measurement, each setup tried, and the 12 rows. The ticket from the API carries an orange logo over 7.84% of the symbol.

  • An independent check remeasured every requirement on the saved files, and a fresh start of the Release build returned the same 11 responses.
  • Before the fifth run, Claude Code tried eight setups outside the API, and three read every code.
  • Claude Code applied the prompt's Gaussian radius of 1.5 as a sigma of 1.5.
  • The Steps 1, 3, 5, and 7 prompts followed in the same session, and 12 of 12 codes decoded at Step 7.
  • NuGet now flags the SixLabors.ImageSharp 3.1.12 pin Claude Code added.
  • With the code sizes left open, an earlier draft of the prompt let plain Auto read every file.

What passes

  • The Release build succeeds with no edits from you.
  • Opening the images shows three different dark foregrounds under a bright square logo, grain across the whole of standard-03.png, and two upright codes side by side in pair-01.png.
Please note: Change the version in step 1 to test another release. The IronQR changelog records what each one changed.

The run record

  • The machine runs Windows 11 x64 on a Core i9-14900KF with 64 GB of memory.
  • Every project targets .NET 9.
  • Every guide ran IronQR 2026.10.1. Copilot and Antigravity also referenced IronQR.Linux 2026.10.1 for Linux builds, the Copilot starter project already carried PDFtoImage 5.4.0, and Cursor's last prompt moved the service to IronQR.Slim 2026.10.1 with IronSoftware.ReaderInternals.Windows 2026.3.47413.
  • Each duration adds up the logged time of the prompts on that guide's page. This guide's row is the acceptance prompt alone.
  • Last tested October 7, 2026, for all six runs.
GuideAssistant and versionModelDuration (minutes)
This guideClaude Code 2.1.277, one message, permission prompts offClaude Opus 529.0
Claude CodeClaude Code 2.1.277 on opusplanClaude Opus 5 for the plan, Claude Sonnet 5 for the rest30.2
ChatGPT CodexCodex CLI 0.160.0GPT-6 Luna37.2
GitHub CopilotGitHub Copilot CLI 1.0.91GPT-6 Luna, routed by Auto26.9
CursorCursor 3.23.23 desktop appGrok 4.750.8
Google AntigravityAntigravity CLI 1.3.1Gemini 3.8 Flash (High)53.6

Agent-Specific Guides

Each guide below applies the steps above to one tool and one QR job.

  • Use IronQR with Claude Code for branded marketing codes, decoding every variant of logo, colors, margins, size, and error correction
  • Use IronQR with ChatGPT Codex for decoding a backlog of scanned and photographed images in parallel with ReadAsync, with a report of every failure
  • Use IronQR with GitHub Copilot for stamping a verification code onto existing PDF pages, including password-protected files, in a document pipeline
  • Use IronQR with Cursor for reading codes from customer photos with the right scan mode, QR type, and corner points, under rules that keep other QR libraries out
  • Use IronQR with Google Antigravity for a Blazor Server scanner page that decodes uploads on the server and is checked in a real browser

Troubleshooting


Questions?

If you have any questions, reach out to support@ironsoftware.com

Curtis Chau
Technical Writer

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.

...
Read More

Ready to Get Started?

Nuget Downloads 76,271Version:2026.10just released

Get your free 30-day Trial Key instantly.
No credit card or account creation required
C# NuGet Library for PDF
Install with NuGet

Version: 2026.10

PM > Install-Package IronQR
nuget.org/packages/IronQR/
  1. In Solution Explorer, right-click References, Manage NuGet Packages
  2. Select Browse and search "IronQR"
  3. Select the package and install
C# PDF DLL
Download DLL

Version: 2026.10

  1. Download and unzip IronQR to a location such as ~/Libs within your Solution directory
  2. In Visual Studio Solution Explorer, right click References. Select Browse, "IronQR.dll"

Licenses from $999

Key in blue circle

Get your free 30-day Trial Key instantly

Your trial license will be sent to your email address

No limitations. 100% unlocked. No credit card.

bullet_checkedNo credit card or account creation requiredNo limitations. 100% unlocked. No credit card.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronQR
Book your free Live Demo
Booking Badge

Trusted by Millions of Engineers Worldwide

Iron Software's customer logos
Get a Quote, No Obligation
Your details will always be kept confidential.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Trusted by Millions of Engineers Worldwide
Get your free 30-day Trial Key instantly.
No credit card or account creation required
C# NuGet Library for PDF
Install with NuGet

Version: 2026.10

PM > Install-Package IronQR
nuget.org/packages/IronQR/
  1. In Solution Explorer, right-click References, Manage NuGet Packages
  2. Select Browse and search "IronQR"
  3. Select the package and install
C# PDF DLL
Download DLL

Version: 2026.10

  1. Download and unzip IronQR to a location such as ~/Libs within your Solution directory
  2. In Visual Studio Solution Explorer, right click References. Select Browse, "IronQR.dll"

Licenses from $999