# API Documentation {#api-documentation} Complete reference for all Quagga2 methods, callbacks, and events. ## Core Methods {#core-methods} ### `Quagga.init(config, callback)` {#quagga-init} Initializes the library with the given configuration and requests camera access if using live stream mode. **Parameters**: - `config` (Object) - Configuration object. See [Configuration Reference](configuration.md) for complete details. - `callback` (Function) - Called when initialization completes: `callback(err)` - `err` (Error | null) - Error object if initialization failed, `null` on success **Returns**: `void` **Example - Live Camera**: ```javascript Quagga.init({ inputStream: { type: "LiveStream", target: document.querySelector('#scanner') // Or '#scanner' }, decoder: { readers: ["code_128_reader"] } }, function(err) { if (err) { console.error("Initialization failed:", err); return; } console.log("Initialization successful, ready to start"); Quagga.start(); }); ``` **Example - Static Images**: ```javascript Quagga.init({ inputStream: { type: "ImageStream", src: "/path/to/images/*.jpg", target: document.querySelector('#scanner') }, decoder: { readers: ["ean_reader", "code_128_reader"] } }, function(err) { if (err) { console.error(err); return; } Quagga.start(); }); ``` **Error Handling**: The callback receives an `err` parameter if initialization fails. Common causes: - User denies camera permission - No camera device found - Browser doesn't support required APIs - Invalid configuration parameters Always check for errors before calling `start()`: **Target Element**: If no `target` is specified, Quagga looks for an element matching the CSS selector `#interactive.viewport` (for backwards compatibility). ### `Quagga.start()` {#quagga-start} Starts the video stream and begins locating and decoding barcodes. **Parameters**: None **Returns**: `void` **Example**: ```javascript Quagga.init(config, function(err) { if (!err) { Quagga.start(); } }); ``` **Prerequisites**: - `Quagga.init()` must have completed successfully - For live stream: Camera permission must be granted **Note**: Call this in the `init()` callback after checking for errors. ### `Quagga.stop()` {#quagga-stop} Stops the decoder from processing images and disconnects the camera if one was requested. **Parameters**: None **Returns**: `Promise` - Resolves when cleanup is complete **Example**: ```javascript // Stop scanning await Quagga.stop(); console.log("Scanner stopped"); // Or with .then() Quagga.stop().then(() => { console.log("Scanner stopped"); }); ``` **Behavior**: - Stops processing new frames - If using live camera: disconnects and releases camera - Does not remove event listeners (use `offDetected()` / `offProcessed()` for that) - Returns a Promise that resolves when camera release is complete ### `Quagga.pause()` {#quagga-pause} Pauses frame processing without stopping the camera or releasing resources. **Parameters**: None **Returns**: `void` **Example**: ```javascript // Pause scanning temporarily Quagga.pause(); // Later, resume scanning Quagga.start(); ``` **Behavior**: - Stops processing new frames (no more `onProcessed` or `onDetected` callbacks) - **Does not stop the camera** - the video stream continues running - **Does not release resources** - the camera remains connected - Can be resumed by calling `Quagga.start()` **Use Cases**: - Temporarily pause scanning while showing a modal or dialog - Reduce CPU usage when the scanner is not visible - Pause after detecting a barcode to allow user confirmation before resuming **Difference from `stop()`**: | Aspect | `pause()` | `stop()` | |--------|-----------|----------| | Frame processing | Stops | Stops | | Camera stream | **Continues** | Disconnects | | Resources | **Retained** | Released | | Resume with | `start()` | `init()` + `start()` | > **Note**: Since `pause()` keeps the camera running, the user's camera indicator light will remain on. If you want to fully release the camera, use `stop()` instead. ### `Quagga.onDetected(callback)` {#quagga-ondetected} Registers a callback that is triggered when a barcode is successfully located and decoded. **Parameters**: - `callback` (Function) - Handler function: `callback(data)` - `data` (Object) - Result object containing decoded barcode information **Returns**: `void` **Example**: ```javascript Quagga.onDetected(function(result) { const code = result.codeResult.code; const format = result.codeResult.format; console.log(`Detected ${format} barcode: ${code}`); // Process the barcode processBarcode(code); }); ``` **Multiple Handlers**: You can register multiple handlers - all will be called: ```javascript Quagga.onDetected(handler1); Quagga.onDetected(handler2); // Both execute on detection ``` ### `Quagga.onProcessed(callback)` {#quagga-onprocessed} Registers a callback that is called for each processed frame, regardless of detection success. **Parameters**: - `callback` (Function) - Handler function: `callback(data)` - `data` (Object) - Processing result with detailed information **Returns**: `void` **Example**: ```javascript Quagga.onProcessed(function(result) { const drawingCtx = Quagga.canvas.ctx.overlay; const drawingCanvas = Quagga.canvas.dom.overlay; if (result) { // Draw boxes and lines for visualization if (result.boxes) { drawingCtx.clearRect(0, 0, drawingCanvas.width, drawingCanvas.height); result.boxes.forEach(function(box) { Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "blue", lineWidth: 2}); }); } if (result.box) { Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "green", lineWidth: 2}); } if (result.codeResult && result.codeResult.code) { // Successfully decoded console.log("Code detected:", result.codeResult.code); } } }); ``` **Use Cases**: - Custom visualization of detection process - Counting processed frames - Performance monitoring - Drawing custom overlays ### `Quagga.drawScannerArea()` {#quagga-drawscannerarea} Manually draws the scanner area overlay on the overlay canvas using the configured `inputStream.area`. **Parameters**: None (uses the area configuration from `Quagga.init()`) **Returns**: `void` **Behavior**: - Only draws when `locate` is `false` and `inputStream.area` is configured with styling - Uses the actual adjusted scanning area (after patch alignment) to accurately match where barcodes will be detected - Automatically accounts for the area offset and dimensions - Skips drawing if no styling is provided (no `borderColor`, `borderWidth`, or `backgroundColor`) - Requires `canvas.createOverlay: true` so the overlay canvas exists - Drawing occurs automatically every processed frame when conditions are met **Example**: ```javascript // Configure area during init Quagga.init({ inputStream: { area: { top: "30%", right: "10%", bottom: "30%", left: "10%", borderColor: "#0F0", borderWidth: 2, backgroundColor: "rgba(255,0,0,0.15)" } }, locate: false }); // Later, manually redraw if you've cleared the overlay Quagga.drawScannerArea(); ``` ### `Quagga.offDetected(handler)` {#quagga-offdetected} Removes a previously registered `onDetected` handler. **Parameters**: - `handler` (Function, optional) - Specific handler to remove. If omitted, **all** handlers are removed. **Returns**: `void` **Example**: ```javascript function myHandler(result) { console.log(result.codeResult.code); } Quagga.onDetected(myHandler); // Later: remove specific handler Quagga.offDetected(myHandler); // Or remove all handlers Quagga.offDetected(); ``` ### `Quagga.offProcessed(handler)` {#quagga-offprocessed} Removes a previously registered `onProcessed` handler. **Parameters**: - `handler` (Function, optional) - Specific handler to remove. If omitted, **all** handlers are removed. **Returns**: `void` **Example**: ```javascript function processHandler(result) { // Process frame } Quagga.onProcessed(processHandler); // Remove specific handler Quagga.offProcessed(processHandler); // Or remove all handlers Quagga.offProcessed(); ``` ### `Quagga.decodeSingle(config, callback)` {#quagga-decodesingle} Decodes a single image without using `getUserMedia`. Useful for processing uploaded images or static images. **Parameters**: - `config` (Object) - Configuration object (subset of full config) - `callback` (Function) - Result handler: `callback(result)` - `result` (Object) - Same format as `onDetected` callback **Returns**: `void` **Important - Default Scaling**: `decodeSingle` has a built-in default of `inputStream.size: 800`. This means images are **automatically scaled to 800px** on their longest side (both larger images scaled down AND smaller images scaled up). The result's `box`, `boxes`, and `line` coordinates are returned in this scaled coordinate space, not the original image dimensions. To use the original image dimensions without scaling, set `inputStream.size` to `0`. **Example**: ```javascript Quagga.decodeSingle({ src: '/images/barcode.jpg', // Or data URL decoder: { readers: ["code_128_reader", "ean_reader"] }, locate: true // Try to locate barcode in image // Note: inputStream.size defaults to 800; images are scaled to 800px (up or down) }, function(result) { if (result && result.codeResult) { console.log("Detected:", result.codeResult.code); console.log("Format:", result.codeResult.format); } else { console.log("No barcode detected"); } }); ``` **Using Data URLs**: ```javascript // From file input document.querySelector('#file-input').addEventListener('change', function(e) { const file = e.target.files[0]; const reader = new FileReader(); reader.onload = function(event) { Quagga.decodeSingle({ src: event.target.result, // Data URL decoder: { readers: ["code_128_reader"] } // Default size: 800 applies - image scaled if larger }, function(result) { if (result && result.codeResult) { alert("Barcode: " + result.codeResult.code); } }); }; reader.readAsDataURL(file); }); ``` **Node.js Usage**: ```javascript const Quagga = require('@ericblade/quagga2').default; Quagga.decodeSingle({ src: "./barcode.jpg", inputStream: { size: 800 // This is actually the default; shown explicitly here }, decoder: { readers: ["code_128_reader"] } }, function(result) { if (result && result.codeResult) { console.log("Code:", result.codeResult.code); } }); ``` ## Result Object {#result-object} The result object passed to `onDetected`, `onProcessed`, and `decodeSingle` callbacks contains detailed information about the detection and decoding process. ### Complete Result Structure {#result-structure} ```javascript { codeResult: { code: "FANAVF1461710", // The decoded barcode string format: "code_128", // Barcode format start: 355, // Start position end: 26, // End position codeset: 100, // Code 128 specific startInfo: { error: 1.0, code: 104, start: 21, end: 41 }, decodedCodes: [ // Individual code segments { code: 104, start: 21, end: 41 }, // ... more segments { error: 0.88, code: 106, start: 328, end: 350 } ], endInfo: { error: 0.88, code: 106, start: 328, end: 350 }, direction: -1 // Scan direction }, line: [ // Scan line coordinates { x: 25.97, y: 360.56 }, { x: 401.92, y: 70.88 } ], angle: -0.657, // Rotation angle in radians pattern: [0, 0, 1, 1, ...], // Bar pattern (0=space, 1=bar) box: [ // Primary bounding box (4 corners) [77.41, 410.93], // Top-left [0.05, 310.54], // Top-right [360.16, 33.06], // Bottom-right [437.51, 133.45] // Bottom-left ], boxes: [ // All detected boxes [/* box 1 */], [/* box 2 */], // ... ] } ``` ### Result Properties {#result-properties} | Property | Type | Description | |----------|------|-------------| | `codeResult` | Object | Decoded barcode information (may be `undefined` if detection failed) | | `codeResult.code` | String | The decoded barcode value | | `codeResult.format` | String | Barcode format (e.g., "code_128", "ean_13") | | `codeResult.start` | Number | Start position in pattern | | `codeResult.end` | Number | End position in pattern | | `codeResult.direction` | Number | Scan direction (1 or -1) | | `codeResult.supplement` | Object | (Optional) Supplement barcode data for EAN-13/UPC-A with EAN-2 or EAN-5 extensions | | `codeResult.supplement.code` | String | The decoded supplement value (2 or 5 digits) | | `codeResult.supplement.format` | String | Supplement format: "ean_2" or "ean_5" | | `line` | Array | Two points defining the scan line | | `angle` | Number | Barcode rotation angle (radians) | | `pattern` | Array | Binary pattern (0=space, 1=bar) | | `box` | Array | Bounding box coordinates (4 corner points) | | `boxes` | Array | All candidate boxes found during localization. When `locate` is `false`, this contains a single box representing the actual adjusted scanning area (after patch alignment) | > **Note: `boxes` with `locate: false`** > > When `locate` is `false` and an `inputStream.area` is configured, `result.boxes` contains a single box representing the actual scanning area dimensions. This box reflects the adjusted dimensions after patch alignment (which can differ slightly from the percentage-based area due to rounding to patch size multiples). Use these coordinates if you need to know the exact scanning rectangle: > > ```javascript > Quagga.onProcessed(function(result) { > if (result.boxes && result.boxes.length > 0) { > // When locate=false, boxes[0] is the actual scanning area > const scanArea = result.boxes[0]; > console.log("Scanning area corners:", scanArea); > } > }); > ``` > **Important: Coordinate System** > > The `box`, `boxes`, and `line` coordinates are returned in **processed canvas coordinates**, not original image/video coordinates. If you're using `inputStream.size` to scale the processing resolution (e.g., for performance), you'll need to scale these coordinates to match your original video/image dimensions. > > ```javascript > // Scale coordinates to original video size > const scaleX = video.videoWidth / Quagga.canvas.dom.image.width; > const scaleY = video.videoHeight / Quagga.canvas.dom.image.height; > const scaledBox = result.box.map(p => [p[0] * scaleX, p[1] * scaleY]); > ``` > > See [Working with Box Coordinates](../how-to-guides/working-with-coordinates.md) for complete examples. ### Checking for Successful Detection {#checking-detection} ```javascript Quagga.onDetected(function(result) { // Always check if codeResult exists if (result && result.codeResult && result.codeResult.code) { console.log("Detected:", result.codeResult.code); } }); ``` ### Using Multiple Barcode Detection {#multiple-barcode-detection} When `decoder.multiple` is `true`, results are returned as an array: ```javascript Quagga.init({ decoder: { readers: ["code_128_reader"], multiple: true } }); Quagga.onDetected(function(result) { // result is an array of result objects result.forEach(function(item) { if (item.codeResult) { console.log("Code:", item.codeResult.code); console.log("Box:", item.box); } }); }); ``` ## Canvas Access {#canvas-access} Quagga automatically creates and manages two canvas elements for visualization. These are positioned over the video/image stream and sized to match the processing dimensions. ### Canvas Structure {#canvas-structure} ```javascript Quagga.canvas = { dom: { image: HTMLCanvasElement, // Canvas for processed image data overlay: HTMLCanvasElement | null // Transparent canvas for drawing overlays }, ctx: { image: CanvasRenderingContext2D, // Context for image canvas overlay: CanvasRenderingContext2D | null // Context for overlay canvas } }; ``` > **Note**: The overlay canvas can be `null` if `canvas.createOverlay` is set to `false` in the configuration. See [Canvas Configuration](configuration.md#canvas-configuration) for details. ### Overlay Canvas {#overlay-canvas} The **overlay canvas** (`Quagga.canvas.dom.overlay`) is a transparent canvas element positioned over the video stream. It's automatically created when Quagga initializes (unless `canvas.createOverlay` is `false`) and is designed for drawing bounding boxes, scan lines, and other visual feedback. **Key characteristics:** - Has CSS class `drawingBuffer` - Sized to match the processed image dimensions (`inputStream.size`) - Positioned absolutely over the video/image element - Automatically appended to the viewport container - Coordinates match the processed image space (no scaling needed) - Can be disabled via `canvas.createOverlay: false` for performance **Accessing the overlay:** ```javascript const overlay = Quagga.canvas.dom.overlay; const overlayCtx = Quagga.canvas.ctx.overlay; // Always check if overlay exists before using if (overlayCtx && overlay) { // Clear overlay overlayCtx.clearRect(0, 0, overlay.width, overlay.height); // Draw custom shapes overlayCtx.strokeStyle = "red"; overlayCtx.lineWidth = 3; overlayCtx.strokeRect(10, 10, 100, 100); } ``` ### Image Canvas {#image-canvas} The **image canvas** (`Quagga.canvas.dom.image`) contains the processed grayscale image data used for barcode detection. This is primarily for internal use and debugging. **Key characteristics:** - Has CSS class `imgBuffer` - Contains the grayscale/processed image data - Useful for debugging locator issues ### When to Use Each Canvas {#when-to-use-canvas} | Use Case | Canvas to Use | |----------|---------------| | Drawing bounding boxes | `overlay` | | Highlighting detected barcodes | `overlay` | | Custom scan line visualization | `overlay` | | Debugging image processing | `image` | | Checking processed resolution | Either (they have same dimensions) | ### Important: Coordinate System {#canvas-coordinate-system} When drawing on the overlay canvas, use `result.box` and `result.boxes` coordinates directly - **no scaling is needed**. These coordinates are already in the overlay canvas's coordinate space. ```javascript Quagga.onProcessed(function(result) { const ctx = Quagga.canvas.ctx.overlay; const canvas = Quagga.canvas.dom.overlay; // Clear previous drawings ctx.clearRect(0, 0, canvas.width, canvas.height); // Draw box directly - coordinates already match the overlay canvas if (result && result.box) { Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, ctx, { color: "green", lineWidth: 2 }); } }); ``` > **Note**: Scaling is only needed when drawing on a **different** canvas (like a custom overlay on the original video element). See [Working with Box Coordinates](../how-to-guides/working-with-coordinates.md) for details. ### CSS Styling {#canvas-css-styling} The overlay canvas can be styled with CSS for positioning: ```css /* Default positioning (handled automatically by Quagga) */ canvas.drawingBuffer { position: absolute; top: 0; left: 0; } /* Ensure proper stacking */ #scanner-container { position: relative; } ``` ## ImageDebug Helper {#imagedebug-helper} Quagga provides a helper for drawing debug visualizations: ```javascript // Draw a path (array of points) Quagga.ImageDebug.drawPath(points, offset, ctx, options); // Example Quagga.ImageDebug.drawPath( result.box, { x: 0, y: 1 }, overlayCtx, { color: "green", lineWidth: 2 } ); ``` ## Complete Example {#complete-example} ```javascript // Initialize Quagga.init({ inputStream: { type: "LiveStream", target: document.querySelector('#scanner'), constraints: { width: 640, height: 480, facingMode: "environment" } }, decoder: { readers: ["code_128_reader", "ean_reader"] } }, function(err) { if (err) { console.error(err); return; } // Start scanning Quagga.start(); }); // Handle detections Quagga.onDetected(function(result) { console.log("Barcode detected:", result.codeResult.code); // Stop after first detection Quagga.stop(); // Cleanup Quagga.offDetected(); Quagga.offProcessed(); }); // Visualize processing Quagga.onProcessed(function(result) { const ctx = Quagga.canvas.ctx.overlay; const canvas = Quagga.canvas.dom.overlay; ctx.clearRect(0, 0, canvas.width, canvas.height); if (result && result.box) { Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, ctx, { color: "green", lineWidth: 2 }); } }); // Stop button document.querySelector('#stop').addEventListener('click', function() { Quagga.stop(); Quagga.offDetected(); Quagga.offProcessed(); }); ``` ## Related {#related} - [Configuration Reference](configuration.md) - Complete configuration options - [CameraAccess API](camera-access.md) - Camera control methods - [Supported Barcode Types](readers.md) - Available barcode readers - [Getting Started](../getting-started.md) - Basic usage examples --- [← Back to Reference](index.md)