---
title: How to Build an Ionic Barcode Scanner with Capacitor
description: Create a cross-platform barcode scanner app using Ionic Framework and Capacitor with ML Kit Barcode Scanning.
date: 
  created: 2023-03-29
  updated: 2026-07-17
authors:
  - robingenz
categories:
  - Capacitor
  - Guides
  - ML Kit
  - SDKs
links:
  - Capacitor ML Kit Barcode Scanning: sdks/capacitor/mlkit/barcode-scanning.md
# canonical_url: https://ionic.io/blog/how-to-build-an-ionic-barcode-scanner-with-capacitor
faq: true
---

# How to Build an Ionic Barcode Scanner with Capacitor

Capacitor lets you build a cross-platform app from one codebase. In combination with the Ionic Framework, we also have a modern open source mobile UI toolkit. We will use these technologies to create a complete barcode scanner app for Android and iOS in 15 minutes.

<!-- more -->

Highlights include:

- One Angular codebase that runs on Android and iOS using Capacitor.
- Barcode Scanning functionality powered by ML Kit, Google’s machine learning SDK for Android and iOS.

Find the complete app code referenced in this guide [on GitHub](https://github.com/capawesome-team/ionic-capacitor-barcode-scanner){:target="_blank"}.

<figure>
  <video width="300" autoplay loop muted playsinline>
    <source src="/docs/assets/videos/posts/how-to-build-an-ionic-barcode-scanner-with-capacitor/barcode-scanner-demo.mp4" type="video/mp4">
  </video>
  <figcaption>Capacitor Barcode Scanner Demo</figcaption>
</figure>

## Download Required Tools

Download and install the following tools to ensure an optimal developer experience:

- [Node.js](https://nodejs.org/en/download){:target="_blank"} to install the required dependencies
- A code editor for... writing code! **Tip**: Visual Studio Code supports the new [Ionic VS Code Extension](https://ionicframework.com/docs/intro/vscode-extension){:target="_blank"}
- [Android Studio](https://developer.android.com/studio){:target="_blank"} to build the Android app
- [Xcode](https://apps.apple.com/de/app/xcode/id497799835){:target="_blank"} to build the iOS app (only available on macOS)

## Create a new App

To create a new project, we use the Ionic CLI. For this, first install the CLI globally:

```bash
npm i -g @ionic/cli
```

Then you can create a new project with the `ionic start` command:

```bash
npx ionic start barcode-scanner blank --type=angular --capacitor
```

In this case, the app is called `barcode-scanner`, the starter template is `blank` and the project type for the purposes of this guide is Angular. You can also choose Vue or React, for example. Additionally, we enable the Capacitor integration with `--capacitor`.

Once everything is ready, you should see this output:

```bash
Your Ionic app is ready! Follow these next steps:

- Go to your new project: cd .\barcode-scanner
- Run ionic serve within the app directory to see your app in the browser
- Run ionic capacitor add to add a native iOS or Android project using Capacitor
- Generate your app icon and splash screens using cordova-res --skip-config --copy
- Explore the Ionic docs for components, tutorials, and more: https://ion.link/docs
- Building an enterprise app? Ionic has Enterprise Support and Features: https://ion.link/enterprise-edition
```

### Add the Android Platform

Now let's add the Android platform.

For this, first install the `@capacitor/android` package:

```bash
npm install @capacitor/android
```

After that you add the platform:

```bash
npx cap add android
```

### Add the iOS Platform

Install the `@capacitor/ios` package:

```bash
npm install @capacitor/ios
```

After that you add the platform:

```bash
npx cap add ios
```

## Add the Barcode Scanner

### Install the Plugin

To use the ML Kit Barcode Scanning SDK in Capacitor, we need to install the [Capacitor ML Kit Barcode Scanning](../../sdks/capacitor/mlkit/barcode-scanning.md) plugin:

```bash
npm install @capacitor-mlkit/barcode-scanning
npx ionic cap sync
```

On Android, the SDKs also require the following permissions in the `AndroidManifest.xml` before or after the `application` tag:

```xml title="android/app/src/main/AndroidManifest.xml"
<!-- To get access to the camera. -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- To get access to the flashlight. -->
<uses-permission android:name="android.permission.FLASHLIGHT"/>
```

You also need to add the following meta data in the `application` tag in your `AndroidManifest.xml`:

```xml title="android/app/src/main/AndroidManifest.xml"
<meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="barcode_ui"/>
```

On iOS, add the `NSCameraUsageDescription` key to the `ios/App/App/Info.plist` file, which tells the user why the app needs to use the camera:

```xml title="ios/App/App/Info.plist"
<key>NSCameraUsageDescription</key>
<string>The app enables the scanning of various barcodes.</string>
```

The plugin is now ready to use.

### Build the UI

To scan a barcode, call the [`scan(...)`](../../sdks/capacitor/mlkit/barcode-scanning.md/#scan) method of the plugin and receive the scanned barcode as a result. To request the necessary permissions and to show the user a dialog in case of missing permissions, we will also use the [`requestPermissions()`](../../sdks/capacitor/mlkit/barcode-scanning.md/#requestpermissions) method.

The following code goes to your `src/app/home/home.page.ts`:

```ts title="src/app/home/home.page.ts" linenums="1"
import { Component, OnInit } from "@angular/core";
import { Barcode, BarcodeScanner } from "@capacitor-mlkit/barcode-scanning";
import { AlertController } from "@ionic/angular";

@Component({
  selector: "app-home",
  templateUrl: "home.page.html",
  styleUrls: ["home.page.scss"],
})
export class HomePage implements OnInit {
  isSupported = false;
  barcodes: Barcode[] = [];

  constructor(private alertController: AlertController) {}

  ngOnInit() {
    BarcodeScanner.isSupported().then((result) => {
      this.isSupported = result.supported;
    });
  }

  async scan(): Promise<void> {
    const granted = await this.requestPermissions();
    if (!granted) {
      this.presentAlert();
      return;
    }
    const { barcodes } = await BarcodeScanner.scan();
    this.barcodes.push(...barcodes);
  }

  async requestPermissions(): Promise<boolean> {
    const { camera } = await BarcodeScanner.requestPermissions();
    return camera === "granted" || camera === "limited";
  }

  async presentAlert(): Promise<void> {
    const alert = await this.alertController.create({
      header: "Permission denied",
      message: "Please grant camera permission to use the barcode scanner.",
      buttons: ["OK"],
    });
    await alert.present();
  }
}
```

To make the scanning process even faster and to reduce the error rate even further, you could filter on the formats you are looking for (e.g. QR codes[^1]) using the `formats` option. However, we leave this up to you.

The only thing missing is the template. To keep the app simple, we list all scanned barcodes with [`ion-list`](https://ionicframework.com/docs/api/list){:target="_blank"}. The scanning process is started via a floating action button in the bottom right corner.

For this, change your `src/app/home/home.page.html` to:

```html title="src/app/home/home.page.html" linenums="1"
<ion-header>
  <ion-toolbar>
    <ion-title>Barcode Scanner</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item *ngFor="let barcode of barcodes">
      <ion-label position="stacked">{{ barcode.format }}</ion-label>
      <ion-input type="text" [value]="barcode.rawValue"></ion-input>
    </ion-item>
  </ion-list>
  <ion-fab slot="fixed" vertical="bottom" horizontal="end">
    <ion-fab-button (click)="scan()" [disabled]="!isSupported">
      <ion-icon name="scan"></ion-icon>
    </ion-fab-button>
  </ion-fab>
</ion-content>
```

Now everything is ready for the first launch! 🎉

## Run the App

Run the app and scan your first barcode or QR code[^1]:

```bash
# Run the Android platform
npx ionic cap run android

# Run the iOS platform
npx ionic cap run ios
```

## FAQ

### Does this barcode scanner work on the web?

No — ML Kit is Google's native machine learning SDK for Android and iOS, and it has no web implementation. If you also need web support, combine this plugin with a separate web-only library like `zxing-js/library` or the (still experimental) Barcode Detection API, and branch your scanning code by platform.

### Why does my app crash when I tap the scan button on iOS?

Almost always a missing camera usage description. iOS requires the `NSCameraUsageDescription` key in `Info.plist` before it lets any app access the camera — without it, the app crashes rather than showing a permission prompt. Double-check that key is set with a real explanation, not left as a placeholder.

### Why does `BarcodeScanner.isSupported()` exist if the plugin already handles permissions?

They check two different things. `isSupported()` verifies the device itself can run ML Kit barcode scanning at all (not every emulator or device configuration can), while `requestPermissions()` handles the separate question of whether the user has granted camera access. Checking support first and disabling the scan button when it returns `false` avoids showing a permission prompt on a device that could never scan anyway.

### Can I limit scanning to just QR codes instead of every barcode format?

Yes, using the `formats` option on the `scan()` call. Restricting to specific formats you care about (like QR codes) both speeds up scanning and reduces false-positive reads, since the SDK isn't spending cycles trying to match formats you don't need.

### Does this plugin support scanning multiple barcodes in one pass, or just one at a time?

The example in this guide scans one at a time, but the plugin itself supports scanning multiple barcodes simultaneously along with torch control. See the [announcement of the Capacitor ML Kit Barcode Scanning plugin](./announcing-the-capacitor-mlkit-barcode-scanner-plugin.md) for those additional capabilities beyond what's shown in this walkthrough.

## Conclusion

If your app ships on Android and iOS, make this plugin your default scanner and stop there. Only reach for [zxing-js/library](https://github.com/zxing-js/library){:target="_blank"} or the [Barcode Detection API](https://developer.mozilla.org/en-US/docs/Web/API/Barcode_Detection_API){:target="_blank"} (still experimental) when the Web platform is also on your list, because Google's machine learning SDK does not support it.

From here, read the [announcement of the Capacitor ML Kit Barcode Scanning plugin](./announcing-the-capacitor-mlkit-barcode-scanner-plugin.md) to add scanning of multiple barcodes at once and torch support, then the [API Reference](https://github.com/capawesome-team/capacitor-mlkit/tree/main/packages/barcode-scanning#api){:target="_blank"} for the remaining options. For text recognition, image labeling, and on-device GenAI in the same app, check out [Capacitor ML Kit 8.2.0: 14 New Plugins](./capacitor-mlkit-8-2-0-release.md). If you have any questions, [create a discussion](https://github.com/capawesome-team/capacitor-mlkit/discussions/new/choose){:target="_blank"} in the GitHub repository. Make sure you follow [Capawesome](https://twitter.com/capawesomeio){:target="_blank"} on X so you don't miss any future updates.

---

[^1]: `QR Code` is a registered trademark of DENSO WAVE INCORPORATED.
