--- 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: 2025-10 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 APIAPIs 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. ## 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. * scannerData ScannerData required Access current scan data and subscribe to new scan events. Use to receive real-time scan results. * 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 locale changes and calls the provided function whenever the locale updates. Returns an unsubscribe function to clean up the subscription. Use to automatically update your extension content when merchants change their language settings during POS sessions. ```ts (fn: (value: T) => void) => () => void ``` * value The current value of the locale string in IETF format. For example, \`"en-US"\`, \`"fr-CA"\`, or \`"de-DE"\`. This property provides immediate access to the current locale without requiring subscription setup. Use for one-time locale checks or initial internationalization setup. ```ts T ``` ```ts export interface ReadonlySignalLike { /** * The current value of the locale string in IETF format. For example, `"en-US"`, `"fr-CA"`, or `"de-DE"`. This property provides immediate access to the current locale without requiring subscription setup. Use for one-time locale checks or initial internationalization setup. */ readonly value: T; /** * Subscribes to locale changes and calls the provided function whenever the locale updates. Returns an unsubscribe function to clean up the subscription. Use to automatically update your extension content when merchants change their language settings during POS sessions. */ 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; } ``` ## 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. ## Examples Learn how to handle barcode and QR code scans and access scanner information. ### 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 )} ); }; ``` * #### Subscribe to scanner data events and track scanning history ##### Description Subscribe to real-time scan events and maintain a history of scanned items. This example demonstrates using \`shopify.scanner.scannerData.current.subscribe()\` to capture scan data, source information, and timestamps. Use this pattern for scan logging, bulk scanning workflows, or scan history review. ##### 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 [scanHistory, setScanHistory] = useState([]); useEffect(() => { const unsubscribe = shopify.scanner.scannerData.current.subscribe( (result) => { if (result.data) { setScanData(result.data); setScanSource(result.source || 'unknown'); setScanHistory((prev) => [ { data: result.data, source: result.source, timestamp: new Date().toLocaleTimeString(), }, ...prev, ]); } }, ); return () => { unsubscribe(); }; }, []); return ( {scanData ? ( <> Data: {scanData} Source: {scanSource} ) : ( Waiting for scan... )} {scanHistory.length > 0 && ( {scanHistory.map((scan, index) => ( [{scan.timestamp}] {scan.data} ({scan.source}) ))} )} ); }; ```