Rapidly Integrate Smart Data Capture

Fast, accurate barcode, passport, and ID scanning. Pre-built scanning UI and AR overlays. Scale to any size and get support at every stage.

Trusted by developers.
Chosen by Fortune 500 companies.

Development teams at six of the top ten Fortune 500 companies trust Scandit for unmatched performance, comprehensive device coverage, security, and developer support.

Barcode Scanning

Powerful, multifunctional SDK with unmatched speed and accuracy, award-winning, purpose-built mini workflows, and AR overlays.

MS Find demo app

Find packages with AR

MatrixScan Find scans multiple items and highlights the right one using AR.

private func setupRecognition() {

  context = DataCaptureContext.licensed

  camera = Camera.default
  context.setFrameSource(camera, completionHandler: nil)

  let cameraSettings = BarcodeCapture.recommendedCameraSettings
  cameraSettings.preferredResolution = .fullHD
  camera?.apply(cameraSettings, completionHandler: nil)

  let settings = BarcodeCaptureSettings()

  settings.set(symbology: .ean13UPCA, enabled: true)
  settings.set(symbology: .ean8, enabled: true)
  settings.set(symbology: .upce, enabled: true)
  settings.set(symbology: .code39, enabled: true)
  settings.set(symbology: .code128, enabled: true)
  settings.set(symbology: .dataMatrix, enabled: true)

  settings.locationSelection = RadiusLocationSelection(radius: .zero)

  settings.codeDuplicateFilter = 1

  barcodeCapture = BarcodeCapture(context: context, settings: settings)

  barcodeCapture.addListener(self)

  captureView = DataCaptureView(context: context, frame: view.bounds)
  captureView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  view.addSubview(captureView)

  overlay = BarcodeCaptureOverlay(barcodeCapture: barcodeCapture, view: captureView, style: .frame)
  overlay.brush = Brush.scanned
  overlay.viewfinder = AimerViewfinder()
}

Optimized barcode scanning, fast

SparkScan gives you top performance and optimized UX with just a few lines of code.

private lazy var sparkScan: SparkScan = {
  let settings = SparkScanSettings()
  Set<Symbology>([.ean8, .ean13UPCA, .upce, .code39, .code128, .interleavedTwoOfFive]).forEach {
    settings.set(symbology: $0, enabled: true)
  }
  settings.settings(for: .code39).activeSymbolCounts = Set(7...20)

  let mode = SparkScan(settings: settings)
  return mode
}()

private var sparkScanView: SparkScanView!

private var items = [Item]()

override func viewDidLoad() {
  super.viewDidLoad()
  self.title = "List Building"
  setupRecognition()
  setupUI()
}

override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)
  sparkScanView.prepareScanning()
}

override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)
  sparkScanView.stopScanning()
}

extension ViewController {
  private func clearItems() {
    // Retrieve all the indexPaths, since we've to clear the whole list.
    let indexPaths = items.indexPaths
    // Update the model.
    items = []
    // Update the view.
    itemsTableViewHeader.itemsCount = items.totalCount
    tableView.deleteRows(
      at: indexPaths,
      with: .automatic
    )
  }

  private func addItem(_ item: Item) {
    // Retrieve the indexPath for the item to be added.
    let indexPath = items.addItemIndexPath
    // Update the model.
    items.insert(item, at: indexPath.row)
    // Update the view.
    itemsTableViewHeader.itemsCount = items.totalCount
    tableView.insertRows(
      at: [indexPath],
      with: .right
    )
  }
}

Count inventory quickly

MatrixScan Count scans and counts multiple items simultaneously.

func setupRecognition() {

  context = DataCaptureContext.licensed

  camera = Camera.default
  context.setFrameSource(camera, completionHandler: nil)

  let recommendedCameraSettings = BarcodeCount.recommendedCameraSettings
  camera?.apply(recommendedCameraSettings)

  let settings = BarcodeCountSettings()

  settings.set(symbology: .ean13UPCA, enabled: true)
  settings.set(symbology: .ean8, enabled: true)
  settings.set(symbology: .upce, enabled: true)
  settings.set(symbology: .code39, enabled: true)
  settings.set(symbology: .code128, enabled: true)

  barcodeCount = BarcodeCount(context: context, settings: settings)

  barcodeCount.addListener(self)

  barcodeCountView = BarcodeCountView(
    frame: view.bounds, context: context, barcodeCount: barcodeCount)
  barcodeCountView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  view.addSubview(barcodeCountView)
  barcodeCountView.uiDelegate = self
}

private func prepareScannedItemsList(
  trackedBarcodes: [TrackedBarcode],
  previousBarcodes: [Barcode]
) -> [ScannedItem] {
  var tempMap: [String: ScannedItem] = [:]
  var allBarcodes = trackedBarcodes.compactMap { $0.barcode }
  allBarcodes.append(contentsOf: previousBarcodes)
  for barcode in allBarcodes {
    guard let barcodeData = barcode.data else {
      continue
    }
    if var item = tempMap[barcodeData] {
      item.quantity += 1
      tempMap[barcodeData] = item
    } else {
      let newItem = ScannedItem(
        symbology: barcode.symbology.description.uppercased(),
        data: barcodeData,
        quantity: 1)
      tempMap[barcodeData] = newItem
    }
  }

  return Array(tempMap.values)
}

Passport and ID Scanning

SDK for fast, accurate, and secure scanning and verification of identity documents.

Add ID scanning to websites quickly

ID Bolt is a complete, foolproof passport or ID scanning workflow maintained by Scandit.

import {
	DocumentSelection,
	IdBoltSession,
	Region,
	Passport,
	ReturnDataMode,
	Validators,
} from "@scandit/web-id-bolt";

const ID_BOLT_URL = "https://app.id-scanning.com";

const LICENSE_KEY = "-- YOUR LICENSE KEY HERE --";

async function startIdBolt() {
	// define which documents are allowed to be scanned. More complex rules can be added.
	const documentSelection = DocumentSelection.create({
		accepted: [new Passport(Region.Any)],
	});
	// initialization of the ID Bolt session
	const idBoltSession = IdBoltSession.create(ID_BOLT_URL, {
		licenseKey: LICENSE_KEY,
		documentSelection,
		// define what data you expect in the onCompletion listener (set below)
		returnDataMode: ReturnDataMode.Full,
		// add validation rules on the scanned document
		validation: [Validators.notExpired()],
		locale: "en",
	});
	// open the pop-up
	await idBoltSession.start();

	// register some listeners:
	idBoltSession.onCancellation = (reason) => {
		// the ID Bolt pop-up has been closed by the user without finishing the scan process.
	};
	idBoltSession.onCompletion = (result) => {
		// the ID has been captured and validation was successful. In this example the result
		// will contain the document data because `returnDataMode` was set to RETURN_DATA_MODE.FULL.
	};
}

// open ID Bolt when some button is clicked
const someButton = document.getElementById("someButton") as HTMLButtonElement;
someButton.addEventListener("click", startIdBolt);

Accurately capture ID data

ID Scan extracts data from passports, ID cards, visa stickers, drivers’ licenses, military IDs, and more.

private func setupModeCollection() {
  let layout = UICollectionViewFlowLayout()
  layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
  layout.minimumInteritemSpacing = 10
  layout.scrollDirection = .horizontal
  let modeCollection = ModeCollectionViewController(collectionViewLayout: layout)
  modeCollection.items = Mode.allCases.map(\.rawValue)
  addChild(modeCollection)
  view.addSubview(modeCollection.view)
  modeCollection.view.translatesAutoresizingMaskIntoConstraints = false
  modeCollection.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
  modeCollection.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
  modeCollection.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
  modeCollection.view.heightAnchor.constraint(equalToConstant: Constants.modeCollectionHeight)
    .isActive = true
  modeCollection.delegate = self
  modeCollection.selectItem(atIndex: 0)
}

private func configure(mode: IdCaptureViewController.Mode) {
  context.removeAllModes()
  idCapture?.removeListener(self)
  if overlay != nil {
    captureView?.removeOverlay(overlay)
  }

  let settings = IdCaptureSettings()
  switch mode {
  case .barcode:
    configureBarcodeMode(settings: settings)
  case .mrz:
    configureMRZMode(settings: settings)
  case .viz:
    configureVIZMode(settings: settings)
  }

  idCapture = IdCapture(context: context, settings: settings)
  idCapture.addListener(self)

  overlay = IdCaptureOverlay(idCapture: idCapture, view: captureView)
  overlay.idLayoutStyle = .rounded
}

private func configureBarcodeMode(settings: IdCaptureSettings) {
  settings.supportedDocuments = [.aamvaBarcode]
}

private func configureVIZMode(settings: IdCaptureSettings) {
  settings.supportedDocuments = [.dlVIZ, .idCardVIZ]
  settings.supportedSides = .frontAndBack
}

private func configureMRZMode(settings: IdCaptureSettings) {
  settings.supportedDocuments = [.passportMRZ]
}

Detect fake IDs

ID Validate runs authenticity and validity checks to detect fake identity documents.

final class DLScanningVerificationRunner {
  typealias Result = Swift.Result<DLScanningVerificationResult, Error>

  let barcodeVerifier: AamvaBarcodeVerifier
  let vizBarcodeComparisonVerifier: AAMVAVizBarcodeComparisonVerifier

  init(_ context: DataCaptureContext) {
    self.barcodeVerifier = AamvaBarcodeVerifier(context: context)
    self.vizBarcodeComparisonVerifier = AAMVAVizBarcodeComparisonVerifier(context: context)
  }

  func verify(capturedId: CapturedId, _ completion: @escaping (Result) -> Void) {

    let vizBarcodeComparisonResult = vizBarcodeComparisonVerifier.verify(capturedId)
    guard vizBarcodeComparisonResult.checksPassed else {
      let mismatchImage = vizBarcodeComparisonResult.frontMismatchImage
      let showWarning = !vizBarcodeComparisonResult.mismatchHighlightingEnabled
      let warningText =
        showWarning ? "Your license does not support highlighting discrepancies" : nil
      completion(
        .success(
          DLScanningVerificationResult(
            status: .frontBackDoesNotMatch,
            image: mismatchImage,
            altText: warningText)))
      return
    }

    guard capturedId.isExpired == nil || !capturedId.isExpired! else {
      completion(.success(DLScanningVerificationResult(status: .expired)))
      return
    }

    runAAMVABarcodeVerification(capturedId, completion)
  }

  private func runAAMVABarcodeVerification(
    _ capturedId: CapturedId,
    _ completion: @escaping (Result) -> Void
  ) {
    barcodeVerifier.verify(capturedId) { result, error in
      if let result = result {
        switch result.status {
        case AamvaBarcodeVerificationStatus.authentic:
          completion(.success(DLScanningVerificationResult(status: .success)))
        case AamvaBarcodeVerificationStatus.likelyForged:
          completion(.success(DLScanningVerificationResult(status: .likelyForged)))
        case AamvaBarcodeVerificationStatus.forged:
          completion(.success(DLScanningVerificationResult(status: .forged)))
        }
      } else if let error = error {
        completion(.failure(error))
      }
    }
  }
}

Scandit Express app

Standalone barcode scanning app for iOS or Android. Instantly access high-performance scanning and advanced features including batch scanning and AR.

  • Turnkey app, no development time needed.
  • No need to change any software.
  • Deploy via MDM or EMM systems.

Support for all major barcode and ID types

ArUco symbology

ArUco

Symbology Aztec Code

Aztec Code

Symbology Codabar

Codabar

Symbology Code 11

Code 11

Symbology Code 128

Code 128

Symbology Code 25

Code 25

Symbology Code 32 Italian Pharmacode

CODE 32 Italian Pharmacode

Symbology Code 39

Code 39

Symbology Code 93

Code 93

Symbology Micro Datamatrix

Data Matrix

Symbology DotCode

DotCode

Driver's licenses

Symbology EAN code

EAN Code

Symbology GS1 Composite code type c

GS1 Composite Codes

Symbology GS1 databar

GS1 Databar

Symbology iata 2 of 5

IATA 2 of 5

ID cards

Symbology ITF

Interleaved 2 of 5 (ITF)

Symbology KIX

KIX

Symbology Matrix 2 of 5

Matrix 2 of 5

Symbology Maxicode

Maxicode

Symbology Micro QR code

Micro QR Code

MICROPDF417

Military IDs

Symbology MSI

MSI Plessey

Passports

Symbology PDF417

PDF417 Barcode

Symbology posi lapa

Posi LAPA 4 State Code

Symbology QR code

QR Code

Residency permits

symbology rectangular micro qr code

Rectangular Micro QR Code

Symbology RM4SCC

RM4SCC

Symbology UPC

UPC Code

UPU (Universal Postage Union) S18 4-State

UPU S18 4-State

Symbology USPS IM

USPS Intelligent Mail

Visas

Support for all major frameworks and programming languages

Free 30-day trial

Get started with a full-featured free trial today