Skip to content

Render QR codes in the browser

Browser applications can render a QR code as an SVG string, a PNG-backed Image element, or a Canvas element. Choose the output for what the page needs to do next, then insert or compose the returned value with standard browser APIs.

Choose Package Return value Best fit
SVG @qrcodesdk/core string Scalable inline markup and the recommended browser default
Image @qrcodesdk/browser HTMLImageElement A familiar, accessible DOM image backed by PNG data
Canvas @qrcodesdk/browser HTMLCanvasElement Drawing, compositing, pixel access, or manual PNG export

Start with SVG unless the next browser API specifically needs an Image or Canvas element. SVG stays sharp when resized and does not require Canvas support. Image and Canvas output require both @qrcodesdk/core and @qrcodesdk/browser.

QRCodeSVGRenderer returns complete SVG markup. It is not a DOM node, so insert it into an existing element or pass it to the browser-side template system that owns the page.

Render into a container when the SVG should participate in the page as inline markup:

import {QRCodeSVGRenderer, qrcode} from '@qrcodesdk/core';
const svg = qrcode('https://qrcodesdk.dev').render(
QRCodeSVGRenderer({
ariaLabel: 'Scan to open qrcodesdk.dev',
}),
);
const container = document.querySelector('#qrcode');
if (container) {
container.innerHTML = svg;
}
<div id="qrcode"></div>

Only insert the string as HTML when the renderer and its options are inside your application’s trust boundary.

The returned string can be interpolated into HTML generated by a browser-side template:

import {QRCodeSVGRenderer, qrcode} from '@qrcodesdk/core';
const svg = qrcode('https://qrcodesdk.dev').render(
QRCodeSVGRenderer({
ariaLabel: 'Scan to open qrcodesdk.dev',
}),
);
const html = `
<section>
<h2>Scan this QR code</h2>
${svg}
</section>
`;

Apply layout styles to the inserted root SVG through its container:

#qrcode > svg {
display: block;
width: min(100%, 20rem);
height: auto;
}

QRCodeImageRenderer synchronously returns a new HTMLImageElement whose src contains the rendered PNG as a data URL. Use it when the QR code should behave like an ordinary image in the DOM.

The returned value is already an HTMLImageElement, so it can be appended and styled like any other image:

import {QRCodeImageRenderer} from '@qrcodesdk/browser';
import {qrcode} from '@qrcodesdk/core';
const image = qrcode('https://qrcodesdk.dev').render(
QRCodeImageRenderer({
alt: 'QR code for qrcodesdk.dev',
ariaLabel: 'Scan to open qrcodesdk.dev',
title: 'QR code for qrcodesdk.dev',
}),
);
image.className = 'qrcode';
document.querySelector('#qrcode')?.append(image);
<div id="qrcode"></div>
.qrcode {
display: block;
width: min(100%, 20rem);
height: auto;
}

Read src when another browser API needs the encoded PNG rather than the element:

import {QRCodeImageRenderer} from '@qrcodesdk/browser';
import {qrcode} from '@qrcodesdk/core';
const image = qrcode('https://qrcodesdk.dev').render(QRCodeImageRenderer());
const response = await fetch(image.src);
const png = await response.blob();
await navigator.clipboard.write([
new ClipboardItem({
'image/png': png,
}),
]);

The Clipboard API requires a secure context and may require a user gesture or permission.

QRCodeCanvasRenderer synchronously returns a new HTMLCanvasElement. Use Canvas when code needs to draw onto the output, combine it with other graphics, inspect pixels, or export it manually.

Give the Canvas its own accessible name, then append it wherever the QR code should appear:

import {QRCodeCanvasRenderer} from '@qrcodesdk/browser';
import {qrcode} from '@qrcodesdk/core';
const canvas = qrcode('https://qrcodesdk.dev').render(QRCodeCanvasRenderer({size: 8, margin: 4}));
canvas.setAttribute('role', 'img');
canvas.setAttribute('aria-label', 'Scan to open qrcodesdk.dev');
document.querySelector('#qrcode')?.append(canvas);
<div id="qrcode"></div>

Use the QR Canvas as a source for a larger composition:

import {QRCodeCanvasRenderer} from '@qrcodesdk/browser';
import {qrcode} from '@qrcodesdk/core';
const qrCanvas = qrcode('https://qrcodesdk.dev').render(QRCodeCanvasRenderer());
const target = document.querySelector<HTMLCanvasElement>('#target');
const context = target?.getContext('2d');
if (target && context) {
target.width = qrCanvas.width;
target.height = qrCanvas.height;
context.drawImage(qrCanvas, 0, 0);
}

Each render creates a new string or element. When the payload changes, render again and replace the old output so the container does not accumulate QR codes:

import {QRCodeImageRenderer} from '@qrcodesdk/browser';
import {qrcode} from '@qrcodesdk/core';
const container = document.querySelector('#qrcode');
export function updateQRCode(data: string) {
const image = qrcode(data).render(
QRCodeImageRenderer({alt: '', ariaLabel: `Scan to open ${data}`}),
);
container?.replaceChildren(image);
}

If application state changes frequently, avoid recreating output for unrelated updates. Framework users can instead use the React, Vue, Svelte, or Angular components, which integrate rendering with their normal component lifecycle.

  • Keep the default four-module margin clear of nearby text, borders, and other UI.
  • Give meaningful SVG, Image or Canvas output an accessible label.
  • Use CSS to shrink output responsively, but do not enlarge Image or Canvas output beyond its rendered pixel dimensions. Increase the renderer’s size when more raster resolution is needed.
  • Scan-test the final page at its smallest supported viewport and after any CSS transforms, browser zoom, screenshots, or image compression.

The QR code now uses the browser output that matches its next operation and is mounted with normal DOM APIs. Follow Customize appearance for shared visual options, Add a center image for prepared image sources, or Download or save to turn the output into a file.