How to Build a QR Code Generator and Reader Using JavaScript (Complete Guide)

Build a QR Code Generator and Reader

QR codes are used everywhere. From booking event tickets, online payments, and accessing Wi-Fi to product packaging. Scanning a QR code and quickly opening a website or verifying a plane ticket. No time wasted 🕓.

Hi, I am Subha Naskar. In this guide, you'll learn how to build a QR code generator and reader using JavaScript. Here, we'll focus on using navigator to access the webcam.

At the end, you will have an idea for creating an HTML file, that can do the following:

  • Generate a QR code from any text, URL, or structured data.
  • Read a QR code from an uploaded image.
  • Read a QR code directly from your device camera.

There will be no heavy frameworks, no complex methods, and no backend. But we'll dive deep into every concept. So stay tuned with me.

Table of Contents

What is a QR Code and How It Work?

Before writing any code, let’s look at how QR codes work.

The year was 1994. At a Toyota factory in Japan, workers spent their days scanning barcodes on car parts. But the barcode had some issues. For example, a barcode stores a small amount of information. Scanning barcodes took time, which slowed down the work.

At that time, an engineer named Masahiro Hara worked at Denso Wave. He was tasked with solving this issue.

QR Code idea

One day, Masahiro was playing a Japanese board game. Masahiro noticed the black and white patterns on the board. That moment gave birth to the QR code.

What's inside a QR code?

Each part of a QR code has a purpose. The three large squares in the corners are finder patterns. They help the scanner detect position. There is a quiet zone around the code, which separates from other content.

anatomy of qr codes

The timing pattern helps scanners map the grid. There are also some metadata preservation patterns such as format and version.

Large QR code also include alignment patterns. These patterns fix distortion caused by camera angles. Other cells contain the actual data and error correction bits.

Inspiration of Creating QR Codes

There are many open-source libraries for QR code available on GitHub. These libraries will generate and decode the QR code for you. If you generate a QR code without using a library, the process becomes more complex. But it's not impossible.

If you'd like, you can check out the "Develop a QR Code Generator" blog posts by Massimo Artizzu. He shared amazing posts for understand QR code. Otherwise, if you are a beginner, I recommend using the library.

Why Build a Browser-Based Tool?

Many tool websites send user data to a remote API to generate QR codes, such as quickchart.io. However, this method has some issues.

  • Privacy: If users don't want to share data.
  • Speed: Requests on a slow network take time to complete.
  • Offline use: The app won't work without internet.
  • API limit: More users can mean API limits.

Running everything in the browser reduces the load on the server. However, the only problem with browser-based QR code generator tools is dependent on the user's device.

Project setup: No Dependencies

We'll create everything in one index.html file. You can choose any file name you like. There's no need for npm install, or no webpack.

Only two CDN scripts:

  • QRCode:- for generating QR codes.
  • jsQR:- for decoding QR codes from image.

Both libraries are open source. Their total size is under 50 KB zipped.

Creating the HTML Structure

Start with a main structure:

<main>
  <h1>QR Code Tool</h1>
  <!-- Generator UI -->
  <!-- Reader UI -->
</main>
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js"></script>
<script>
  // Our JavaScript code will go here
</script>

Building the QR Code Generator

We'll first creating a QR code generator.

Introducing the QRCode Library

The node-qrcode library has many methods:

  • QRCode.toCanvas():- Renders a <canvas> element.
  • QRCode.toDataURL():- Returns a base64-encoded image.
  • QRCode.toString():- Outputs a string of SVG.

Step by Step Implementation

Add the following HTML inside <main>:

<section class="generator">
  <h2>Generate QR Code</h2>
  <input type="text" id="qrInput" placeholder="Enter text or URL">
  <button onclick="generateQRCode()">Generate</button>
  <img id="qrImage" style="display: none;" alt="Generated QR code"/>
</section>

Now the JavaScript for QR Generation:

const qrInput = document.getElementById('qrInput');
const qrImage = document.getElementById('qrImage');

function generateQRCode() {
  const text = qrInput.value.trim();
  if (text === '') {
    alert('Please enter some text or a URL.');
    return;
  }

  QRCode.toDataURL(text, { width: 250, margin: 2 }, (err, url) => {
    if (err) {
      console.error(err);
      alert('Failed to generate QR code.');
      return;
    }
    qrImage.src = url;
    qrImage.style.display = "block";
  });
}

Here’s a breakdown of the code

  • QRCode.toDataURL() accepts the input string.
  • The callback receives the base64 image URL.
  • We set that URL as the src of the <img> tag.

Congratulation 🎉. You have a fully functional QR code generator.

Customising Appearance (Size, Colour, Margin)

Here's a better version with custom colors and error correction:

const options = {
  width: 300,
  margin: 4,
  color: {
    dark: '#1a4d8c',   // deep blue
    light: '#ffffff'   // white background
  },
  errorCorrectionLevel: 'H'  // up to 30% damage resistant
};

QRCode.toDataURL(text, options, callback);

You can also create a QR code directly on a <canvas> for more control.

Building the QR Code Reader from Image Upload

Here, we'll use the jsQR library to decode QR codes.

How jsQR Works Behind the Scenes

jsQR scans for QR code patterns. It does not depend on canvas or external image processing servers. The library works as follows:

  1. Converts the image to greyscale.
  2. Looks for the position patterns.
  3. Identifies the QR code format.
  4. Extracts the bit matrix.
  5. Decodes the message.

Implementation for File Upload

Add this HTML:

<section class="reader">
  <h2>Read QR Code from Image</h2>
  <input type="file" id="qrUpload" accept="image/*">
  <div id="readResult">See the result.</div>
</section>

Add a hidden <canvas> element. We'll use it to draw the uploaded image.

<canvas id="hiddenCanvas" style="display: none;"></canvas>

Now the JavaScript for QR Code Read:

const qrUpload = document.getElementById('qrUpload');
const readResult = document.getElementById('readResult');
const hiddenCanvas = document.getElementById('hiddenCanvas');
const ctx = hiddenCanvas.getContext('2d');

qrUpload.addEventListener('change', (event) => {
  const file = event.target.files[0];
  if (!file) return;

  readResult.textContent = 'Decoding image...';
  const img = new Image();
  img.onload = () => {
    hiddenCanvas.width = img.width;
    hiddenCanvas.height = img.height;
    ctx.drawImage(img, 0, 0, img.width, img.height);
    const imageData = ctx.getImageData(0, 0, img.width, img.height);
    const qrCode = jsQR(imageData.data, imageData.width, imageData.height);
    if (qrCode) {
      readResult.textContent = `${escapeHtml(qrCode.data)}`;
    } else {
      alert('No QR code found in this image.');
    }
    URL.revokeObjectURL(img.src);
  };
  img.onerror = () => {
     alert('Failed to load image.');
  };
  img.src = URL.createObjectURL(file);
});

// XSS protection
function escapeHtml(str) {
  return str.replace(/[&<>]/g, function(m) {
    if (m === '&') return '&';
    if (m === '<') return '<';
    if (m === '>') return '>';
    return m;
  });
}

Here's an explanation of the QR code reader code.

  • URL.createObjectURL(file) creates a local URL for the uploaded image.
  • We draw that image on the hidden canvas. Then, we call ctx.getImageData() to get an ImageData object.
The QR code reader will require camera or file access.

Handling Large Images

The code works well for normal images. However, if a user uploads a height resolution image, getImageData() will use a lot of memory. This may cause browser crashes.

What is the solution? Resize the image before scanning. Set a maximum size, such as 800px.

img.onload = () => {
  let width = img.width;
  let height = img.height;
  const MAX_SIZE = 800;
  if (width > MAX_SIZE || height > MAX_SIZE) {
    if (width > height) {
      height = (height * MAX_SIZE) / width;
      width = MAX_SIZE;
    } else {
      width = (width * MAX_SIZE) / height;
      height = MAX_SIZE;
    }
  }
  hiddenCanvas.width = width;
  hiddenCanvas.height = height;
  ctx.drawImage(img, 0, 0, width, height);
  // ... rest same
};

This reduces processing time without affecting decoding result.

How to scan QR code using camera?

You can use the html5-qrcode library to scan QR codes directly from the device camera. It scans using the browser camera APIs.

Add the CDN:

<script src="https://unpkg.com/html5-qrcode@2.3.8/html5-qrcode.min.js"></script>

Add a container:

<section class="camera-reader">
  <h2>Live Scan (Camera)</h2>
  <div id="cameraScanner" style="width: 100%; max-width: 500px;"></div>
  <button id="startCameraBtn">Start Camera</button>
  <button id="stopCameraBtn" disabled>Stop Camera</button>
  <div id="cameraResult"></div>
</section>

Adding JavaScript for Live Camera:

let html5QrCode = null;
const startBtn = document.getElementById('startCameraBtn');
const stopBtn = document.getElementById('stopCameraBtn');
const cameraResult = document.getElementById('cameraResult');

startBtn.addEventListener('click', () => {
  html5QrCode = new Html5Qrcode("cameraScanner");
  const config = { fps: 10, qrbox: { width: 250, height: 250 } };
  html5QrCode.start(
    { facingMode: "environment" },
    config,
    (decodedText) => {
      cameraResult.textContent = `${escapeHtml(decodedText)}`;
    },
    (errorMessage) => {}
  ).then(() => {
    startBtn.disabled = true;
    stopBtn.disabled = false;
  }).catch(err => {
    console.error("Camera error", err);
    cameraResult.textContent = "Unable to access camera. Check permissions.";
  });
});

stopBtn.addEventListener('click', () => {
  if (html5QrCode) {
    html5QrCode.stop().then(() => {
      startBtn.disabled = false;
      stopBtn.disabled = true;
      cameraResult.textContent = "Camera stopped.";
    });
  }
});

Users can read any QR code with the camera.

How to Secure QR Code Scanner Feature?

Remove the old text before adding new text to the output. We have already used escapeHtml(). However, innerHTML should never be set to qrCode.data.

If your app redirects users after scanning a QR code, it’s a good idea to verify the URL. QR codes may contain links to misleading websites, so validating the URL helps improve user safety.

You can add User confirmation.

if (qrCode.data.startsWith('http://') || qrCode.data.startsWith('https://')) {
  if (confirm(`Redirect to ${qrCode.data}?`)) {
    window.location.href = qrCode.data;
  }
}

Always ask for user permission before redirecting mailto:, tel:, or sms: links.

How to Make the QR Code Tool Work Offline?

We used CDN scripts. So you need an internet connection to load the liberties. To create an offline tool, you can:

  • Download the library files and host them locally.
  • Use a service worker.

Use these tags in <head>:

<link rel="preconnect" href="https://cdn.jsdelivr.net"> 
<link rel="preload" href="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js" as="script"> 
<link rel="preload" href="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js" as="script">

How You Can Extend This Tool

The simple generator works for any text. So, you can create QR codes that start phone actions. For example:

  • vCard (MECARD or VCARD format)
  • WiFi login (WIFI:S:MyNetwork;T:WPA;P:MyPassword;;)
  • Calendar event (BEGIN:VEVENT...)

You don't need any extra code. Just pass the properly formatted string to the generator.

Here is an example of WiFi QR generation.

const wifiString = `WIFI:S:${ssid};T:${encryption};P:${password};;`;
QRCode.toDataURL(wifiString, options, callback);

Live Demo: How the QR Tools Works

Here, live demo to help you see how the QR Code Tools works. Click "Run Code" to see the QR Code Tools live.

1. QR Code Generator

Users enter the required input. For example, if they are providing a URL, they paste that link into the input field. Then click the generate button and the tool will create a QR code.

qr code generator

2. QR Code Reader

Users can upload a photo. The tool reads the QR code and displays the text.

qr code reader works

Next Step: Improvements you can add

Download as PNG/SVG

Add a button that saves the generated QR code.

History

Store previously generated texts in localStorage.

Batch generation

Accept a CSV file and generate multiple QR codes.

Custom Logo

Add a logo right in the middle of the QR code.

Conclusion

You've built a fully functional QR code generator and reader using JavaScript libraries. The tool works completely in the browser. It can be added to any web project.

What You Learned
  • node-qrcode help you to generate QR code.
  • jsQR decoding QR codes from images.
  • Resize large images.
  • Scanning QR codes with live camera.

Now improve your web applications with QR features. Enjoy every line you build QR tool.

Happy coding! See you next project!

Post a Comment

0 Comments