Skip to main content
Speed up Smart Label Capture integration with Agent Skills

Install the Scandit plugin and use the /label-capture-ios skill so that your AI coding agent can integrate, debug, and customize Smart Label Capture on iOS following Scandit's recommended patterns. More info →

Run the following command in your project directory. It detects the supported coding agents you have installed and adds the Scandit plugin to each. Re-run it to update.

npx plugins add scandit/skills

Prefer to set it up yourself? Manual installation steps for each agent →

Scan shipping labels

Shipping Label Scanning reads a shipping label and returns its tracking ID, the receiver's name and address, and the carrier. Like receipt scanning, it uses the Adaptive Recognition Engine, which processes the label in the cloud.

To read your own set of fields on the device instead, define a custom label.

Beta

Shipping Label Scanning requires the Adaptive Recognition Engine, which is still in beta and may change in future versions of Scandit Data Capture SDK. To enable it on your subscription, contact support@scandit.com.

Before you start​

  • Use Scandit Data Capture SDK 8.6.0 or later. Shipping Label Scanning is available on iOS, Android, and Web. It isn't available on other frameworks yet.
  • Ask support@scandit.com to enable the Adaptive Recognition Engine on your subscription.
  • Make sure the device has a network connection. The Adaptive Recognition Engine processes the label in the cloud.
  • Set up a LabelCapture instance and a DataCaptureView. If you haven't done this yet, follow Get started.

Create the LabelCapture instance with LabelCaptureSettings that have no label definitions. The overlay adds its own definition for the tracking barcode. Label definitions that you add stay active alongside it, so a barcode that isn't the tracking barcode can end up as the trackingId.

let labelCaptureSettings = try LabelCaptureSettings(labelDefinitions: [])
let labelCapture = LabelCapture(context: context, settings: labelCaptureSettings)

Steps​

1. Create the settings​

Create LabelCaptureAdaptiveRecognitionSettings with the result type AdaptiveRecognitionResultType.shippingLabel. The result type sets the kind of document that the overlay looks for.

To change the hint that the overlay shows while it processes a label, use processingHintText.

import ScanditLabelCapture

let settings = LabelCaptureAdaptiveRecognitionSettings(resultType: .shippingLabel)

2. Create the overlay​

Create the overlay with LabelCaptureAdaptiveRecognitionOverlay(labelCapture:view:). Then apply the settings with apply(_:).

When you pass your DataCaptureView, the overlay adds itself to the view. If you pass nil instead, add the overlay yourself with DataCaptureView.addOverlay(_:).

let overlay = LabelCaptureAdaptiveRecognitionOverlay(labelCapture: labelCapture, view: dataCaptureView)
overlay.apply(settings)

3. Listen for results​

Set a LabelCaptureAdaptiveRecognitionDelegate as the overlay's delegate. It receives two callbacks:

The overlay holds its delegate weakly, so keep a strong reference to the delegate object.

overlay.delegate = self

extension YourScanViewController: LabelCaptureAdaptiveRecognitionDelegate {
func labelCaptureAdaptiveRecognitionOverlay(_ overlay: LabelCaptureAdaptiveRecognitionOverlay,
didRecognizeWith result: AdaptiveRecognitionResult) {
guard let shippingLabel = result as? ShippingLabelScanningResult else { return }

let trackingId = shippingLabel.trackingId
let receiverName = shippingLabel.receiverFullName
let receiverCompany = shippingLabel.receiverCompany // nil if the label doesn't show one
let carrier = shippingLabel.carrier
}

func labelCaptureAdaptiveRecognitionOverlayDidFail(_ overlay: LabelCaptureAdaptiveRecognitionOverlay) {
// Recognition failed, for example because of a connection error.
}
}

4. Switch the camera back on​

When the overlay starts to process a label, it switches the camera to standby. It doesn't switch the camera back on after a result. To scan the next label, call the camera's switch(toDesiredState: .on) in labelCaptureAdaptiveRecognitionOverlay(_:didRecognizeWith:) after you handle the result.

The overlay doesn't switch the camera back on after a failure either. Call switch(toDesiredState: .on) in labelCaptureAdaptiveRecognitionOverlayDidFail(_:) too, so that you can scan the label again.

func labelCaptureAdaptiveRecognitionOverlay(_ overlay: LabelCaptureAdaptiveRecognitionOverlay,
didRecognizeWith result: AdaptiveRecognitionResult) {
// Handle the result, then get ready for the next label.
camera?.switch(toDesiredState: .on)
}

func labelCaptureAdaptiveRecognitionOverlayDidFail(_ overlay: LabelCaptureAdaptiveRecognitionOverlay) {
// Get ready to scan the label again.
camera?.switch(toDesiredState: .on)
}

Shipping label fields​

ShippingLabelScanningResult has the following fields:

FieldTypeDescription
trackingIdStringThe tracking identifier, read from the tracking barcode on the label.
receiverFullNameStringThe receiver's full name.
receiverCompanyString?The receiver's company. nil if the label doesn't show one.
receiverStreetStringThe street of the receiver's address.
receiverCityStringThe city of the receiver's address.
receiverStateString?The state of the receiver's address. nil if the label doesn't show one.
receiverPostalCodeStringThe postal code of the receiver's address.
receiverCountryString?The country of the receiver's address. nil if the label doesn't show one.
carrierCarrierThe postal provider of the label. See Carriers.

jsonString returns the result as a JSON string.

Handle missing values​

Carriers​

Carrier has the following values. The SDK maps the carrier that the engine identifies on the label to one of these values. The list can grow in future SDK versions.

CarrierValue
FedExCarrier.fedEx
United Parcel Service (UPS)Carrier.ups
United States Postal Service (USPS)Carrier.usps
DHLCarrier.dhl
DPDCarrier.dpd
GLSCarrier.gls
TNTCarrier.tnt
Amazon LogisticsCarrier.amazonLogistics
OnTracCarrier.onTrac
Royal MailCarrier.royalMail
ParcelforceCarrier.parcelforce
EvriCarrier.evri
YodelCarrier.yodel
ChronopostCarrier.chronopost
ColissimoCarrier.colissimo
Mondial RelayCarrier.mondialRelay
Poste ItalianeCarrier.posteItaliane
BRTCarrier.brt
SDACarrier.sda
HermesCarrier.hermes
Austrian PostCarrier.austrianPost
Swiss PostCarrier.swissPost
PostNLCarrier.postNL
bpostCarrier.bpost
PostNordCarrier.postNord
CorreosCarrier.correos
SEURCarrier.seur
InPostCarrier.inPost
Classified by the engine as otherCarrier.other
Not identified, or not in this listCarrier.notAvailable

Verify it works​

You're done when:

  • The overlay shows its processing hint after you point the camera at a shipping label.
  • Your labelCaptureAdaptiveRecognitionOverlay(_:didRecognizeWith:) callback receives a ShippingLabelScanningResult, and you can read its trackingId and carrier.
  • Your labelCaptureAdaptiveRecognitionOverlay(_:didRecognizeWith:) code switches the camera back on after each result, so you can scan the next label.
  • Your labelCaptureAdaptiveRecognitionOverlayDidFail(_:) code also switches the camera back on, so you can scan the label again.

Processing starts only after the SDK decodes a tracking barcode on the label. The tracking barcode must be Code 128, Code 39, ITF, Data Matrix, or PDF417. Processing also requires a license key that includes Adaptive Recognition. If the overlay never shows its processing hint, check that the label has one of these barcodes and that your license key includes Adaptive Recognition.

If labelCaptureAdaptiveRecognitionOverlayDidFail(_:) runs instead, recognition failed, for example because of a network problem or a label the engine can't read. Check the network connection, then scan the label again.