Google ML Kit Barcode Scanning vs IronBarcode: C# Barcode Library Comparison
Google ML Kit's barcode scanning is genuinely impressive on Android. It powers Google Lens, it handles damaged and partially obscured codes, it works on-device without a network call, and it supports a wide range of 1D and 2D formats. When .NET developers encounter it in a barcode library comparison, those facts are accurate. What comparison articles often omit is that ML Kit has no .NET SDK, no NuGet package, and no C# API. This article is for developers who found ML Kit on a list and need to understand what "using ML Kit in a .NET project" actually means in practice — and what the managed-code equivalent looks like.
What Google ML Kit Barcode Scanning Is
Google ML Kit Barcode Scanning is a native mobile library. That is not a limitation to work around; it is the product's design. ML Kit ships in two flavors:
- Android: Distributed via Google Maven as
com.google.mlkit:barcode-scanning(Kotlin/Java). Requires Google Play Services on the target device. ProcessesInputImageobjects constructed from camera frames, file URIs, or bitmaps. - iOS: Distributed via CocoaPods as
GoogleMLKit/BarcodeScanning, with a Firebase dependency. Uses Swift or Objective-C.
There is no dotnet add package google-mlkit-barcode. There is no using Google.MLKit.BarcodeScanning;. Google does not publish a .NET binding for ML Kit.
Community-maintained Xamarin bindings have existed at various points, but they have a consistent problem: ML Kit updates its Android and iOS SDKs frequently, and binding projects maintained by individuals or small teams tend to lag behind or break entirely when the underlying API changes. As of 2026, there is no actively maintained, production-ready .NET NuGet package that wraps ML Kit's barcode scanner.
What ML Kit Does Well
Understanding why ML Kit appears in barcode comparisons is useful context. On native Android:
- On-device inference: No server round-trip. ML Kit's model runs locally using Google Play Services, which means low latency and no network dependency at scan time.
- Damage tolerance: The ML model handles damaged, partially obscured, or low-resolution barcodes better than many threshold-based decoders. This is a real differentiator for consumer-facing apps scanning real-world codes.
- Google Lens integration: ML Kit's scanner is the same stack that powers Google Lens barcode detection. That is a strong quality signal.
- Format breadth on mobile: QR Code, EAN-13, EAN-8, Code 128, Code 39, Code 93, Codabar, ITF, PDF417, Data Matrix, Aztec, and UPC-A/UPC-E are all supported natively.
- Zero configuration: A three-line Kotlin snippet can produce a working scanner without tuning thresholds or choosing a decoder strategy.
These are legitimate strengths. The issue for .NET developers is not that ML Kit is bad — it is that ML Kit is not available to them without significant work.
The .NET Development Reality
When a .NET developer needs to scan barcodes, the ML Kit path looks like this in practice:
No async/await C# API. ML Kit uses Android's Task API with addOnSuccessListener and addOnFailureListener callbacks. These do not map to .NET's Task<T> and await. Any binding layer must adapt between callback-based Android async and .NET's TPL — a non-trivial translation that community bindings handle inconsistently.
No .NET dependency injection integration. BarcodeScanning.getClient(options) is a static factory call that returns an Android BarcodeScanner object. There is no .NET interface to register, no IServiceCollection.AddBarcodeScanner(), no way to inject it into ASP.NET Core middleware or Azure Functions.
No ASP.NET Core or Azure Function support. ML Kit requires Android or iOS runtime context. It cannot run in a web API process on Linux, in an Azure Function, on Windows Server, or in a Docker container. If your use case is server-side barcode processing — a REST endpoint that accepts an image and returns barcode data, a document processing pipeline, a batch job — ML Kit is architecturally incompatible regardless of any binding availability.
Camera or frame input only — no file, no PDF. ML Kit's InputImage can be constructed from a Bitmap, a ByteBuffer, or a file URI on the Android filesystem. There is no concept of processing a PDF document, iterating pages, or handling a multi-page TIFF. Server-side document processing is outside the product's scope entirely.
Google Play Services dependency. The on-device ML model runs through Google Play Services. Devices without Google Play Services — custom Android builds, certain enterprise devices, Amazon Fire tablets — cannot use the default ML Kit configuration. The "bundled" model option (com.google.mlkit:barcode-scanning-bundled) works around this but increases APK size significantly.
Porting Android ML Kit Code to .NET
If you have an existing Android app with ML Kit barcode scanning and you are porting it to .NET MAUI or .NET 9, here is the translation. The Kotlin code uses ML Kit's callback pattern; the C# code uses IronBarcode's synchronous API.
// Android Kotlin: ML Kit
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_QR_CODE, Barcode.FORMAT_CODE_128)
.build()
val scanner = BarcodeScanning.getClient(options)
val inputImage = InputImage.fromFilePath(context, uri)
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
for (barcode in barcodes) {
val rawValue = barcode.rawValue
val format = barcode.format
}
}
.addOnFailureListener { e -> Log.e("MLKit", e.message ?: "") }
// .NET C#: IronBarcode
// NuGet: dotnet add package IronBarcode
using IronBarCode;
var results = BarcodeReader.Read("captured-image.jpg");
foreach (var barcode in results)
{
Console.WriteLine($"{barcode.Format}: {barcode.Value}");
}
// .NET C#: IronBarcode
// NuGet: dotnet add package IronBarcode
using IronBarCode;
var results = BarcodeReader.Read("captured-image.jpg");
foreach (var barcode in results)
{
Console.WriteLine($"{barcode.Format}: {barcode.Value}");
}
Imports IronBarCode
Dim results = BarcodeReader.Read("captured-image.jpg")
For Each barcode In results
Console.WriteLine($"{barcode.Format}: {barcode.Value}")
Next
The structural difference is more than syntax. The ML Kit version sets up a scanner object, constructs an InputImage, calls scanner.process(), and registers success and failure callbacks. If you need the result before proceeding, you have to coordinate callback execution with the rest of your logic — typically through a CountDownLatch in Java or coroutines in Kotlin.
IronBarcode's BarcodeReader.Read() returns a result collection synchronously. You iterate it immediately. There is no callback registration, no thread synchronization, no separate scanner object to manage.
For teams porting Android code, the pattern translation for multi-barcode scenarios looks like this:
// .NET C#: IronBarcode — reading multiple barcodes with options
using IronBarCode;
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
ExpectedBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128
};
var results = BarcodeReader.Read("image.jpg", options);
foreach (var barcode in results)
{
Console.WriteLine($"Format: {barcode.Format}, Value: {barcode.Value}");
}
// .NET C#: IronBarcode — reading multiple barcodes with options
using IronBarCode;
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
ExpectedBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128
};
var results = BarcodeReader.Read("image.jpg", options);
foreach (var barcode in results)
{
Console.WriteLine($"Format: {barcode.Format}, Value: {barcode.Value}");
}
Imports IronBarCode
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True,
.ExpectedBarcodeTypes = BarcodeEncoding.QRCode Or BarcodeEncoding.Code128
}
Dim results = BarcodeReader.Read("image.jpg", options)
For Each barcode In results
Console.WriteLine($"Format: {barcode.Format}, Value: {barcode.Value}")
Next
The ExpectedBarcodeTypes flag is the equivalent of ML Kit's setBarcodeFormats(). Setting it narrows the search and improves performance, but unlike ML Kit, leaving it unset does not break the read — IronBarcode will attempt all supported formats.
Format Coverage Comparison
Both tools cover the mainstream 2D and 1D formats. The overlap is substantial.
| Format | ML Kit (Android) | IronBarcode |
|---|---|---|
| QR Code | Yes | Yes |
| EAN-13 | Yes | Yes |
| EAN-8 | Yes | Yes |
| UPC-A | Yes | Yes |
| UPC-E | Yes | Yes |
| Code 128 | Yes | Yes |
| Code 39 | Yes | Yes |
| Code 93 | Yes | Yes |
| Codabar | Yes | Yes |
| ITF | Yes | Yes |
| PDF417 | Yes | Yes |
| Data Matrix | Yes | Yes |
| Aztec | Yes | Yes |
| Code 11 | No | Yes |
| MSI Plessey | No | Yes |
| Pharmacode | No | Yes |
| Interleaved 2 of 5 | Via ITF | Yes |
| RSS-14 / GS1 Databar | No | Yes |
| Micro QR | No | Yes |
| MaxiCode | No | Yes |
IronBarcode supports 50+ encoding types across both reading and generation. ML Kit's format list is fixed to what Google ships with the model — you cannot add custom symbologies.
What IronBarcode Adds
Beyond reading, IronBarcode covers the full barcode workflow:
Generation. ML Kit has no generation API at all — it reads barcodes, it does not create them. IronBarcode generates any supported format to PNG, JPEG, SVG, HTML, or binary data.
// Generate a Code 128 barcode to file
BarcodeWriter.CreateBarcode("SHIP-20240312-7834", BarcodeEncoding.Code128)
.SaveAsPng("shipping-label.png");
// Generate a Code 128 barcode to file
BarcodeWriter.CreateBarcode("SHIP-20240312-7834", BarcodeEncoding.Code128)
.SaveAsPng("shipping-label.png");
' Generate a Code 128 barcode to file
BarcodeWriter.CreateBarcode("SHIP-20240312-7834", BarcodeEncoding.Code128) _
.SaveAsPng("shipping-label.png")
QR code customization. QRCodeWriter supports logo embedding, color changes, and error correction levels — features that have no ML Kit equivalent because ML Kit does not generate anything.
// QR code with embedded logo and custom color
QRCodeWriter.CreateQrCode("https://example.com/product/4821", 500)
.AddBrandLogo("company-logo.png")
.ChangeBarCodeColor(System.Drawing.Color.DarkBlue)
.SaveAsPng("product-qr.png");
// QR code with embedded logo and custom color
QRCodeWriter.CreateQrCode("https://example.com/product/4821", 500)
.AddBrandLogo("company-logo.png")
.ChangeBarCodeColor(System.Drawing.Color.DarkBlue)
.SaveAsPng("product-qr.png");
' QR code with embedded logo and custom color
QRCodeWriter.CreateQrCode("https://example.com/product/4821", 500) _
.AddBrandLogo("company-logo.png") _
.ChangeBarCodeColor(System.Drawing.Color.DarkBlue) _
.SaveAsPng("product-qr.png")
PDF processing. BarcodeReader.Read("document.pdf") reads barcodes from every page of a PDF natively. No image extraction step, no page-by-page loop with a separate PDF library — it handles PDFs directly.
// Read all barcodes from every page of a PDF
var results = BarcodeReader.Read("invoice-batch.pdf");
foreach (var barcode in results)
{
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Value}");
}
// Read all barcodes from every page of a PDF
var results = BarcodeReader.Read("invoice-batch.pdf");
foreach (var barcode in results)
{
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Value}");
}
Imports System
' Read all barcodes from every page of a PDF
Dim results = BarcodeReader.Read("invoice-batch.pdf")
For Each barcode In results
Console.WriteLine($"Page {barcode.PageNumber}: {barcode.Value}")
Next
Server-side and cloud. IronBarcode runs on Windows, Linux, macOS, Docker, Azure Functions, and AWS Lambda. There is no Google Play Services requirement, no camera, no mobile runtime.
Binary output. .ToPngBinaryData() returns a byte[] directly — useful for APIs that return barcode images as HTTP responses without writing to disk.
// Generate barcode and return as byte array (e.g., in a web API)
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ORDER-8821", BarcodeEncoding.QRCode)
.ToPngBinaryData();
// Generate barcode and return as byte array (e.g., in a web API)
byte[] barcodeBytes = BarcodeWriter.CreateBarcode("ORDER-8821", BarcodeEncoding.QRCode)
.ToPngBinaryData();
' Generate barcode and return as byte array (e.g., in a web API)
Dim barcodeBytes As Byte() = BarcodeWriter.CreateBarcode("ORDER-8821", BarcodeEncoding.QRCode) _
.ToPngBinaryData()
Feature Comparison
| Feature | Google ML Kit Barcode | IronBarcode |
|---|---|---|
| .NET / C# API | None (no NuGet package) | Yes — using IronBarCode; |
| NuGet package | None | IronBarcode |
| Barcode reading | Yes (Android/iOS only) | Yes (all platforms) |
| Barcode generation | No | Yes (50+ formats) |
| QR code generation | No | Yes |
| QR logo embedding | No | Yes |
| PDF input support | No | Yes (native) |
| File input (PNG/JPEG) | Yes (via InputImage URI) | Yes |
| Camera / frame input | Yes (primary use case) | Via image file |
| Server-side processing | No | Yes |
| ASP.NET Core support | No | Yes |
| Azure Functions | No | Yes |
| Docker / Linux | No | Yes |
| Windows app support | No (Android/iOS only) | Yes |
| Google Play Services dep. | Yes (standard model) | No |
| Firebase dependency (iOS) | Yes | No |
| Async/await C# API | No | Synchronous (fits .NET model) |
| Multi-barcode in one image | Yes | Yes |
| Community .NET binding | Unofficial, unstable | N/A (native .NET) |
| Pricing | Free (as part of Google Play) | From $749 perpetual |
API Concept Mapping
Because there is no official .NET ML Kit API, this mapping is conceptual — it shows the intent of each ML Kit operation and the IronBarcode equivalent.
| ML Kit (Kotlin/Java concept) | IronBarcode (.NET C#) |
|---|---|
BarcodeScannerOptions.Builder() |
new BarcodeReaderOptions { } |
.setBarcodeFormats(FORMAT_QR_CODE) |
ExpectedBarcodeTypes = BarcodeEncoding.QRCode |
BarcodeScanning.getClient(options) |
Static — no scanner object needed |
InputImage.fromFilePath(context, uri) |
File path string passed to BarcodeReader.Read() |
InputImage.fromBitmap(bitmap, rotation) |
BarcodeReader.Read(stream) or byte array overload |
scanner.process(inputImage) |
BarcodeReader.Read(path, options) |
.addOnSuccessListener { barcodes -> } |
Return value of Read() — iterate directly |
.addOnFailureListener { e -> } |
Standard try/catch |
barcode.rawValue |
barcode.Value |
barcode.format |
barcode.Format |
barcode.boundingBox |
barcode.BarcodeImage (region data) |
Barcode.FORMAT_QR_CODE |
BarcodeEncoding.QRCode |
Barcode.FORMAT_CODE_128 |
BarcodeEncoding.Code128 |
| No generation API | BarcodeWriter.CreateBarcode() |
| No generation API | QRCodeWriter.CreateQrCode() |
Speed / model selection |
ReadingSpeed.Balanced / .Faster / .Detailed |
When to Consider IronBarcode
Porting an Android app to .NET MAUI or .NET 9. If your Android app uses ML Kit for barcode scanning and you are building a .NET equivalent, IronBarcode is the natural target. The concept translation is straightforward — read a file, get a result, iterate values.
Server-side barcode processing. Any scenario involving an HTTP endpoint that scans barcodes, a background job processing uploaded images, or a document workflow that extracts codes from PDFs. ML Kit cannot participate in any of these.
Windows desktop applications. WinForms, WPF, or .NET MAUI on Windows. ML Kit does not run on Windows at all.
Environments without Google Play Services. If your Android deployment includes devices that do not have Google Play Services — enterprise hardware, custom AOSP builds, Amazon Fire devices — the standard ML Kit model is unavailable. IronBarcode has no such dependency.
Generation alongside reading. If you need to both generate and read barcodes — print shipping labels and verify scans, for example — IronBarcode handles both in the same library. ML Kit handles neither generation nor server-side reading.
Azure or AWS deployment. Azure Functions, Azure App Service on Linux, AWS Lambda — none of these can host ML Kit. IronBarcode targets all of them.
Licensing and Pricing
Google ML Kit Barcode Scanning is free for Android and iOS apps. There is no per-scan fee and no commercial license required. That pricing model makes sense in its intended context — a native mobile library bundled with Google Play Services.
IronBarcode is a commercial .NET library with perpetual licenses:
- Lite: $749 — 1 developer, 1 project location
- Plus: $1,499 — up to 3 developers
- Professional: $2,999 — up to 10 developers
- Unlimited: $5,999 — unlimited developers
A free trial is available without a time limit; the trial watermarks generated barcodes. For teams already paying for server infrastructure to process documents, the license cost is typically a small fraction of the engineering effort required to maintain an unofficial ML Kit binding.
Conclusion
Google ML Kit Barcode Scanning is a well-engineered library that does exactly what it was designed to do: scan barcodes quickly and accurately on Android and iOS devices. The comparison with IronBarcode is less about which library is better and more about which library exists in the context where you need it.
If you are writing Kotlin for Android and scanning from a camera, ML Kit is an excellent choice. If you are writing C# for .NET — whether for a web API, a document processing service, a Windows application, a cloud function, or a cross-platform MAUI app — Google ML Kit has no offering for you. There is no NuGet package, no C# API, and no Google-supported path to using it in managed code. IronBarcode is a native .NET library that covers both reading and generation across every platform .NET supports.
Frequently Asked Questions
What is Google ML Kit Barcode Scanning?
Google ML Kit Barcode Scanning is a .NET barcode library for generating and reading barcodes in C# applications. It is one of several alternatives developers evaluate when selecting a barcode solution for .NET projects.
What are the main differences between Google ML Kit Barcode Scanning and IronBarcode?
IronBarcode uses a static, stateless API requiring no instance management, while Google ML Kit Barcode Scanning typically requires instance creation and configuration before use. IronBarcode also provides native PDF support, automatic format detection, and single-key licensing across all environments.
Is IronBarcode easier to license than Google ML Kit Barcode Scanning?
IronBarcode uses a single license key covering both development and production deployments. This simplifies CI/CD pipelines and Docker configurations compared to licensing systems that separate SDK keys from runtime keys.
Does IronBarcode support all barcode formats that Google ML Kit Barcode Scanning supports?
IronBarcode supports over 30 barcode symbologies including QR Code, Code 128, Code 39, DataMatrix, PDF417, Aztec, EAN-13, UPC-A, GS1, and many more. Format auto-detection means no explicit format enumeration is required.
Does IronBarcode support native PDF barcode reading?
Yes. IronBarcode reads barcodes directly from PDF files using BarcodeReader.Read("document.pdf") without requiring a separate PDF rendering library. Per-page results include page number, barcode format, value, and confidence score.
How does IronBarcode handle batch processing compared to Google ML Kit Barcode Scanning?
IronBarcode's static methods are stateless and naturally thread-safe, enabling direct use of Parallel.ForEach without per-thread instance management. There is no throughput ceiling at any pricing tier.
What .NET versions does IronBarcode support?
IronBarcode supports .NET Framework 4.6.2+, .NET Core 3.1, and .NET 5, 6, 7, 8, and 9 in a single NuGet package. Platform targets include Windows x64/x86, Linux x64, and macOS x64/ARM.
How do I install IronBarcode in a .NET project?
Install IronBarcode via NuGet: run 'Install-Package IronBarCode' in the Package Manager Console, or 'dotnet add package IronBarCode' in the CLI. No additional SDK installers or runtime files are required.
Can I evaluate IronBarcode before purchasing, unlike Google ML Kit?
Yes. IronBarcode's trial mode returns complete decoded barcode values — only generated output images receive a watermark. You can benchmark read accuracy on your own documents before committing to a purchase.
What is the pricing difference between Google ML Kit Barcode Scanning and IronBarcode?
IronBarcode starts at $749 for a perpetual single-developer license covering development and production. Pricing details and volume options are available on the IronBarcode licensing page. There is no separate runtime license requirement.
Is it straightforward to migrate from Google ML Kit Barcode Scanning to IronBarcode?
Migration from Google ML Kit Barcode Scanning to IronBarcode primarily involves replacing instance-based API calls with IronBarcode's static methods, removing licensing boilerplate, and updating result property names. Most migrations involve reducing code rather than adding it.
Does IronBarcode generate QR codes with logos?
Yes. QRCodeWriter.CreateQrCode().AddBrandLogo("logo.png") embeds a brand image in a QR code natively with configurable error correction. Colored QR codes are also supported via ChangeBarCodeColor().

