jsQR

A pure JavaScript library that locates, extracts, and decodes QR codes from raw image data, with no native dependencies.

Library
npm
v1.4.0
4,026stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
46/100Fair
Development Activity16
Maintenance0
Community68
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
66/100Good
Architecture70
Code Quality62
Innovation55
Learning Curve75

jsQR is a dependency-free JavaScript library for reading QR codes directly from raw pixel data. It takes an ImageData-shaped Uint8ClampedArray plus width and height, locates any QR code finder patterns in the frame, corrects for perspective and rotation, and decodes the underlying bytes into text, binary data, and structured chunks.

Because it has no platform-specific dependencies, jsQR runs anywhere JavaScript runs: browser webcam streams, uploaded images on a canvas, or image buffers inside a Node.js backend. Written in TypeScript and compiled to a single UMD bundle, it ships type definitions out of the box and can be dropped in via a script tag or imported as a module.

What You Get

  • A single jsQR(imageData, width, height, options?) function that returns decoded text, raw bytes, QR version, and chunk data, or null if no code is found
  • Automatic handling of both black-on-white and inverted (white-on-black) QR codes via configurable inversionAttempts
  • Location data for each finder pattern and corner, useful for drawing an overlay or bounding box around a detected code
  • TypeScript type definitions bundled with the package, plus a pre-built UMD bundle (dist/jsQR.js) for direct <script> tag use
  • Zero runtime dependencies and no platform-specific code, so the same function works in a browser, a web worker, or Node.js

Common Use Cases

  • Scanning a live webcam or mobile camera stream in the browser to read QR codes for check-in, payment, or login flows
  • Decoding QR codes from user-uploaded images (e.g. a photo of a ticket or product label) without a server round trip
  • Server-side QR decoding in a Node.js pipeline, such as validating codes embedded in generated PDFs or scanned documents
  • Building custom scanning UIs (React/Vue components, PWAs) that need full control over the camera feed and canvas frame extraction

Under The Hood

Architecture jsQR follows a four-stage pipeline mirrored directly in its module layout: src/binarizer converts raw RGBA pixel data into a black/white BitMatrix (with an inverted variant for white-on-black codes), src/locator scans that matrix for the three finder patterns and computes the perspective transform needed to map a skewed or rotated code onto a square grid, src/extractor applies that transform to pull out the aligned module grid plus a coordinate-mapping function used to report corner locations, and src/decoder (with decoder.ts, decodeData/, and reedsolomon/) reads format/version info, applies the correct data mask, runs Reed-Solomon error correction, and parses the resulting bytes into text, binary data, and structured chunks. src/index.ts composes these four stages in a single scan() function, trying multiple candidate locations returned by the locator until one decodes successfully, then wraps the whole flow in the public jsQR() entry point that handles the inversionAttempts option by running scan() against the normal and/or inverted bitmap.

Tech Stack The library is written in TypeScript targeting ES5 (per tsconfig.json) with no runtime dependencies at all, keeping the compiled UMD bundle self-contained for both browser <script> tag use and Node.js require. Builds go through Webpack 3 with awesome-typescript-loader, linting via tslint, and tests via jest with ts-jest; these are dev-era tools reflecting the project’s 2015 origin, but they don’t affect the shipped artifact, which is just the compiled dist/jsQR.js plus bundled .d.ts type definitions.

Code Quality Each core module ships its own test.ts alongside a test-data/ fixture directory (src/locator/test-data, src/extractor/test-data, plus decoder-level test fixtures), and the end-to-end suite in tests/end-to-end/ runs the full pipeline against several hundred real QR code images with a generated report.json tracking pass/fail per image — a notably rigorous approach for a small library. However, there is no CI workflow in .github/, so these tests aren’t automatically enforced on every push or PR, and commit activity has slowed substantially in recent years, meaning regressions in edge-case image handling could go unnoticed for a while.

API Design The public API is deliberately minimal: a single default-exported function, jsQR(imageData, width, height, options?), that returns a fully-typed result object or null. This is easy to learn (documented clearly in the README, with argument shapes and a linked live demo) and easy to embed anywhere a Uint8ClampedArray of pixels is available. The tradeoff is that it stays low-level by design: there’s no built-in webcam/canvas helper, no Promise-based or streaming API, and callers must handle frame capture and ImageData extraction themselves, which is appropriate for a focused decoding primitive but adds a small amount of boilerplate for the common webcam-scanning use case.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search