vue-qrcode-reader: QR scanning as three drop-in Vue components
A set of Vue.js components for detecting and decoding QR codes.
At a glance
- What is it?
- A Vue 3 component set that reads barcodes from a camera stream, a drag-and-drop zone or a file input, delegating the actual decoding to a WebAssembly build fetched at runtime.
- Who is it for?
- vue-qrcode-reader is a good fit when you need camera scanning or file-based decoding inside a Vue 3 app and do not want to write the WebAssembly plumbing yourself, and the three components cover the three realistic input paths without a plugin architecture or a store to configure. The decision that matters is the CDN fetch: the decoder is retrieved at runtime, which breaks offline use and strict Content Security Policy setups unless you work around it.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 86 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three components for the three ways a code arrives
The library's whole surface is three Vue components, and the README's framing is that they cover how a barcode actually reaches your application. `QrcodeStream` continuously scans frames from a camera stream. `QrcodeDropZone` is an empty region where a user can drag and drop images to be decoded. `QrcodeCapture` is a classic file upload field that scans every file selected at once.
The usage is one tag plus one handler:
<qrcode-stream @detect="onDetect"></qrcode-stream>methods: {
onDetect (detectedCodes) {
// ...
}
}What the README emphasises just as much is what these components are not. They are responsive, and beyond close to zero styling they are yours to fit into a layout. There is no theme, no built-in camera permission flow with its own UI, and no opinion about how your app should look once a code is found. For a component library that is a deliberate choice, and it is the reason the demos can be short.
The repository description says the components handle QR codes and various other barcode formats, linking to the upstream Barcode Detector polyfill for the format list. That upstream project is where the capability actually lives, and understanding it is more useful than understanding the Vue wrapper.
Installing through npm or through a script tag
With a package manager the install is one command:
npm install vue-qrcode-readerAfter that you have two registration options. Import the components individually, which keeps them tree-shakeable:
import { QrcodeStream, QrcodeDropZone, QrcodeCapture } from 'vue-qrcode-reader'
const MyComponent = {
//
components: {
QrcodeStream,
QrcodeDropZone,
QrcodeCapture
}
// ...
}Or register all of them globally with a plugin install, which is the option to pick if you use the components across many files:
import Vue from 'vue'
import VueQrcodeReader from 'vue-qrcode-reader'
Vue.use(VueQrcodeReader)There is also a no-npm path for a plain HTML page, using the UMD build from unpkg. Order matters, because Vue has to be on the page first:
<script src="./vue.js"></script>
<script src="./vue-qrcode-reader.umd.js"></script>Components are then registered automatically and referenced in kebab-case, so `QrcodeStream` becomes `qrcode-stream` in a template. The package.json confirms the layout, with `main` and `module` pointing at an ES build, `unpkg` at the UMD build, and an exports map that serves import, require and types conditions separately.
The decoder is a Wasm file fetched from a CDN at runtime
This is the detail that decides whether the library fits your deployment, and it is filed under Troubleshooting rather than under installation. The README has an entry for a Failed to fetch error on some Wasm file, and explains that the file implements the QR code detector, that it is not convenient to bundle with the package, and that by default it is fetched at runtime from a CDN.
The stated consequences are offline applications and networks with a strict Content Security Policy. If your app has to work without a network, or your policy forbids connecting to a CDN, the default configuration will fail at exactly the moment your user points a camera at something. The README points at issue 354 for a workaround, which tells you the situation is known and has more than one answer.
The runtime dependencies in package.json are small and telling: `barcode-detector` pinned at 3.2.0 and `webrtc-adapter` at 8.2.3. The second one is the adapter that smooths over browser differences in the WebRTC implementation the camera stream depends on, and its presence is a fair signal of how much browser variance this library is insulating you from.
Troubleshooting entries that tell you what actually breaks
The Troubleshooting section is the most useful part of the README, because each entry describes a failure mode rather than a feature.
For a missing camera, the advice is diagnostic: check the demo page first, especially the Handle Errors demo since it renders error messages. If the demo works but your project does not, listen for the `error` event to investigate. If the demo does not work either, review browser support, since the device may simply not be supported. That three-step split tells you whether to debug your build or your hardware.
For 1D barcodes, the README gives the exact reason: the default value of the `formats` prop is `qr_code`, which reflects the setting from before that prop existed. You have to add the other formats to the prop, and the README links a demo showing the full set. This is a compatibility default preserved on purpose, so a QR-only app keeps working, but it surprises anyone who assumes the component detects everything named in the project description.
For detection quality, the advice is to make sure there is a white border around the code, then to test in the upstream packages in order: `barcode-detector`, then `zxing-wasm`, then `zxing-cpp`, and to look for file detection issues in the highest-level repository where the problem first appears. That debugging order is genuinely useful, because it lets you stop as soon as the problem stops reproducing.
HTTPS, localhost and testing camera code on a phone
Camera access in a browser requires a secure context, which is the second practical blocker after the CDN fetch. The README has a dedicated entry for developers running a dev server on localhost who want to test on a mobile device without HTTPS.
The first suggestion is narrow and free: if your setup is Desktop Chrome plus Android Chrome, use Chrome's remote debugging, which lets the Android device reach your local server as localhost. Otherwise, use a reverse proxy such as ngrok or serveo to expose the local server temporarily over HTTPS. The README also lists a set of serverless and static hosting services that have HTTPS on by default, and names GitHub Pages, GitLab Pages, Firebase, Netlify, Heroku and ZEIT Now as places you could deploy a web app for free.
That is a longer list than most projects give, and it reflects where the audience actually is: people building a demo or a prototype who need the camera to work on a phone today. For an application with a real deployment pipeline, the answer is simpler, and it is that your production origin must be HTTPS anyway.
One more limitation worth naming: the README says `torch` support, meaning the camera flashlight, is inconsistent across devices. If your use case is a dark warehouse, that inconsistency is a product problem rather than a library problem, and no amount of component configuration changes it.
Version policy, Vue 2 and the project's own conventions
The versions tell a short story. v5.7.3 was published on 2025-07-16 and fixed a case where the BarcodeDetector polyfill was not always used, closing two issues. v5.7.2 from 2025-04-22 corrected the type of the camera constraints passed by `QrcodeStream`. v5.7.1 from 2025-02-11 fixed PDF417 codes on desktop Mac. Three patch releases, each a specific browser or type problem, no feature work in the recent history. The last push to master was on 2026-07-12.
That shape suits a library whose hard part is delegated upstream. When zxing-wasm or the Barcode Detector polyfill changes, the fix here is usually a version bump and a typing correction, which is what the release notes show.
Vue 2 is explicitly out. The README states that support is dropped and that you can downgrade to vue-qrcode-reader v3.x or lower, which is a clean answer for a team that has not migrated yet but not a good place to be long term. package.json requires Node 18 or newer and is an ES module package, and the build runs on Vite with VitePress for the documentation site under docs/.
The conventions are modern and worth noting if you plan to contribute: prettier for formatting with a .prettierrc.json, eslint via .eslintrc.cjs, a .browserslistrc, semantic-release driven by .releaserc.yml, which is why the commit messages and changelog look the way they do, and a CLAUDE.md at the root alongside flake.nix for a reproducible dev shell.
Editorial conclusion
vue-qrcode-reader is a good fit when you need camera scanning or file-based decoding inside a Vue 3 app and do not want to write the WebAssembly plumbing yourself, and the three components cover the three realistic input paths without a plugin architecture or a store to configure. The decision that matters is the CDN fetch: the decoder is retrieved at runtime, which breaks offline use and strict Content Security Policy setups unless you work around it. Start with QrcodeStream and the error event, check whether your deployment can reach the CDN, and add barcode formats to the formats prop before concluding that 1D codes do not work.
Frequently asked questions
How do I scan a 1D barcode with vue-qrcode-reader?
Add the format to the formats prop. The README explains that the default value is qr_code, which reflects the setting from before the prop existed, so other barcode types are not detected until you list them. It links a demo showing the full set of supported formats.
Why does the camera not work on my localhost dev server?
Camera access needs a secure context. The README suggests Chrome remote debugging when your setup is Desktop Chrome plus Android Chrome, so the phone can reach your local server as localhost, and otherwise a reverse proxy such as ngrok or serveo to expose it over HTTPS temporarily. It also suggests listening for the error event, which the Handle Errors demo renders.
Can vue-qrcode-reader work without an internet connection?
Not with the default configuration. The decoder is a Wasm file that is inconvenient to bundle with the package, so it is fetched at runtime from a CDN, which the README says is a problem for offline applications and for networks with a strict Content Security Policy. Issue 354 is linked as the place to find a workaround.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gruhn-vue-qrcode-reader)