--- title: Scanner API description: >- The Scanner API provides access to barcode and QR code scanning functionality on POS devices, allowing you to subscribe to scan events, monitor available scanner sources, and process scanned data in real-time. The API enables integration with device cameras, external scanners, and embedded scanning hardware. api_version: 2026-01 api_name: pos-ui-extensions source_url: html: >- https://shopify.dev/docs/api/pos-ui-extensions/latest/target-apis/platform-apis/scanner-api md: >- https://shopify.dev/docs/api/pos-ui-extensions/latest/target-apis/platform-apis/scanner-api.md --- # Scanner API The Scanner API provides access to barcode and QR code scanning functionality on POS devices, allowing you to subscribe to scan events, monitor available scanner sources, and process scanned data in real-time. The API enables integration with device cameras, external scanners, and embedded scanning hardware. #### Use cases * **Barcode scanning:** Implement barcode scanning for product lookup or inventory management. * **QR codes:** Build QR code scanning for customer engagement or loyalty programs. * **Custom workflows:** Create scanning workflows that process data and trigger business logic. * **Real-time feedback:** Implement real-time scanning feedback with immediate processing. ## Support Targets (10) ### Supported targets * [pos.​cart.​line-item-details.​action.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/cart-details#cart-details-action-modal-) * [pos.​customer-details.​action.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/customer-details#customer-details-action-modal-) * [pos.​draft-order-details.​action.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/draft-order-details#draft-order-details-action-modal-) * [pos.​exchange.​post.​action.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/post-exchange#post-exchange-action-modal-) * [pos.​home.​modal.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/home-screen#home-screen-action-modal-) * [pos.​order-details.​action.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/order-details#order-details-action-modal-) * [pos.​product-details.​action.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/product-details#product-details-action-modal-) * [pos.​purchase.​post.​action.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/post-purchase#post-purchase-action-modal-) * [pos.​register-details.​action.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/register-details#register-details-action-modal-) * [pos.​return.​post.​action.​render](https://shopify.dev/docs/api/pos-ui-extensions/2026-01/targets/post-return#post-return-action-modal-) ## ScannerApi The `ScannerApi` object provides access to scanning functionality and scanner source information. Access these properties through `shopify.scanner` to monitor scan events and available scanner sources. * **hideCameraScanner** **() => void** **required** Hide the camera scanner. * **scannerData** **ScannerData** **required** Access current scan data and subscribe to new scan events. Use to receive real-time scan results. * **showCameraScanner** **() => void** **required** Show the camera scanner. * **sources** **ScannerSources** **required** Access available scanner sources on the device. Use to check which scanners are available (camera, external, or embedded). ### ScannerData Represents the scanner interface for accessing scan events and subscription management. Provides real-time access to scanned data through a reactive signal pattern. * current Current available scanner sources with subscription support. The \`value\` property provides current sources, and \`subscribe\` listens for changes. Use to monitor which scanners are available. ```ts ReadonlySignalLike ``` ```ts export interface ScannerData { /** * Current available scanner sources with subscription support. The `value` property provides current sources, and `subscribe` listens for changes. Use to monitor which scanners are available. */ current: ReadonlySignalLike; } ``` ### ReadonlySignalLike Represents a reactive signal interface that provides both immediate value access and subscription-based updates. Enables real-time synchronization with changing data through the observer pattern. * subscribe Subscribes to value changes and calls the provided function whenever the value updates. Returns an unsubscribe function to clean up the subscription. Use to automatically react to changes in the signal's value. ```ts (fn: (value: T) => void) => () => void ``` * value The current value of the signal. This property provides immediate access to the current value without requiring subscription setup. Use for one-time value checks or initial setup. ```ts T ``` ```ts export interface ReadonlySignalLike { /** * The current value of the signal. This property provides immediate access to the current value without requiring subscription setup. Use for one-time value checks or initial setup. */ readonly value: T; /** * Subscribes to value changes and calls the provided function whenever the value updates. Returns an unsubscribe function to clean up the subscription. Use to automatically react to changes in the signal's value. */ subscribe(fn: (value: T) => void): () => void; } ``` ### ScannerSubscriptionResult Represents the data from a scanner event. Contains the scanned string data and the hardware source that captured the scan. * data The string data from the last scanner event received. Contains the scanned barcode, QR code, or other scannable data. Returns \`undefined\` when no scan data is available. Use to process scanned content and implement scan-based business logic. ```ts string ``` * source The scanning source from which the scan event came. Returns one of the following scanner types: • \`'camera'\` - Built-in device camera used for scanning • \`'external'\` - External scanner hardware connected to the device • \`'embedded'\` - Embedded scanner hardware built into the device ```ts ScannerSource ``` ```ts export interface ScannerSubscriptionResult { /** * The string data from the last scanner event received. Contains the scanned barcode, QR code, or other scannable data. Returns `undefined` when no scan data is available. Use to process scanned content and implement scan-based business logic. */ data?: string; /** * The scanning source from which the scan event came. Returns one of the following scanner types: * * • `'camera'` - Built-in device camera used for scanning * • `'external'` - External scanner hardware connected to the device * • `'embedded'` - Embedded scanner hardware built into the device */ source?: ScannerSource; } ``` ### ScannerSource The scanner source the POS device supports. ```ts 'camera' | 'external' | 'embedded' ``` ### ScannerSources Represents the available scanner hardware sources on the device. Provides reactive access to the list of scanners that can be used for scanning operations. * current Current available scanner sources with subscription support. The \`value\` property provides current sources, and \`subscribe\` listens for changes. Use to monitor which scanners are available. ```ts ReadonlySignalLike ``` ```ts export interface ScannerSources { /** * Current available scanner sources with subscription support. The `value` property provides current sources, and `subscribe` listens for changes. Use to monitor which scanners are available. */ current: ReadonlySignalLike; } ``` Examples ### Examples * #### Respond to scan events based on scanner source ##### Description Subscribe to scan events and adapt behavior based on the scanner source. This example shows how to use \`shopify.scanner.subscribe()\` to receive scan events and check \`shopify.scanner.source\` to determine which scanner type was used (camera, external scanner, or embedded hardware). By identifying the scanner type, you can customize handling based on the scanning method. ##### jsx ```jsx import {render} from 'preact'; import {useState, useEffect} from 'preact/hooks'; export default async () => { render(, document.body); }; const Extension = () => { const [scanData, setScanData] = useState(''); const [scanSource, setScanSource] = useState(''); const [hasCameraScanner, setHasCameraScanner] = useState(false); const [hasExternalScanner, setHasExternalScanner] = useState(false); useEffect(() => { const unsubscribeData = shopify.scanner.scannerData.current.subscribe((result) => { setScanData(result.data || ''); setScanSource(result.source || ''); }); const unsubscribeSources = shopify.scanner.sources.current.subscribe((sources) => { setHasCameraScanner(sources.includes('camera')); setHasExternalScanner(sources.includes('external')); }); return () => { unsubscribeData(); unsubscribeSources(); }; }, []); return ( Scanned data: {scanData} Scanned data source: {scanSource} {hasCameraScanner && ( Camera scanner is available )} {hasExternalScanner && ( External scanner is available )} ); }; ``` ## Best practices * **Handle scan events reactively:** Use `subscribe` methods to process scan events as they occur for immediate feedback. * **Validate scanned data:** Validate before processing and handle invalid codes, unsupported formats, or errors. * **Provide clear feedback:** Show success confirmations, error messages, and guidance when scans fail. * **Adapt to available sources:** Check available scanner sources and provide alternatives when preferred methods aren't available. * **Handle scan data processing:** Scan data processing is reactive and requires proper subscription management to avoid memory leaks or unexpected behavior when components unmount. ## Limitations The Scanner API is only available in action (modal) targets where scanning functionality is supported and can't be used in other targets.