Speed up MatrixScan Batch integration with Agent Skills
Install the Scandit plugin and use the /matrixscan-batch-web skill so that your AI coding agent can integrate, debug, and customize MatrixScan Batch on Web 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/skillsPrefer to set it up yourself? Manual installation steps for each agent →
Get Started
In this guide you will learn step-by-step how to add MatrixScan to your application.
The general steps are:
- Create the Data Capture Context initialized with your license key.
- Configure the Barcode Batch Mode with the symbologies you want to read.
- Use the Built-in Camera as the frame source.
- Use a Capture View to Visualize the Scan Process by adding a basic overlay for visual feedback.
- Get Barcode Batch Feedback by registering an overlay listener.
- Disable Barcode Batch when it is no longer needed.
Prerequisites
Before starting with adding a capture mode, make sure that you have a valid Scandit Data Capture SDK license key and that you added the necessary dependencies. If you have not done that yet, check out this guide.
You can retrieve your Scandit Data Capture SDK license key by signing in to your Scandit account.
Improve runtime performance by enabling browser multithreading
You can achieve better performance by enabling multithreading in any browser that supports it. Check the Requirements Page to know the minimum versions that can take advantage of multithreading.
To enable multithreading you must set your site to be crossOriginIsolated. This will enable the SDK to use multithreading and significantly boost performance. If the environment supports it the SDK will automatically use multithreading. You can programmatically check for multithreading support using BrowserHelper.checkMultithreadingSupport().
Multithreading is particularly critical for MatrixScan as it significantly improves frame processing speed and tracking accuracy. Be sure to configure it correctly following this tutorial. You can also check this guide to enable cross-origin isolation and safely reviving shared memory.
Verify multithreading is enabled
You can verify that multithreading is working correctly by checking the cross-origin isolation status:
import { BrowserHelper } from "@scandit/web-datacapture-core";
// Whether or not the browser supports SharedArrayBuffer, the page is served to be crossOriginIsolated and has support for nested web workers.
const supportsMultithreading = await BrowserHelper.checkMultithreadingSupport();
if (supportsMultithreading) {
console.log("Multithreading is enabled and working!");
} else {
console.warn("Multithreading is not available. Check your cross-origin headers.");
}
Configure cross-origin headers
To enable cross-origin isolation, you need to set specific HTTP headers on your HTML page (not on the SDK files). The headers you need depend on whether you're self-hosting or using a CDN:
If you're loading the SDK from a CDN (jsDelivr, UNPKG, etc.), you should use Cross-Origin-Embedder-Policy: credentialless instead of require-corp to avoid blocking cross-origin resources. Alternatively, we strongly recommend self-hosting the SDK files when using multithreading for better reliability and to avoid potential CDN CORS/CORP issues.
Choose the appropriate header configuration:
- If self-hosting the SDK: Use
Cross-Origin-Embedder-Policy: require-corp - If using a CDN: Use
Cross-Origin-Embedder-Policy: credentialless(requires modern browsers)
Below are examples for common server setups:
- Nginx
- Apache
- Express.js
- Vite
- Netlify
- Vercel
- ASP.NET Core
Add these headers to your Nginx configuration file (usually in /etc/nginx/sites-available/ or within a server block):
For self-hosted SDK:
server {
# ... other configuration ...
location / {
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
# ... other directives ...
}
}
For CDN-hosted SDK:
server {
# ... other configuration ...
location / {
add_header Cross-Origin-Embedder-Policy "credentialless" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
# ... other directives ...
}
}
After making changes, reload Nginx:
sudo nginx -t && sudo nginx -s reload
Add these headers to your .htaccess file or Apache configuration:
For self-hosted SDK:
<IfModule mod_headers.c>
Header set Cross-Origin-Embedder-Policy "require-corp"
Header set Cross-Origin-Opener-Policy "same-origin"
</IfModule>
For CDN-hosted SDK:
<IfModule mod_headers.c>
Header set Cross-Origin-Embedder-Policy "credentialless"
Header set Cross-Origin-Opener-Policy "same-origin"
</IfModule>
Make sure mod_headers is enabled:
sudo a2enmod headers
sudo systemctl restart apache2
For Express.js applications, add the headers using middleware:
For self-hosted SDK:
const express = require("express");
const app = express();
// Add cross-origin isolation headers
app.use((req, res, next) => {
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
next();
});
// ... rest of your app configuration ...
app.listen(3000);
For CDN-hosted SDK:
const express = require("express");
const app = express();
// Add cross-origin isolation headers
app.use((req, res, next) => {
res.setHeader("Cross-Origin-Embedder-Policy", "credentialless");
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
next();
});
// ... rest of your app configuration ...
app.listen(3000);
For Vite projects, create a custom plugin in your vite.config.ts:
For self-hosted SDK:
import { defineConfig, type PluginOption } from 'vite';
function crossOriginIsolation(): PluginOption {
return {
name: 'vite-plugin-cross-origin-isolation',
configureServer: (server) => {
server.middlewares.use((_req, res, next) => {
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
next();
});
},
configurePreviewServer: (server) => {
server.middlewares.use((_req, res, next) => {
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
next();
});
},
};
}
export default defineConfig({
plugins: [crossOriginIsolation()],
// ... other config
});
For CDN-hosted SDK:
import { defineConfig, type PluginOption } from 'vite';
function crossOriginIsolation(): PluginOption {
return {
name: 'vite-plugin-cross-origin-isolation',
configureServer: (server) => {
server.middlewares.use((_req, res, next) => {
res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless');
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
next();
});
},
configurePreviewServer: (server) => {
server.middlewares.use((_req, res, next) => {
res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless');
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
next();
});
},
};
}
export default defineConfig({
plugins: [crossOriginIsolation()],
// ... other config
});
This plugin configures headers for both vite dev (development) and vite preview (production preview) modes.
Create a _headers file in your publish directory (usually public/ or dist/):
For self-hosted SDK:
/*
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
For CDN-hosted SDK:
/*
Cross-Origin-Embedder-Policy: credentialless
Cross-Origin-Opener-Policy: same-origin
Add the headers to your vercel.json configuration file:
For self-hosted SDK:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Cross-Origin-Embedder-Policy",
"value": "require-corp"
},
{
"key": "Cross-Origin-Opener-Policy",
"value": "same-origin"
}
]
}
]
}
For CDN-hosted SDK:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Cross-Origin-Embedder-Policy",
"value": "credentialless"
},
{
"key": "Cross-Origin-Opener-Policy",
"value": "same-origin"
}
]
}
]
}
Add the headers in your Program.cs or Startup.cs:
For self-hosted SDK:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Cross-Origin-Embedder-Policy", "require-corp");
context.Response.Headers.Add("Cross-Origin-Opener-Policy", "same-origin");
await next();
});
For CDN-hosted SDK:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Cross-Origin-Embedder-Policy", "credentialless");
context.Response.Headers.Add("Cross-Origin-Opener-Policy", "same-origin");
await next();
});
Or use middleware in Program.cs (change the COEP value as needed):
app.UseMiddleware<CrossOriginIsolationMiddleware>();
// Middleware class:
public class CrossOriginIsolationMiddleware
{
private readonly RequestDelegate _next;
private readonly string _coepValue; // "require-corp" or "credentialless"
public CrossOriginIsolationMiddleware(RequestDelegate next, string coepValue = "require-corp")
{
_next = next;
_coepValue = coepValue;
}
public async Task InvokeAsync(HttpContext context)
{
context.Response.Headers.Add("Cross-Origin-Embedder-Policy", _coepValue);
context.Response.Headers.Add("Cross-Origin-Opener-Policy", "same-origin");
await _next(context);
}
}
Important notes:
- After configuring the headers, clear your browser cache and restart your development server to ensure the new headers take effect.
Cross-Origin-Embedder-Policy: credentiallessrequires Chrome 96+, Edge 96+, or other Chromium-based browsers. For older browser support, self-hosting withrequire-corpis more reliable.- Verify your configuration using
BrowserHelper.checkMultithreadingSupport()- it should returntrueif multithreading is properly enabled (see Verify multithreading is enabled above). - If you see CORS errors after enabling these headers, verify that all external resources (fonts, analytics, etc.) either use CORS or are self-hosted.
Internal dependencies
Some of the Scandit Data Capture SDK modules depend on others to work:
| Module | Dependencies | Optional Dependencies |
|---|---|---|
| ScanditCaptureCore | None | None |
| ScanditBarcodeCapture | ScanditCaptureCore | None |
| ScanditParser | None | None |
| ScanditLabelCapture | ScanditCaptureCore ScanditBarcodeCapture | ScanditLabelCaptureText ScanditPriceLabel |
| ScanditIdCapture | ScanditCaptureCore | ScanditIdCaptureBackend ScanditIdEuropeDrivingLicense ScanditIdAamvaBarcodeVerification ScanditIdVoidedDetection |
When using ID Capture or Label Capture, consult the respective module's getting started guides to identify the optional dependencies required for your use case. The modules you need to include will vary based on the features you intend to use.
Please be aware that your license may only cover a subset of Barcode and/or ID Capture features. If you require additional features, contact us.
Create the Data Capture Context
The first step to add capture capabilities to your application is to create a new data capture context.
import { DataCaptureContext } from "@scandit/web-datacapture-core";
import { barcodeCaptureLoader } from "@scandit/web-datacapture-barcode";
const context = await DataCaptureContext.forLicenseKey('-- ENTER YOUR SCANDIT LICENSE KEY HERE --', {
libraryLocation: new URL('library/engine/', document.baseURI).toString(),
moduleLoaders: [barcodeCaptureLoader()],
});