Scanbot SDK has been acquired by Apryse! Learn more

Learn more
Skip to content

Building a Flutter check scanner app for reading MICR codes

Kevin October 2, 2025 5 mins read
Flutter Data Capture SDK

In this tutorial, we’ll use Flutter to build a cross-platform app for Android and iOS that extracts the routing number, account number, and check number from the MICR (magnetic ink character recognition) line on paper checks.

To implement the scanning functionalities, we’ll use the Scanbot Check Scanner SDK.

Scanning the MICR line on a check with our Flutter check scanner app

Building our app involves the following steps:

  1. Preparing the project
  2. Initializing the SDK
  3. Setting up the main widget
  4. Implementing the check scanning feature

Prerequisites

  • Flutter SDK: Ensure you have the latest version installed.
  • Development tools:
    • For Android: Android Studio with the Android SDK.
    • For iOS: macOS with the latest Xcode and CocoaPods installed.
    • Optional: Visual Studio Code with the Flutter and Dart extensions.

Step 1: Prepare the project

Open your terminal and execute:

flutter create check_scanner_app
cd check_scanner_app

Then open pubspec.yaml and add the scanbot_sdk dependency.

dependencies:
  flutter:
    sdk: flutter
  scanbot_sdk: ^7.1.0

Fetch the package.

flutter pub get

💡 We use SDK version 7.1.0 in this tutorial. You can find the latest version in the changelog.

We need to access the device camera to scan machine-readable zones, so open android/app/src/main/AndroidManifest.xml and add the necessary permissions for Android:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

For iOS, open ios/Runner/Info.plist and add:

<key>NSCameraUsageDescription</key>
<string>Grant camera access to start scanning.</string>

Step 2: Initialize the SDK

Before we can use the Scanbot SDK, we need to initialize it. Make sure to call the initialization after entering the main widget creation. This ensures the SDK is correctly initialized.

In lib/main.dart, import the Scanbot SDK package:

import 'package:scanbot_sdk/scanbot_sdk.dart';
import 'package:scanbot_sdk/scanbot_sdk_ui_v2.dart';

Within your main widget, initialize the Scanbot SDK. This is typically done in the initState method of your main widget’s state class:

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
    _initScanbotSdk();
  }

  Future<void> _initScanbotSdk() async {
    var config = ScanbotSdkConfig(
      licenseKey: "",
      loggingEnabled: true,
    );

    try {
      await ScanbotSdk.initScanbotSdk(config);
      print('Scanbot SDK initialized successfully');
    } catch (e) {
      print('Error initializing Scanbot SDK: $e');
    }
  }
  //...

💡 Without a license key, our SDK only runs for 60 seconds per session. This is more than enough for the purposes of our tutorial, but if you like, you can generate a license key using your app identifier.

Step 3: Set up the main widget

Next, we’ll create a simple user interface that includes a button to initiate the scanning process. Still in lib/main.dart, and in your main widget’s state class, define a widget with a button labeled “Scan MICR Code”:

class _MyHomePageState extends State<MyHomePage> {
  // ... (existing code)

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Check Scanner'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _startCheckScanner,
          child: Text('Scan MICR Code'),
        ),
      ),
    );
  }

  Future<void> _startCheckScanner() async {
    // To be implemented in the next step
  }
}

Next, we’ll connect the button with our RTU UI’s scanning screen.

Step 4: Implement the check scanning feature

Within the _startCheckScanner method, configure and launch the scanning UI. This involves creating an CheckScannerScreenConfiguration and starting the scanner:

Future<void> _startCheckScanner() async {
  try {
    final licenseInfo = await ScanbotSdk.getLicenseStatus();
    if (!licenseInfo.isLicenseValid) {
      return;
    }

    final configuration = CheckScannerScreenConfiguration();
    final result = await ScanbotSdkUiV2.startCheckScanner(configuration);

    if (result.status == OperationStatus.OK && result.data?.check != null) {}
  } catch (e) {
    print('Error: $e');
  }
}

Now we’ll need to process the scan result. In this example, we’ll look for the Indian check format (INDCheck). For the full list of supported check formats, please refer to the SDK’s API documentation.

Once we have the check information, we can extract the specific data we need. In this example, we’ll extract the routing number, account number, and check number and display them to the user.

Future<void> _startCheckScanner() async {
    try {
      final licenseInfo = await ScanbotSdk.getLicenseStatus();
      if (!licenseInfo.isLicenseValid) {
        return;
      }

      final configuration = CheckScannerScreenConfiguration();
      final result = await ScanbotSdkUiV2.startCheckScanner(configuration);

if (result.status == OperationStatus.OK && result.data?.check != null) {
        final checkDocument = result.data?.check;
        if (checkDocument!.type.name == 'INDCheck') {
          final check = INDCheck(checkDocument);
          if (Navigator.of(context).mounted) {
            showDialog(
              context: context,
              builder: (BuildContext context) {
                return AlertDialog(
                  title: const Text("Check data:"),
                  content: Text(
                    "Routing number: ${check.sortNumber?.value?.text ?? 'N/A'}\n"
                    "Account number: ${check.accountNumber.value?.text ?? 'N/A'}\n"
                    "Check number: ${check.serialNumber.value?.text ?? 'N/A'}",
                  ),
                  actions: <Widget>[
                    TextButton(
                      child: const Text("OK"),
                      onPressed: () {
                        Navigator.of(context).pop();
                      },
                    ),
                  ],
                );
              },
            );
          }
        }
      }
    } catch (e) {
      print('Error: $e');
    }
  }

In this tutorial, we use a default configuration object. For more information on how to customize the scanning UI, please refer to the SDK’s RTU UI documentation.

Now build and run the app and scan the MICR line on a check …

Example of a paper check with an MICR code at the bottom

… to test your scanner!

Scanning the MICR line on a check with our Flutter check scanner app

Conclusion

And that’s it! You’ve successfully built a cross-platform check scanner app with Flutter 🎉

If this tutorial has piqued your interest in integrating scanning functionalities into your Flutter app, make sure to take a look at the SDK’s other neat features in the documentation – or run our example project for a more hands-on experience.

Should you have questions about this tutorial or run into any issues, we’re happy to help! Just shoot us an email via tutorial-support@scanbot.io.

Happy scanning! 🤳

Related blog posts

Experience our demo apps

Barcode Icon Art

Barcode Scanner SDK

Scan 1D and 2D barcodes reliably in under 0.04s. Try features like Batch Scanning, Scan & Count, and our AR Overlays.

Launch Web Demo

Scan the code to launch the web demo on your phone.

Web QR Code

Also available to download from:

Document Icon Art

Document Scanner SDK

Scan documents quickly and accurately with our free demo app. Create crisp digital scans in seconds.

Launch Web Demo

Scan the code to launch the web demo on your phone.

Black and white QR code. Scan this code for quick access to information.

Also available to download from:

Data_capture Icon Art

Data Capture Modules

Try fast, accurate data capture with our demo app. Extract data from any document instantly – 100% secure.

Launch Web Demo

Scan the code to launch the web demo on your phone.

Black and white QR code. Scan this quick response code with your smartphone.

Also available to download from: