qr-image vs qrcode
QR Codes Generator in Web Apps
qr-imageqrcodeSimilar Packages:
QR Codes Generator in Web Apps

qr-image and qrcode are both npm packages used to generate QR codes in JavaScript environments, but they differ significantly in architecture, output formats, and runtime compatibility. qr-image is a Node.js-focused library that generates QR codes as image streams (PNG, SVG, EPS, PDF) using server-side APIs like Streams and Buffers. qrcode, by contrast, is a universal library designed to work consistently across both browser and Node.js environments, supporting canvas, data URLs, terminal output, and UTF-8 text rendering without relying on Node-specific constructs.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
qr-image01,064-159 years agoMIT
qrcode08,041135 kB114a year agoMIT

qr-image vs qrcode: Choosing the Right QR Code Generator for Your Stack

Both qr-image and qrcode solve the same basic problem — generating QR codes from strings — but their internal designs, supported environments, and output capabilities diverge sharply. Understanding these differences is crucial when building anything from a simple marketing site to a complex full-stack application.

🖼️ Output Formats and Rendering Targets

qr-image produces QR codes exclusively as image streams or buffers, targeting file-based outputs:

  • PNG (via png-js)
  • SVG
  • EPS
  • PDF

It uses Node.js Streams under the hood, so every render returns a ReadableStream or Buffer. This makes it ideal for writing QR codes directly to disk or piping into HTTP responses on the server.

// qr-image: Node.js-only stream output
const qr = require('qr-image');
const fs = require('fs');

const qrStream = qr.image('https://example.com', { type: 'png' });
qrStream.pipe(fs.createWriteStream('qrcode.png'));

qrcode supports multiple rendering strategies tailored to different environments:

  • <canvas> element (browser)
  • Data URL strings (browser or Node.js)
  • Terminal/ASCII output (CLI tools)
  • UTF-8 text blocks (lightweight fallback)
  • Raw byte arrays (for custom encoders)

This flexibility means you can embed a QR code directly in an HTML page without touching the filesystem.

// qrcode: Browser-friendly canvas rendering
import QRCode from 'qrcode';

QRCode.toCanvas(document.getElementById('qrcode'), 'https://example.com', (error) => {
  if (error) console.error(error);
});

🌐 Runtime Compatibility: Node.js vs Universal

qr-image depends heavily on Node.js built-ins like stream, buffer, and zlib. It will fail immediately in browser environments because these modules don’t exist outside Node.js. Even with bundlers like Webpack, polyfilling these dependencies adds unnecessary bloat and complexity.

// This breaks in the browser
import qr from 'qr-image'; // ❌ ReferenceError: stream is not defined

qrcode is written to be runtime-agnostic. It avoids Node-specific APIs entirely and detects available features at runtime (e.g., HTMLCanvasElement in browsers, process.stdout in terminals). This makes it safe to use in React, Vue, Svelte, Electron, Cloudflare Workers, or plain Node.js — all with the same API.

// Works everywhere
import QRCode from 'qrcode';

// In browser
QRCode.toDataURL('hello', (err, url) => {
  document.getElementById('img').src = url;
});

// In Node.js
QRCode.toString('hello', { type: 'terminal' }, (err, qrcode) => {
  console.log(qrcode);
});

⚙️ API Design and Error Handling

qr-image uses a synchronous/streaming model with minimal error handling. Invalid input usually throws an exception, and there’s no callback or Promise interface. You’re expected to manage streams manually.

// qr-image: No async support, just streams
try {
  const svg = qr.imageSync('data', { type: 'svg' }); // Returns Buffer
} catch (e) {
  // Handle error
}

qrcode provides consistent async/sync variants for every method (toCanvas, toString, toDataURL, etc.), with optional callback or Promise support. Errors are passed explicitly rather than thrown, making integration with modern async patterns straightforward.

// qrcode: Flexible async handling
const url = await QRCode.toDataURL('hello');
// or
QRCode.toDataURL('hello', (err, url) => { /*...*/ });

🧪 Maintenance and Future-Proofing

While neither package is officially deprecated, qr-image has seen minimal updates in recent years and lacks support for newer QR code standards (like Micro QR or structured append). Its reliance on outdated stream patterns also makes it feel increasingly out of step with modern Node.js practices.

qrcode, on the other hand, receives regular updates, supports UTF-8 mode for compact text rendering, and actively addresses edge cases (e.g., very long URLs, special characters). Its test suite covers both browser and Node environments thoroughly.

🔁 Real-World Usage Scenarios

Generating a Downloadable QR Code on the Server

If you’re building an Express route that serves QR code images:

  • With qr-image:

    app.get('/qr.png', (req, res) => {
      res.type('png');
      qr.image(req.query.text, { type: 'png' }).pipe(res);
    });
    
  • With qrcode:

    app.get('/qr.png', async (req, res) => {
      const buffer = await QRCode.toBuffer(req.query.text);
      res.type('png').send(buffer);
    });
    

Both work, but qrcode gives you a clean Buffer without stream plumbing.

Embedding a QR Code in a React Component

Only qrcode works here:

import { useEffect, useRef } from 'react';
import QRCode from 'qrcode';

function QrComponent({ value }) {
  const canvasRef = useRef();

  useEffect(() => {
    QRCode.toCanvas(canvasRef.current, value);
  }, [value]);

  return <canvas ref={canvasRef} />;
}

Trying this with qr-image would crash the app.

✅ When They Overlap

Despite their differences, both libraries:

  • Use the same underlying QR code algorithm (based on the ISO/IEC 18004 standard)
  • Support common error correction levels (L, M, Q, H)
  • Allow configuration of margin size and module size
  • Encode UTF-8 strings correctly (though qr-image may require manual encoding in some cases)
// Both support error correction
qr.image('text', { ec_level: 'H' });          // qr-image
QRCode.toDataURL('text', { errorCorrectionLevel: 'H' }); // qrcode

🆚 Summary: Key Differences

Featureqr-imageqrcode
Browser Support❌ No✅ Yes
Output Types🖼️ PNG/SVG/EPS/PDF (streams)🖼️ Canvas / Data URL / Terminal / UTF-8
Runtime🖥️ Node.js only🌍 Universal (browser + Node)
API Style📦 Stream-based, sync-only⏳ Async/sync, callback or Promise
Maintenance🕒 Low activity🔁 Actively maintained
Use Case Fit🖨️ Server file generation only🧩 Anywhere QR codes are needed

💡 Final Recommendation

For new projects, default to qrcode. Its universal compatibility, modern API, and active maintenance make it the clear choice for almost every scenario — whether you’re building a static site, a React SPA, a CLI tool, or a server-rendered app.

Reserve qr-image only for legacy Node.js systems where you’re already deeply invested in stream pipelines and have no browser requirements. Even then, consider migrating to qrcode for future-proofing.

In short: if your code might ever touch a browser — even indirectly — skip qr-image entirely.

How to Choose: qr-image vs qrcode
  • qr-image:

    Choose qr-image only if you're working in a pure Node.js backend environment and need to generate QR codes as downloadable image files (especially PNG or SVG) using Streams or Buffers. It’s a good fit for server-rendered reports or file exports where you don’t need browser compatibility. However, avoid it for any frontend or isomorphic use case—it won’t work in the browser and hasn’t seen active maintenance in recent years.

  • qrcode:

    Choose qrcode when you need reliable QR code generation across both frontend and backend contexts. It supports canvas rendering for web apps, data URLs for inline embedding, terminal output for CLI tools, and UTF-8 fallbacks for low-dependency environments. Its consistent API and lack of Node.js-specific dependencies make it the safer, more versatile choice for modern full-stack or client-side applications.

README for qr-image

qr-image

npm version

This is yet another QR Code generator.

Overview

  • No dependecies;
  • generate image in png, svg, eps and pdf formats;
  • numeric and alphanumeric modes;
  • support UTF-8.

Releases

Installing

npm install qr-image

Usage

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' });

More examples

qr = require('qr-image')

Methods

  • 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.

Options

  • 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.

Changes

  • Use zlib.deflateSync instead of pako.
  • Fix deprecation warning for NodeJS 7.

TODO

  • Tests;
  • mixing modes;
  • Kanji (???).