diff --git a/packages/qr-code-scanner/README.md b/packages/qr-code-scanner/README.md
index dc633f3e60b724c91406ab4da1e077fb4f5bc34f..6508dcc4273c35f2657210346d5f57e5153332c9 100644
--- a/packages/qr-code-scanner/README.md
+++ b/packages/qr-code-scanner/README.md
@@ -46,10 +46,6 @@ after loaded. This attribute is also used to stop the QR code reader or if you d
 - `'code-detected'`: Outgoing Event which is fired if a QR code is detected. The data of the detected QR code is in `event.detail`.
 - `'scan-started`: Fired after the first image is drawn. Can be used to scrolling or other layout dependent tasks.
 
-## Assets
-
-- `qr-scanner/qr-scanner-worker.*` -> `dist/local/@dbp-toolkit/qr-code-scanner/`
-
 ## Local development
 
 ```bash
@@ -72,6 +68,13 @@ yarn run build
 
 Jump to <http://localhost:8002> and you should get a demo page.
 
+## Content Security Policy
+
+The QR code detection worker is loaded via `blob:`, so your CSP needs to allow
+`worker-src blob:`. Since Safari does not support this you also have to set
+`child-src blob:`. Since `child-src` also affects other things make sure this
+doesn't break things.
+
 ## Camera for local development
 
 You can use your desktop as a camera, to test the qr code reader
diff --git a/packages/qr-code-scanner/package.json b/packages/qr-code-scanner/package.json
index c3d0dee05821b45951a5780dc650af161aeaf348..66b51b1cf365859d2a684872aede20ef58c9d9b5 100644
--- a/packages/qr-code-scanner/package.json
+++ b/packages/qr-code-scanner/package.json
@@ -41,7 +41,7 @@
         "@open-wc/scoped-elements": "^2.1.0",
         "async-mutex": "^0.3.0",
         "lit": "^2.0.0",
-        "qr-scanner": "^1.2.0 <=1.3.0"
+        "qr-scanner": "^1.4.1"
     },
     "scripts": {
         "clean": "rm dist/*",
diff --git a/packages/qr-code-scanner/rollup.config.js b/packages/qr-code-scanner/rollup.config.js
index ba20556ce08b056de8dfc2fca691e776f843a912..c32a0fcc44c94d19d5078146c492b56295fbdd30 100644
--- a/packages/qr-code-scanner/rollup.config.js
+++ b/packages/qr-code-scanner/rollup.config.js
@@ -67,10 +67,6 @@ export default async () => {
                         src: await getPackagePath('@dbp-toolkit/common', 'assets/icons/*.svg'),
                         dest: 'dist/' + (await getDistPath('@dbp-toolkit/common', 'icons')),
                     },
-                    {
-                        src: await getPackagePath('qr-scanner', 'qr-scanner-worker.*'),
-                        dest: 'dist/' + (await getDistPath(pkg.name)),
-                    },
                 ],
             }),
             process.env.ROLLUP_WATCH === 'true'
diff --git a/packages/qr-code-scanner/src/qr-code-scanner.js b/packages/qr-code-scanner/src/qr-code-scanner.js
index 31b82e2f4efb8998c0c92aec4f56efa1140bf21e..be3080b54551bd326f50df3c0096cf5f97fbf3a9 100644
--- a/packages/qr-code-scanner/src/qr-code-scanner.js
+++ b/packages/qr-code-scanner/src/qr-code-scanner.js
@@ -5,9 +5,7 @@ import * as commonStyles from '@dbp-toolkit/common/styles';
 import {ScopedElementsMixin} from '@open-wc/scoped-elements';
 import {Icon, MiniSpinner} from '@dbp-toolkit/common';
 import {classMap} from 'lit/directives/class-map.js';
-import * as commonUtils from '@dbp-toolkit/common/utils';
 import {Mutex} from 'async-mutex';
-import {name as pkgName} from './../package.json';
 import {getIconSVGURL} from '@dbp-toolkit/common';
 
 /**
@@ -128,22 +126,17 @@ class QRScanner {
     async scan(canvas, x, y, width, height) {
         if (this._scanner === null) {
             this._scanner = (await import('qr-scanner')).default;
-            this._scanner.WORKER_PATH = commonUtils.getAssetURL(
-                pkgName,
-                'qr-scanner-worker.min.js'
-            );
         }
         if (this._engine === null) {
-            this._engine = await this._scanner.createQrEngine(this._scanner.WORKER_PATH);
+            this._engine = await this._scanner.createQrEngine();
         }
         try {
             return {
-                data: await this._scanner.scanImage(
-                    canvas,
-                    {x: x, y: y, width: width, height: height},
-                    this._engine,
-                    this._canvas
-                ),
+                data: await this._scanner.scanImage(canvas, {
+                    scanRegion: {x: x, y: y, width: width, height: height},
+                    qrEngine: this._engine,
+                    canvas: this._canvas,
+                }),
             };
         } catch (e) {
             return null;
@@ -315,17 +308,18 @@ export class QrCodeScanner extends ScopedElementsMixin(DBPLitElement) {
                             lastCode = code;
 
                             if (code) {
-                                if (lastSentData !== code.data) {
-                                    this._outputData = code.data;
+                                let currentData = code.data.data;
+                                if (lastSentData !== currentData) {
+                                    this._outputData = currentData;
                                     this.dispatchEvent(
                                         new CustomEvent('code-detected', {
                                             bubbles: true,
                                             composed: true,
-                                            detail: {code: code.data},
+                                            detail: {code: currentData},
                                         })
                                     );
                                 }
-                                lastSentData = code.data;
+                                lastSentData = currentData;
                             } else {
                                 this._outputData = null;
                                 lastSentData = null;
@@ -333,7 +327,7 @@ export class QrCodeScanner extends ScopedElementsMixin(DBPLitElement) {
                         });
                 }
 
-                let matched = lastCode ? lastCode.data.match(this.matchRegex) !== null : false;
+                let matched = lastCode ? lastCode.data.data.match(this.matchRegex) !== null : false;
 
                 //draw mask
                 canvas.beginPath();
diff --git a/yarn.lock b/yarn.lock
index 9ad70e1f51ae0a786bf7d105037e2138921fdc75..585a0e9a5a686fe286e21e6b7807223425d0bf6a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2064,6 +2064,11 @@
   resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
   integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
 
+"@types/offscreencanvas@^2019.6.4":
+  version "2019.6.4"
+  resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.6.4.tgz#64f6d120b53925028299c744fcdd32d2cd525963"
+  integrity sha512-u8SAgdZ8ROtkTF+mfZGOscl0or6BSj9A4g37e6nvxDc+YB/oDut0wHkK2PBBiC2bNR8TS0CPV+1gAk4fNisr1Q==
+
 "@types/parse-json@^4.0.0":
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
@@ -7041,10 +7046,12 @@ qjobs@^1.2.0:
   resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
   integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==
 
-"qr-scanner@^1.2.0 <=1.3.0":
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/qr-scanner/-/qr-scanner-1.3.0.tgz#5a7cc7ae8edefc3ad0053a5473f591fb113f91ff"
-  integrity sha512-xNXlZaKOW0nihHaV7KPrMYJHNp1YX9z+NTqFrbNoibGIzQpPLeIocP9187lxihU/EbgplMm7sQ4hI9jG9+zYHg==
+qr-scanner@^1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/qr-scanner/-/qr-scanner-1.4.1.tgz#31a1bf7f9927f0eb1e3c0909fe66fec97a3b3701"
+  integrity sha512-xiR90NONHTfTwaFgW/ihlqjGMIZg6ExHDOvGQRba1TvV+WVw7GoDArIOt21e+RO+9WiO4AJJq+mwc5f4BnGH3w==
+  dependencies:
+    "@types/offscreencanvas" "^2019.6.4"
 
 qs@6.10.3, qs@^6.9.4:
   version "6.10.3"