The qr-image, qr.js, qrcode, qrious, react-qr-code, and uqr packages are all JavaScript libraries designed to generate QR codes, but they serve different architectural needs ranging from backend image generation to frontend React components. qr-image and qrcode are robust, general-purpose libraries often used in Node.js environments to produce image buffers or SVG strings. qrious and uqr focus on client-side rendering, with qrious utilizing the HTML5 Canvas API for dynamic manipulation and uqr offering a modern, lightweight alternative. qr.js is a legacy library that is no longer maintained, while react-qr-code provides a specialized React component wrapper to simplify integration in frontend applications without managing low-level rendering logic.
When adding QR code functionality to a web application, the choice of library depends heavily on your execution environment (Node.js vs. Browser), your required output format (Image buffer, SVG, Canvas), and your framework (React vs. Vanilla JS). Let's break down how these six packages tackle the core challenges of QR generation.
The most critical architectural decision is what form the QR code takes after generation. Some libraries produce binary data for servers, while others draw directly to the browser screen.
qr-image is designed for Node.js and produces binary image buffers or SVG strings. It does not render to the screen but returns data you can save to a file or send over a network.
// qr-image: Generate a PNG buffer in Node.js
const qr = require('qr-image');
const pngBuffer = qr.imageSync('https://example.com', { type: 'png' });
// pngBuffer is a Node.js Buffer object ready for fs.writeFile
qrcode is highly versatile, supporting UTF8 text output for terminals, SVG strings, and Canvas drawing depending on the method called.
// qrcode: Generate an SVG string
const QRCode = require('qrcode');
const svgString = await QRCode.toString('https://example.com', { type: 'svg' });
// svgString contains the raw <svg>...</svg> markup
qrious renders directly to an HTML5 Canvas element in the browser. It does not return a buffer; instead, it paints pixels onto a DOM element.
// qrious: Draw to a canvas element
const qr = new QRious({
element: document.getElementById('qr-canvas'),
value: 'https://example.com'
});
// The library automatically draws the QR code onto the canvas element
uqr focuses on generating clean SVG strings efficiently, suitable for both browser and Node environments without heavy dependencies.
// uqr: Generate SVG asynchronously
import { toSVG } from 'uqr';
const svgContent = await toSVG('https://example.com');
// svgContent is a string containing the SVG markup
react-qr-code abstracts the rendering entirely, outputting an SVG-based React component that integrates directly into your JSX tree.
// react-qr-code: Render as a React Component
import QRCode from 'react-qr-code';
function MyComponent() {
return <QRCode value="https://example.com" />;
}
// Renders an <svg> element directly in the React DOM
qr.js (Legacy) historically provided canvas rendering but lacks the modern API consistency of qrious or qrcode.
// qr.js: Legacy canvas approach (Not Recommended)
var qr = new QRCode(document.getElementById('qrcode'), {
text: "https://example.com"
});
// Directly manipulates the DOM element passed in
Developers often need to adjust error correction levels, colors, or margins. The API design for these configurations varies significantly between class-based and functional approaches.
qr-image uses a simple options object passed to the generation function, focusing mainly on image types and margins.
// qr-image: Options for margin and type
const options = { type: 'png', margin: 2, ecLevel: 'H' };
const buffer = qr.imageSync('data', options);
qrcode offers a rich configuration object allowing deep customization of colors, margins, and error correction levels.
// qrcode: Detailed customization
await QRCode.toCanvas(canvas, 'text', {
width: 256,
margin: 2,
color: {
dark: '#000000',
light: '#ffffff'
},
errorCorrectionLevel: 'H'
});
qrious uses a constructor-based pattern where properties are set during instantiation or via chainable setters.
// qrious: Chainable configuration
const qr = new QRious({
element: document.getElementById('canvas'),
value: 'text',
size: 200,
foreground: '#000000',
background: '#ffffff',
level: 'H'
});
uqr employs a functional API where options are passed as the second argument to the generator function.
// uqr: Functional options
const svg = await toSVG('text', {
size: 200,
margin: 1,
color: '#000000'
});
react-qr-code exposes configuration as standard React props, making it intuitive for frontend developers.
// react-qr-code: Props-based configuration
<QRCode
value="text"
size={256}
level="H"
bgColor="#ffffff"
fgColor="#000000"
/>
Choosing the wrong library for your environment can lead to build errors or missing dependencies like canvas or jsdom.
qr-image is strictly a Node.js library. It relies on native buffer handling and will not work in a browser environment without complex polyfills.
// qr-image: Node.js only
// Will fail in browser: require('fs') or Buffer usage
const qr = require('qr-image');
qrcode is isomorphic. It detects the environment and uses native Canvas APIs in the browser or the canvas package in Node.js.
// qrcode: Works everywhere
// In browser: uses <canvas>
// In Node: uses 'canvas' dependency if installed
QRCode.toDataURL('text');
qrious is browser-first. It requires a DOM element to render and is not designed for server-side image generation.
// qrious: Browser only
// Requires document.getElementById to exist
const qr = new QRious({ element: document.getElementById('c') });
uqr is designed to be lightweight and environment-agnostic for SVG generation, making it safe for both server and client.
// uqr: Universal SVG generation
// No heavy DOM dependencies required for string output
const svg = await toSVG('text');
react-qr-code is obviously React-specific, running in the browser or during server-side rendering (SSR) in React frameworks.
// react-qr-code: React ecosystem only
// Requires React to be installed
return <QRCode value="text" />;
Using unmaintained libraries introduces security risks and compatibility issues with modern build tools.
qr.js is deprecated. The repository has not seen significant updates in years, and it lacks support for modern module systems (ESM) and recent browser security policies. You should explicitly avoid this in new projects.
// qr.js: DEPRECATED
// Do not use. Switch to 'qrcode' or 'qrious' for active support.
var qr = new QRCode(...);
All other libraries (qr-image, qrcode, qrious, react-qr-code, uqr) are currently maintained and receive updates for bug fixes and dependency upgrades.
| Package | Primary Environment | Output Type | React Ready | Status |
|---|---|---|---|---|
qr-image | Node.js | Buffer / SVG String | β | Active |
qr.js | Browser | Canvas | β | Deprecated |
qrcode | Universal | Canvas / SVG / UTF8 | β (Helper needed) | Active |
qrious | Browser | Canvas | β (Wrapper needed) | Active |
react-qr-code | React | SVG Component | β | Active |
uqr | Universal | SVG String | β (Wrapper needed) | Active |
qrcode is the safest bet for full-stack developers who need one library to handle both server-side buffer generation and client-side rendering. It is the "Swiss Army Knife" of the group.
react-qr-code is the definitive choice for React teams. It removes the boilerplate of managing refs and canvas contexts, letting you treat QR codes like any other UI component.
qr-image remains the specialist for backend-heavy workflows where you need to email QR codes or save them to disk as PNGs without spinning up a headless browser.
qrious and uqr serve specific niches: qrious for dynamic, interactive canvas manipulation in the browser, and uqr for lightweight, modern SVG generation.
Final Thought: Avoid qr.js entirely. For most modern web apps, start with react-qr-code if you use React, or qrcode if you need maximum flexibility across different environments.
Choose qr-image if you are working in a Node.js environment and need to generate QR codes as image buffers (PNG, SVG, EPS) for file storage or email attachments. It is ideal for backend services where you need reliable, synchronous-like generation of standard image formats without relying on browser APIs.
Do NOT choose qr.js for any new project. This library is deprecated and unmaintained, lacking support for modern JavaScript standards and containing known issues that have been resolved in newer alternatives like qrcode or qrious.
Choose qrcode if you need a versatile, industry-standard library that works seamlessly in both Node.js and browser environments. It is the best choice when you require support for multiple output formats (UTF8 text, Canvas, SVG, Terminal) and need a mature API with extensive configuration options for error correction and masking.
Choose qrious if your application runs entirely in the browser and requires dynamic, client-side manipulation of the QR code via the HTML5 Canvas API. It is perfect for scenarios where users need to download the image directly or where the QR code content changes frequently based on user interaction without server round-trips.
Choose react-qr-code if you are building a React application and want a drop-in component that handles the rendering logic for you. It is the most efficient choice for frontend developers who need to display QR codes quickly without worrying about Canvas contexts, SVG generation, or managing library lifecycle methods manually.
Choose uqr if you are looking for a modern, lightweight, and dependency-free library specifically optimized for generating SVG QR codes in the browser or Node.js. It is suitable for projects where bundle size is a critical concern and you prefer a functional, promise-based API over class-based instantiation.
This is yet another QR Code generator.
png, svg, eps and pdf formats;npm install qr-image
Example:
var qr = require('qr-image');
var qr_svg = qr.image('I love QR!', { type: 'svg' });
qr_svg.pipe(require('fs').createWriteStream('i_love_qr.svg'));
var svg_string = qr.imageSync('I love QR!', { type: 'svg' });
qr = require('qr-image')
qr.image(text, [ec_level | options]) β Readable stream with image data;qr.imageSync(text, [ec_level | options]) β string with image data. (Buffer for png);qr.svgObject(text, [ec_level | options]) β object with SVG path and size;qr.matrix(text, [ec_level]) β 2D array.text β text to encode;ec_level β error correction level. One of L, M, Q, H. Default M.options β image options object:
ec_level β default M.type β image type. Possible values png (default), svg, pdf and eps.size (png and svg only) β size of one module in pixels. Default 5 for png and undefined for svg.margin β white space around QR image in modules. Default 4 for png and 1 for others.customize (only png) β function to customize qr bitmap before encoding to PNG.parse_url (experimental, default false) β try to optimize QR-code for URLs.zlib.deflateSync instead of pako.